Intro

In this post I will cover how to create an Arista Vagrant box for use with the vagrant-libvirt provider. This post assumes a working installation of Vagrant with the vagrant-libvirt plugin already installed. You can follow this post to get the vagrant-libvirt plugin installed.

Note

I originally covered this topic in November 2017. I have learned alot of lessons since then so this is a revamp of that previous post.

For reference the following software will be used in this post.

  • EOS - vEOS-lab-4.20.1F-combined.vmdk
  • Vagrant - Vagrant 2.0.1
  • vagrant-libvirt - 0.0.43

Download

Arista does not provide a Vagrant Libvirt box like they do for the Virtualbox provider, so we will need to download the vmdk from the Arista software download page. An account is required to download the software but, it's free to register and no support contract is required.

Once you have logged in download the vEOS-lab-4.20.1F-combined.vmdk image from the vEOS-lab section. This image combines the boot image and has the necessary drivers installed to work in virtual environments.

Install

Create and change into directory for veos files. I like to keep my custom vagrant boxes under ~/vagrant/boxes/ .

cmd
mkdir -p ~/vagrant/boxes/arista/
cd ~/vagrant/boxes/arista/

Copy the veos files downloaded earlier to the ~/vagrant/boxes/arista/ directory.

cmd
cp ~/Downloads/vEOS-lab-4.20.1F-combined.vmdk .

The good folks who maintain the vagrant-libvirt plugin have a script can be used to convert qcow2 images to a vagrant box. Download the libvirt convertsion script.

cmd
curl -O https://raw.githubusercontent.com/vagrant-libvirt/vagrant-libvirt/master/tools/create_box.sh

Convert the vmdk disk to the qcow2 format for use with KVM.

cmd
qemu-img convert -f vmdk -O qcow2 vEOS-lab-4.20.1F-combined.vmdk vEOS-lab-4.20.1F-combined.qcow2

Launch the Arista veos VM in order to apply a bootstrap config to it that allows Vagrant to login and manage the box.

cmd
virt-install \
    --connect=qemu:///system \
    --name=veos \
    --os-type=linux \
    --arch=x86_64 \
    --cpu host \
    --vcpus=2 \
    --hvm \
    --ram=2048 \
    --disk path=vEOS-lab-4.20.1F-combined.qcow2,bus=ide,format=qcow2 \
    --network=network:vagrant-libvirt,model=virtio \
    --graphics none \
    --import

Conenct to the console to apply the bootstrap configuration.

cmd
virsh console veos

# output

Connected to domain veos
Escape character is ^]
Switching rootfs

Welcome to Arista Networks EOS 4.20.1F
New seat seat0.
[  OK  ] ConnMgr: Starting TimeAgent: [  OK  ]
Cannot find initial response [FAILED]
Starting ProcMgr: [  OK  ]
Starting EOS initialization stage 1: [   47.644196] NMI watchdog: failed to be enabled on some cpus
[  OK  ]
Starting NorCal initialization: [  OK  ]
Starting EOS initialization stage 2: [  OK  ]
Starting Power On Self Test (POST): [  OK  ]
Completing EOS initialization (press ESC to skip): [  OK  ]
Model and Serial Number: unknown
System RAM: 1893320 kB
Flash Memory size:  3.8G

localhost login:

Login with the username admin (no password) and apply bootstrap configuration.

cmd
!
conf t
!
aaa authorization exec default local
!
no aaa root
!
username vagrant privilege 15 shell /bin/bash secret sha512 $6$3kgdKcJLJ3j/0N51$a0YshIzKL3xtdwP6XXXRlY9B8yHFK/tLdg0I95YUIaW7oHqLsgK9TxMg8/0bL6VDkImuWT.g7WRKTxi8nNPtA1
username vagrant sshkey ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key
!
interface Management1
   ip address dhcp
!
no ip routing
!
management api http-commands
   no shutdown
!
end
wr mem
!

This configuration allows Vagrant to assign an IP address to the management interface via DHCP and to also ssh to the guest using ssh keys.

Check IP address assigned via DHCP.

cmd
show ip int brie

# output

Interface              IP Address         Status     Protocol         MTU
Management1            192.168.121.173/24 up         up              1500

From your host terminal confirm you can SSH to the Arista VM with the vagrant ssh key. You will be placed in the /bin/bash shell, use the FastCli command to change to the Arista eos CLI.

cmd
# host terminal

ssh vagrant@192.168.121.173 -i ~/.vagrant.d/insecure_private_key

# now in arista VM

[vagrant@localhost ~]$ FastCli

localhost#show version
Arista vEOS
Hardware version:
Serial number:
System MAC address:  5254.004b.5f79

Software image version: 4.20.1F
Architecture:           i386
Internal build version: 4.20.1F-6820520.4201F
Internal build ID:      790a11e8-5aaf-4be7-a11a-e61795d05b91

Uptime:                 6 minutes
Total memory:           1893320 kB
Free memory:            867428 kB

localhost#

Once logged in apply the following additional config to activate a couple of event handlers.

cmd
!
conf t
!
event-handler ALTER-VAGRANT-SHELL
   trigger on-intf Management0 ip
   action bash sudo sed -i 's:^username vagrant privilege 15 shell /bin/bash :username vagrant privilege 15 :g' /mnt/flash/startup-config
   delay 60
!
event-handler COPY-STARTUP-TO-RUNNING
   trigger on-intf Management0 ip
   action bash FastCli -p 15 -c 'configure replace startup-config'
   delay 70
!
end
wr mem
!

The first handler ALTER-VAGRANT-SHELL removes the /bin/bash argument from the vagrant users login shell. Having the default prompt set to /bin/bash allows Vagrant to login and perform guest OS detection when the hosts boots up without spitting back any errors.

