If you followed me through the first part of this set of articles, you will now be faced with a shiny new box containing your BIG-IP VE image. You're chomping at the bit to get it fired up in vagrant, so let's do it!

The Vagrantfile

 
Vagrant uses a configuration file called the Vagrantfile to boot up your environment and provision your devices as you have specified. A Vagrantfile is written in Ruby, but you (generally) are not required to know Ruby to be able to use it. Granted, if you want to do magical things with the Vagrant file, you need to know Ruby. For what we're doing, you will not.
 
Vagrant looks for these Vagrantfiles in your current working directory. I'll get straight to the point here and give you the Vagrantfile you need to boot your BIG-IP. Then, we'll walk through what it does.
 
Here's the business end of the article.
 
# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.define "big-ip01.internal" do | v |
    v.vm.box = "/path/to/box/BIGIP-11.6.0.0.0.401.LTM_1SLOT-ide.box"

    config.vm.synced_folder ".", "/vagrant", disabled: true

    v.vm.network :forwarded_port, guest: 443, host: 10443

    v.vm.provider :virtualbox do |p|
      p.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
      p.customize ["modifyvm", :id, "--memory", 2048]
      p.customize ["modifyvm", :id, "--cpus", 2]
      p.customize ["modifyvm", :id, "--name", "big-ip01.internal"]

      p.customize ["modifyvm", :id, "--nic1", "nat"]
      p.customize ["modifyvm", :id, "--nictype1", "virtio"]
      p.customize ["modifyvm", :id, "--nic2", "hostonly"]
      p.customize ["modifyvm", :id, "--nictype2", "virtio"]
      p.customize ["modifyvm", :id, "--hostonlyadapter2", "vboxnet2"]
    end

    v.vm.provision "shell", inline: <<-SHELL
      while true; do
          string=`tmsh show sys failover`
          if [[ $string == *"active"* ]]
          then
              break
          else
              echo "runlevel is 'unknown' - waiting for 10s"
              sleep 10
          fi
      done
      echo "runlevel is now valid, kicking off provisioning..."
    SHELL
  end
end
 
OK! Lots of stuff going on there!
 
The first couple of lines can be overlooked as they are specific to Vagrant itself. In the "box" line, we tell Vagrant where to find out box we created.
 
Next, the "config.vm.synced_folder" line, is important because BIG-IP did not have the Virtual box Guest Additions installed on it. You can't install them because the kernel headers do not exist on your VE. So there is not ability to mount a shared folder using Vagrant's build in commands. Since vagrant tries to do this by default, we simply turn that feature off for this box.
 
In the forwarded_port line we Vagrant to accept connections to the host on port 10443 and forward them to port 443 on the BIG-IP. This allows us to reach the web UI. Why port 10443? Well, I make the assumption here that most folks will not be running vagrant as root. As such, you are not going to be able to bind to ports less than 1024. So I just follow a simple convention and add 10,000 to any port I want to add. This gets you out of the range of most common services and you're allowed to bind to these ports as a normal user.
 
Next we get into the BIG-IP specific details of the Vagrantfile. Remember back to the packer template we made? Well, we are going to use similar configurations here to make sure that BIG-IP has everything it needs to boot properly.
 
Among those things is setting the RAM and CPU count. Additionally we give the VM in Virtualbox a name so that we can know what it is just by looking. Vagrant provides a way to set the hostname on a device, but we cannot use it on a BIG-IP because the return code from doing so is greater than zero, ie, an error that looks like this.
 
==> big-ip01.internal: Setting hostname...

The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

hostname

Stdout from the command:

Stderr from the command:

logname: no login name
Use the TMOS shell utility to make changes to the system configuration.
For more information, see "tmsh help sys global-settings."
 
Not very graceful.
 
After that, you can see that we once again create the first interface for mgmt and specify that it is a NAT
interface. This means that Vagrant will serve DHCP on that interface and, of course, BIG-IP will receive a
lease when it boots.
 
It's important to note that you specify the NIC type as "virtio". This is important because BIG-IP doesn't
have drivers for the other types of card provided by Virtualbox. If you specify the default, you're likely to
not have an interface for it when BIG-IP boots.
 
In the section section you can see me specifying another interface and connecting it to a private network
(vboxnet2) that is provided by Virtualbox.
 
This is a convenient time to answer the question
 
Vagrant provides convenience tools for this such as private_network, why not use those?
The answer is because of tmm. If you did use the private_network command, the problem is that tmm
controls all of your interfaces after the device boots. Adding configuration to the standard linux locations
is futile because tmm controls these and you have to use tmsh to set Self-IPs and VLANs so that the
configuration will land in mcpd and be read by tmm.
 
Wow, that's a lot.
 
So what's with that final block? Well, this is my hack to assure that BIG-IP is "ready to go" so-to-speak.
 
If this pause and loop were not here, then Vagrant would boot the device and be like "ok here you go!" but
the system and its services would still be in the middle of starting up and configuring themselves. So that's
a problem.
 
With this poor-mans version of a spin-lock, we ensure that Vagrant won't bless the VM as ready-to-go until
tmm, mcpd, and all the other things are ready to go.
 
So that's it! Crazy.
 
Now, an aside here, what if you want to do any pre-configuration automatically so that you do not need to
perform it in the web UI? This is a trivial addition. You would add another block that resembles the following
 
    v.vm.provision "shell", inline: <<-SHELL

      tmsh load /sys config default
      tmsh modify sys db setup.run value false
      sleep 10

      SOAPLicenseClient --basekey XXXXX-XXXXX-XXXXX-XXXXX-XXXXXXX

      sleep 10

      tmsh save sys config
    SHELL
 
Or whatever you want to do. The above will turn off the standard setup screen and license the box for you.
 
With that all in place, fire it up!
 
vagrant up
 
Wait a little bit and when you're done, there it is in Virtualbox ready to be used as any other Vagrant box
would be.
 
I've included the full Vagrantfile in the References section below.
 
This concludes our trip through vagrant land. Hope it has provided insight into how to use the tool with a BIG-IP VE image. Lemme know if the comments what you think and if you would be interested in other oddball technical articles about BIG-IP.
 
Enjoy!

References

  • https://devcentral.f5.com/codeshare/vagrantfile-to-use-big-ipbox