Home > Blogs > OpenStack Blog for VMware > Tag Archives: Vagrant

Tag Archives: Vagrant

Vagrant Up with VMware Integrated OpenStack, Part 3

In Part 1, we discussed how to get Vagrant working with VMware Integrated OpenStack. In Part 2, we discussed how to setup multiple nova instances with Vagrant. In today’s article, we’ll discuss a couple useful tips and tricks to have a more productive test environment deployment, namely:

How do I specify different settings per instance?
How do I automate the configuration of my instances?

These tasks are relatively simple to achieve with Vagrant!

Instance Settings Selection

Remember in Part 2 that we discussed the ability to leverage Ruby constructs in Vagrant? Well, this applies to If-Then-Else statements too! I can use the instance’s name in my conditional statement to determine how to change the characteristics (i.e. image, flavor, etc.) for each instance.

In the example that follows, I choose the instance flavor based on the name. The master instance will most likely run software that requires increased resources. So, I specify the medium flavor (4 GB RAM and 2 vCPU) for it. For any other instances, I stick with the small flavor (2 GB RAM and 1 vCPU). See the If-Then-Else statement in the Vagrantfile sample that follows


puts "\nHave you sourced your OpenStack creds today???\n"
nodes = ['master','node1']

Vagrant.configure("2") do |config|
  config.vm.box = "openstack"
  config.ssh.private_key_path = "~/.ssh/id_rsa"
  nodes.each do |server|
    config.vm.define "#{server}" do |box|
      config.vm.provider :openstack do |os|
        os.endpoint     = "#{ENV['OS_AUTH_URL']}/tokens"      # e.g. "#{ENV['OS_AUTH_URL']}/tokens"   
        os.username     = "#{ENV['OS_USERNAME']}"          # e.g. "#{ENV['OS_USERNAME']}"
        os.tenant_name = "#{ENV['OS_TENANT_NAME']}"
        os.api_key      = "#{ENV['OS_PASSWORD']}"          # e.g. "#{ENV['OS_PASSWORD']}"
        if server == 'master'
          os.flavor = /m1.medium/ # Resource allocation for the master node
        else
          os.flavor = /m1.small/ # Resource allocation for all other nodes
        end
        os.image        = /ubuntu/                 # Regex or String
        os.keypair_name = "demo-keypair"      # as stored in Nova
        os.ssh_username = "ubuntu"           # login for the VM
        os.networks = ["demo-network"]
        os.floating_ip = :auto
        os.floating_ip_pool = "EXTNET"
      end
    end
  end
end

The next time I run the vagrant up command, I’ll see that my master and node1 instances have different resource allocations. I can verify this with the nova show command.

Vagrant Provisioners

Vagrant includes support for instance customization via provisioners such as shell scripts and popular configuration management tools like Puppet, Chef, Ansible, and Salt. In the example that follows, I use a simple shell script for each instance. I use the vm.provision command and specify the path to the shell script (it resides in the same directory as my Vagrantfile).

If you want to use a configuration management solution, you have two options:

  1. Create a custom image that contains the required binary for the tool of choice.
  2. In the Vagrantfile, specify a shell script provisioner first to install the binary, and then specify the appropriate provisioner (puppet, chef, ansible, etc.) afterwards in the Vagrantfile.

Yes, you can use a shell script AND a puppet manifest in the same Vagrantfile, and they will be executed in the order that you specify them. You can read more about provisioners on the Vagrant site. I recommend option 2 from the list above since you can avoid keeping track of an additional binary as you version control your images.

The Vagrantfile that contains the shell script provisioner is included below with the provision command highlighted in bold.


puts "\nHave you sourced your OpenStack creds today???\n"
nodes = ['master','node1']

Vagrant.configure("2") do |config|
  config.vm.box = "openstack"
  config.ssh.private_key_path = "~/.ssh/id_rsa"
  nodes.each do |server|
    config.vm.define "#{server}" do |box|
      config.vm.provider :openstack do |os|
        os.endpoint     = "#{ENV['OS_AUTH_URL']}/tokens"      # e.g. "#{ENV['OS_AUTH_URL']}/tokens"   
        os.username     = "#{ENV['OS_USERNAME']}"          # e.g. "#{ENV['OS_USERNAME']}"
        os.tenant_name = "#{ENV['OS_TENANT_NAME']}"
        os.api_key      = "#{ENV['OS_PASSWORD']}"          # e.g. "#{ENV['OS_PASSWORD']}"
        if server == 'master'
          os.flavor = /m1.medium/ # Resource allocation for the master node
        else
          os.flavor = /m1.small/ # Resource allocation for all other nodes
        end
        os.image        = /ubuntu/                 # Regex or String
        os.keypair_name = "demo-keypair"      # as stored in Nova
        os.ssh_username = "ubuntu"           # login for the VM
        os.networks = ["demo-network"]
        os.floating_ip = :auto
        os.floating_ip_pool = "EXTNET"
      end
      box.vm.provision :shell, :path => "#{server}.sh"
    end
  end