The second handler COPY-STARTUP-TO-RUNNING applies the change to the running config. That way when you login to the guest with the vagrant ssh command you are placed into the Arista eos CLI rather than a /bin/bash shell.

If you successfully connected and applied the additional event handler config power off the VM.

cmd
bash sudo poweroff

# output

Flushing AAA accounting queue: [  OK  ]
.
. <snip>
.
Storage is finalized.
[  763.709085] System halted.

To exit the console use one of these key combinations (Assuming English keyboard).

  • CTRL + ]
  • CTRL + 5
  • Press and hold CTRL and SHIFT while pressing 6 then ]

Even though the eos software is shutdown the VM is still powered on, so poweroff the VM.

cmd
virsh destroy veos

# output

Domain veos destroyed

Create a file called metadata.json with the following contents.

file
{"provider":"libvirt","format":"qcow2","virtual_size":4}

Use the previously downloaded script create_box.sh to create a vagrant box.

cmd
bash create_box.sh vEOS-lab-4.20.1F-combined.qcow2

# output

{4}
==> Creating box, tarring and gzipping
./metadata.json
./Vagrantfile
./box.img
Total bytes written: 619786240 (592MiB, 35MiB/s)
==> box.box created
==> You can now add the box:
==>   'vagrant box add vEOS-lab-4.20.1F-combined.box --name box'

Create a metadata file called veos.json so that the box is added with the correct version number.

file
{
  "name": "arista/veos",
  "description": "Arista vEOS",
  "versions": [
    {
      "version": "4.20.1F",
      "providers": [
        {
          "name": "libvirt",
          "url": "file:///home/bradmin/vagrant/boxes/arista/vEOS-lab-4.20.1F-combined.box"
        }
      ]
    }
  ]
}

Add the box to Vagrant.

cmd
vagrant box add veos.json

# output

==> box: Loading metadata for box 'veos.json'
box: URL: file:///home/bradmin/vagrant/boxes/arista/veos.json
==> box: Adding box 'arista/veos' (v4.20.1F) for provider: libvirt
box: Unpacking necessary files from: file:///home/bradmin/vagrant/boxes/arista/vEOS-lab-4.20.1F-combined.box
==> box: Successfully added box 'arista/veos' (v4.20.1F) for 'libvirt'!

Confirm the box was added successfully

cmd
vagrant box list

# output

arista/veos                   (libvirt, 4.20.1F)

CumulusCommunity/cumulus-vx   (libvirt, 3.5.3)

We are finished with the install and ready to test our new Arista vagrant-libvirt box.

Testing

Now that we have the box installed lets create a Vagrantfile and confirm we can build VM's with Vagrant.

Create a test directory.

cmd
mkdir ~/arista-test
cd ~/arista-test

Add a Vagrantfile to the test directory with the following contents

file
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  config.vm.box = "arista/veos"
  config.vm.box_version = "4.20.1F"

  # Turn off shared folders
  config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true

  # Dont change default SSH key
  config.ssh.insert_key = false

  config.vm.provider :libvirt do |domain|
    domain.disk_bus = 'ide'
    domain.cpus = 2
    domain.memory = 2048
  end

end

Now vagrant up and confirm you can login.

cmd
vagrant up

# output

Bringing machine 'sw01' up with 'libvirt' provider...
==> default: Checking if box 'arista/veos' is up to date...
==> default: Creating image (snapshot of base box volume).
==> default: Creating domain with the following settings...
==> default:  -- Name:              arista-test_default
==> default:  -- Domain type:       kvm
==> default:  -- Cpus:              2
==> default:
==> default:  -- Feature:           acpi
==> default:  -- Feature:           apic
==> default:  -- Feature:           pae
==> default:  -- Memory:            2048M
==> default:  -- Management MAC:
==> default:  -- Loader:
==> default:  -- Base box:          arista/veos
==> default:  -- Storage pool:      default
==> default:  -- Image:             /var/lib/libvirt/images/arista-test_sw01.img (5G)
==> default:  -- Volume Cache:      default
==> default:  -- Kernel:
==> default:  -- Initrd:
==> default:  -- Graphics Type:     vnc
==> default:  -- Graphics Port:     -1
==> default:  -- Graphics IP:       127.0.0.1
==> default:  -- Graphics Password: Not defined
==> default:  -- Video Type:        cirrus
==> default:  -- Video VRAM:        9216
==> default:  -- Sound Type:
==> default:  -- Keymap:            en-us
==> default:  -- TPM Path:
==> default:  -- INPUT:             type=mouse, bus=ps2
==> default: Creating shared folders metadata...
==> default: Starting domain.
==> default: Waiting for domain to get an IP address...
==> default: Waiting for SSH to become available...
==> default: Configuring and enabling network interfaces...
    default: SSH address: 192.168.121.144:22
    default: SSH username: vagrant
    default: SSH auth method: private key
Note

Once the VM boots up it takes approximately 30 seconds for the event handler config to be applied.

Confirm you can login to the box.

cmd
# Host terminal

vagrant ssh

# Now in vagrant box terminal

localhost#show version
Arista vEOS
Hardware version:
Serial number:
System MAC address:  28b7.adae.a3cd

Software image version: 4.20.1F
Architecture:           i386
Internal build version: 4.20.1F-6820520.4201F
Internal build ID:      790a11e8-5aaf-4be7-a11a-e61795d05b91

Uptime:                 4 minutes
Total memory:           2017148 kB
Free memory:            1206280 kB

localhost#

Awesome, we can build and login to the box with Vagrant. Lastly, let clean up a bit.

cmd
# back in host shell

vagrant destroy -f

# output

==> default: Removing domain...

Outro

Although that was a lot more involved than using the off the shelf virtualbox box provided by Arista. For me, the benefits of using the libvirt provider are worth the effort.