end

I use the server variable to specify individual shell scripts for each instance. So, I created master.sh and node1.sh script files. Alternatively, I could have a single file for both instances and give it a name like common.sh, for example.

When Vagrant finishes creating the instances, it rsync’s the directory containing the Vagrantfile and the shell scripts to the instances. Finally, Vagrant executes the appropriate script on each instance.

Since the script execution is automated, you want to make sure that you specify answers to any prompts that your instructions may require. For example, if I’m installing a package on Ubuntu, I use the “-y” option (ex: apt-get install -y curl). If the package that I am installing has advanced options that force a response (ex: mysql), I could use the debconf-set-selections command as well to handle this. One thing that I recommend to speed up shell provisioner execution is to decrease output to standard out using the “-q” switch (ex: apt-get install -qy curl).

Are you using Vagrant or some other automation tool with your VMware Integrated OpenStack cloud? Feel free to share your own tips and tricks in the comments section!

You can learn more about VMware Integrated OpenStack on the VMware Product Walkthrough site and on the VMware Integrated OpenStack product page.

Vagrant Up with VMware Integrated OpenStack, Part 2

In our previous installment, we covered the basics of using Vagrant with VMware Integrated OpenStack. In today’s article, we will take a look at a multi-instance deployment from a single Vagrantfile. Today’s sample Vagrantfile looks almost identical to our previous example with a few changes, highlighted in bold, that we discuss below.

Let’s go back to the same directory where you created your Vagrantfile from our previous walkthrough. Make sure that your old Vagrant instance is deleted using the following command:

vagrant destroy -f

Now backup your original Vagrantfile if you would like to preserve it. Then, replace your Vagrantfile content with the code that follows.


puts "\nHave you sourced your OpenStack creds today???\n"

nodes = ['master','node1']

Vagrant.configure("2") do |config|
  config.vm.box = "openstack"
  config.ssh.private_key_path = "~/.ssh/id_rsa"
  nodes.each do |server|
    config.vm.define "#{server}" do |box|
      config.vm.provider :openstack do |os|
        os.endpoint     = "#{ENV['OS_AUTH_URL']}/tokens"      # e.g. "#{ENV['OS_AUTH_URL']}/tokens"   
        os.username     = "#{ENV['OS_USERNAME']}"          # e.g. "#{ENV['OS_USERNAME']}"
        os.tenant_name = "#{ENV['OS_TENANT_NAME']}"
        os.api_key      = "#{ENV['OS_PASSWORD']}"          # e.g. "#{ENV['OS_PASSWORD']}"
        os.flavor       = /m1.small/                # Regex or String
        os.image        = /ubuntu/                 # Regex or String
        os.keypair_name = "demo-keypair"      # as stored in Nova
        os.ssh_username = "ubuntu"           # login for the VM
        os.networks = ["demo-network"]
        os.floating_ip = :auto
        os.floating_ip_pool = "EXTNET"
      end
    end
  end
end

Vagrant is written in Ruby, and this allows us to use Ruby constructs to control how instances are deployed. For example, we use a Ruby list of strings (nodes = [‘master’,’node1′]) near the top of the file to declare the names of multiple servers that we want Vagrant to create for us in the OpenStack cloud.

We leverage a Ruby iterator (each), which will run the code that follows it for each element of the list. We have two entries in the node list. So, the Vagrant instructions will be run two times.  If you would like to create more than two nodes, you are free to add multiple names to that list up to the limit of instances specified by your OpenStack project’s quota.

When Vagrant is done provisioning your environment, you will see messages on the commandline similar to the following:


==> node1: The server is ready!
==> node1: Configuring and enabling network interfaces...
==> master: The server is ready!
==> master: Configuring and enabling network interfaces...
==> node1: Rsyncing folder: /Users/trobertsjr/Development/vagrant-on-openstack/ => /vagrant
==> master: Rsyncing folder: /Users/trobertsjr/Development/vagrant-on-openstack/ => /vagrant

You can then use the following command to verify that your OpenStack instances were created successfully and are available for use:


vagrant status

This command’s output should show an active state for your instances:


Current machine states:

master                    active (openstack)
node1                     active (openstack)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

The nova CLI will also show your instances being active and available:


(openstack)vagrant-on-openstack $ nova list
+--------------------------------------+--------+--------+------------+-------------+-----------------------------------------+
| ID                                   | Name   | Status | Task State | Power State | Networks                                |
+--------------------------------------+--------+--------+------------+-------------+-----------------------------------------+
| 38702893-4b33-4f77-ba9a-07c99ab16318 | master | ACTIVE | -          | Running     | demo-network=192.168.0.41, 10.115.96.32 |
| 45f9d279-d6fb-48b7-a191-985eed9452fc | node1  | ACTIVE | -          | Running     | demo-network=192.168.0.40, 10.115.96.31 |
+--------------------------------------+--------+--------+------------+-------------+-----------------------------------------+

Finally, you can ssh into the instances using Vagrant as you did with our previous post, but you will need to specify the name of the instance you are connecting to this time.


vagrant ssh master

or


vagrant ssh node1

Try Vagrant with VMware Integrated OpenStack today, and let us know how it worked out for you!

You can learn more about VMware Integrated OpenStack on the VMware Product Walkthrough site and on the VMware Integrated OpenStack product page.

Vagrant Up with VMware Integrated OpenStack, Part 1

Since VMware Integrated OpenStack is DefCore-compliant, our users can easily leverage popular community tools, such as Vagrant, to work with our distribution. In this article, we will discuss how to prepare your development environment for using Vagrant with OpenStack, and we will deploy a single instance. In our next installment, we will discuss a multi-instance deployment.

If you are not familiar with Vagrant, it is a HashiCorp solution for quickly building repeatable development according to instructions contained in a simple text file known as the Vagrantfile. The Vagrantfile specifies how you want to configure a template VM (also known as a “box”) with multiple customization options including shell scripts, Puppet manifests, Chef recipes, Ansible playbooks, etc.

For the examples below, I used the Vagrant OpenStack plugin developed by Edmund Haselwanter and the team at Cloudbau. However, there are others that you can try if you don’t like the way this plugin works.

An important prerequisite for working with the OpenStack plugin is to register a signed certificate with your VIO installation. This is due to the Vagrant plugins currently being unable to process the OS_CACERT environment variable for self-signed certificates.

Next, install Vagrant on your desktop if you have not done so already. After installing vagrant, we need to install the OpenStack plugin using the following syntax:

vagrant plugin install vagrant-openstack-plugin

We then specify a box that will be a placeholder for the images in our OpenStack cloud:

vagrant box add openstack https://github.com/cloudbau/vagrant-openstack-plugin/raw/master/dummy.box

Vagrant typically looks for boxes on your local machine. When working with an OpenStack cloud, though, we specify an image in the cloud instead of a local box as you will see and example of this in the sample Vagrantfile below. So, this placeholder box is only here to satisfy Vagrant syntax requirements.

Finally, we are ready to use Vagrant with OpenStack. Let’s create a new directory on your local desktop.  Change to that directory and type the following command:

vagrant init openstack

This will generate a sample Vagrantfile definition. We will pretty much remove all the contents from that file and replace it with content similar to the following (explanations are included as comments with the “#”) prefix:


puts "\nHave you sourced your OpenStack creds today???\n" # A helpful reminder to source your OpenStack tenant's credentials file

Vagrant.configure("2") do |config|
  config.vm.box = "openstack" # specify the placeholder box
  config.ssh.private_key_path = "~/.ssh/id_rsa" # replace with the path to your own private key that you use with OpenStack
  config.vm.provider :openstack do |os|
    os.endpoint     = "#{ENV['OS_AUTH_URL']}/tokens"   # Get the environment variable for the authentication URL. 
    os.username     = "#{ENV['OS_USERNAME']}"          # Get the environment variable for the username.
    os.tenant_name = "#{ENV['OS_TENANT_NAME']}"        # Get the environment variable for the OpenStack tenant name.
    os.api_key      = "#{ENV['OS_PASSWORD']}"          # Get the environment variable for the OpenStack password.
    os.flavor       = /m1.small/                       # Specify either an exact string for the flavor or a regex.
    os.image        = /ubuntu/                         # Specify either an exact string for the image or a regex.
    os.keypair_name = "demo-keypair"                   # Replace with your keypair name. You can use nova keypair-list to get it
    os.ssh_username = "ubuntu"                         # The username that Vagrant will use to login to the instance and customize it.
    os.networks = ["demo-network"]                     # You can specify one or more networks enclosed in quotes and comma-separated.
    os.floating_ip = :auto                             # Indicate a specific Floating IP or use the :auto keyword.
    os.floating_ip_pool = "EXTNET"                     # Specify the name of your external network.
  end
end

Before we proceed, make sure to load your OpenStack credentials as environment variables, and confirm this was done with a sample CLI command like nova list. Now, we are ready to use Vagrant for the first time to bring up an OpenStack instance:

vagrant up --provider=openstack

You should see some output at the command line. After the line about rsyncing files to your instance, it will be available for use by using the following command:

vagrant ssh

When you are done with the instance, you can use the following command to get rid of it:

vagrant destroy

Try Vagrant with VMware Integrated OpenStack today, and let us know how it worked out for you!

You can learn more about VMware Integrated OpenStack on the VMware Product Walkthrough site and on the VMware Integrated OpenStack product page.