Mastering OpenStack
上QQ阅读APP看书,第一时间看更新

Eat the elephant

At first sight, you may wonder what is the best automation tool that will be useful for our OpenStack "production day". We have already chosen Git and Jenkins to handle our continuous and delivery code infrastructure. It is time to choose the right tool for automation.

Eventually, it might be difficult to select the right tool. Most likely, you'll have to choose between several of them. Covering all the existing IT automation tools could fill an entire book or even books. Therefore, giving succinct hints on different tools might be helpful in order to distinguish the best outfit for certain particular setups. Of course, we are still talking about large infrastructures with heterogeneous systems, a lot of networking, and distributed services.

Giving the chance for one or more tools to be selected as system management parties can be effective and fast for our deployment. We will use Chef for the next deployment phase.

Preparing the infrastructure code environment

If you are not familiar with the Git command line, do not worry, because we will use an integrated development environment (such as Eclipse), which provides a great Git plugin.

Note

Later, we will need to write and maintain code written in the Ruby programming language. Chef cookbooks are written in Ruby. Feel free to use your best development environment that supports and simplifies code branching and maintenance within your VCS. There are plenty of preferences for development environments and Ruby code editors, such as RubyMine (https://www.jetbrains.com/ruby/) and Komodo (http://komodoide.com/). The Netbeans IDE also comes up with a Ruby plugin (http://plugins.netbeans.org/plugin/38549/ruby-and-rails) and the Sublime text editor (http://www.sublimetext.com/) can be a good candidate for a lightweight text editor for code.

Feel free to use any Linux distribution. The next setup will use CentOS 6.5 64 bit as the standard operating system.

Ensure that Java and its dependencies are installed:

packtpub@dev$ sudo yum install java
packtpub@dev$ sudo yum install gcc-c++

You can download Eclipse for CentOS from here:

packtpub@dev$ wget http://mirror.netcologne.de/eclipse/technology/ epp/downloads/ release/juno/SR2/eclipse-automotive-juno-SR2-incubation-linux-gtk-x86_64.tar.gz

Extract the Eclipse to the /opt directory:

packtpub@dev$ sudo tar -xvzf eclipse-automotive-juno-SR2-incubation-linux-gtk-x86_64.tar.gz -C /opt/

Create a symlink:

packtpub@dev$ sudo ln -s /opt/eclipse/eclipse /usr/bin/eclipse

To install Ruby, you need to go from the Eclipse menu bar and navigate to Help | Install New Software. From the pending list, navigate to Program Languages | Dynamic Languages Toolkit - Ruby Development Tools:

Preparing the infrastructure code environment

Install Git:

packtpub@dev$ sudo yum install git

Check the correctness of the Git installation:

packtpub@chef$ git --version

Bring the magic EGit plugin into the action link in order to develop with Git in Eclipse. We do this in the same way from the Eclipse update manager by navigating to the Help | Install new Software menu entry. You will need to add the following URL installation to EGit:

http://download.eclipse.org/egit/updates

You will then see the following screen:

Preparing the infrastructure code environment

If you are not familiar with Chef, the following section will cover the basic setup and the most important parts of a Chef server, and you can see how it looks.

Tip

If you do not have the Ruby plugin installed in your Eclipse environment by default, you can download and install it from SourceForge at http://sourceforge.net/projects/rubyeclipse/files/rdt/0.8.0/org.rubypeople.rdt-0.8.0.604272100PRD.zip/download?use_mirror=freefr&download=.

The Chef environment

When you think about a typical chef, you may think of cookbooks, recipes, and knives! These are what a chef needs in order to make awesome dishes. The taste of the food on a plate depends on the creativity of the chef. We do the same thing in terms of cooking: we use a basic cookbook, from which we derive the right recipes. We refine the recipes till we get what fulfills our needs.

Let's see how Chef defines its awesomeness:

  • Cookbook: The grained unit of the configuration in Chef describes the kind of scenario that is there, and how it should be defined in order to deploy an application in a node.
  • Recipe: This is the part of a cookbook that is authored in Ruby and defines the configuration of the nodes. Note that a recipe can use or be used by another recipe.
  • Node: This is where we can apply the cookbook configurations.
  • Role: This can be considered as a logical function for a node. It can be customized within a collection of recipes and cookbooks, in a particular order.
  • Attribute files: The attributes are very important in order to change the settings of the nodes.
    Note

    You should take into consideration the precedence level of the attributes that define what should be applied. Basically, the evaluation of such attributes against the node object will be done during each Chef run.

Keep the previous terms in your mind, but do not be surprised when you start to find much more than these terms during our deployment. We will cover them in a nutshell.

Tip

To read more about Chef, you can refer to the official Opscode website: https://docs.chef.io/.

Prerequisites for settings

Before installing the server, we need to set up the right hostname of our CentOS box, where we can define it as an FQDN with a domain suffix:

  1. Open the /etc/sysconfig/network file and modify the HOSTNAME value to match your FQDN hostname:
    packtpub@chef$ sudo nano /etc/sysconfig/network
    HOSTNAME=chef.packtpub.com
    
  2. Change the host that is associated to your IP address for your server found in the /etc/hosts file, as follows:
    packtpub@chef$ sudo nano /etc/hosts
    192.168.47.10 chef.packtpub.com chef
    
  3. Check your hostname via the following command:
    packtpub@chef$ hostname -f
    chef.packtpub.com
    
  4. Make sure that your changes are persistent on reboot:
    packtpub@chef$ sudo /etc/init.d/network restart
    
    Note

    You will need to adjust the settings, such as the hostname, FQDN, and IP address, to suit your needs.

  5. As we are using CentOS, it will be much easier for a smooth installation process in order to modify iptables and SELinux. Note that it is not recommended that you entirely disable the iptables service in a production environment where you will have to create extra iptables rules and update your SELinux as well. We will need to allow access to the following ports:
    • TCP ports: 80, 443 for the Chef server web user interface
    • TCP port: 4000 for the Chef server Knife access

    The following commands will update the running iptables rules in your CentOS box:

    packtpub@chef$ sudo iptables -A INPUT -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
    packtpub@chef$ sudo iptables -A INPUT -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
    packtpub@chef$ sudo iptables -A INPUT -p tcp --dport 4000 -m state --state NEW,ESTABLISHED -j ACCEPT
    
  6. Save the new policy update and restart the iptables service:
    packtpub@chef$ sudo service iptables save
    packtpub@chef$ sudo service iptables restart
    
  7. Set SELinux to the permissive mode:
    packtpub@chef$ sudo setenforce 0
    
The Chef server installation

The next setup describes some simple steps to install the Chef server:

  1. In your local shell, run the following command to download the Chef server:
    packtpub@chef$ sudo rpm -ivh https://opscode-omnibus packages.s3.amazonaws.com/el/6/x86_64/chef-server-11.0.8-1.el6.x86_64.rpm
    
  2. Configure the Chef server:
    packtpub@chef$ sudo chef-server-ctl reconfigure
    
  3. Check whether the installation was successful or not:
    packtpub@chef$ sudo chef-server-ctl test
    Finished in 0.11742 seconds
    0 examples, 0 failures
    
  4. The server should be up and running. You can access the web interface via https://chef.packtpub.com:443:

    The Chef server installation

Tip

The Chef server user interface can be accessed using the FQDN edited previously: https://FQDN:443. You can use https://CHEF_IP_ADDR:443, where CHEF_IP_ADDR is the local IP address of your Chef server.

Enter admin as the username and p@ssw0d1 as the default password.

The Chef server installation

Workstation installation

We will need additionally one or more Chef workstation(s) as a development toolkit. This node's role is as follows:

  • The Chef client is installed and Knife is configured
  • It holds the local repository for the Chef server
  • It installs Chef on the nodes via the knife bootstrap operation
  • It dictates nodes, roles, and infrastructure environments to be uploaded to the Chef server

Our Chef workstation will hold the local repo, and then we can install it on our VCS node, where all the development will be performed and then uploaded to the Chef server.

Note

Knife in Chef refers to a tool which provides a Command-Line Interface (CLI) between a Chef server and the Chef repository. It can be installed in a Chef workstation and used to manage nodes, roles, cookbooks, and environments with the Chef server. To read more about Knife in Chef, refer to this link https://docs.chef.io/knife.html.

Let's install our Chef workstation:

  1. Get the Chef client installed:
    packtpub@workstation$ curl -L https://www.opscode.com/chef/ install.sh | bash
    
  2. Verify the installation:
    packtpub@workstation$ chef-client -v
    
  3. Create your chef-repos for a proper format of the Chef repository from GitHub by cloning the structure in /home/packtpub/:
    packtpub@workstation$ git clone https://github.com/ opscode/chef-repo.git
    packtpub@workstation$ cd /home/packtpub 
    packtpub@workstation$ mkdir -p /chef-repo/.chef
    

    In order to authenticate against the Chef server, we will need to add some inputs for the key files from the Chef server web interface. Go to the Clients tab and click on Edit with the chef-validator client.

  4. Copy the value of the Private key field. In your workstation, create a new file for the validator key:
    packtpub@workstation$ vi /home/packtpub/chef-repo/.chef/chef-validator.pem
    
  5. Paste the content of the copied key and save and close the file.

We perform the same procedure to generate the admin user's key file. In the Users tab, click on Edit, which is associated with the admin user, and check Regenerate Private Key followed by Save User.

After copying the private key, create a new file admin.pem in /home/packtpub/chef-repo/.chef/ again and paste the content of the admin's private key:

  1. Create the Knife configuration file:
    packtpub@workstation$ knife configure -i
    
    Overwrite /root/.chef/knife.rb? (Y/N) y
    Please enter the chef server URL: [https://test.example.com:443] 
    https://chef-server.packtpub.com:443/
    Please enter a name for the new user: [root] packtpub
    Please enter the existing admin name: [admin] Enter
    Please enter the location of the existing admin's private key: [/etc/chefserver/admin.pem] /home/packtpub/chef-repo/.chef/admin.pem
    Please enter the validation clientname: [chef-validator]
    Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem] /home/packtpub/chef-repo/.chef/chef-validator.pem 
    Please enter the path to a chef repository (or leave blank): 
    Creating initial API user... 
    Please enter a password for the new user
    Created user[pack-knife] 
    Configuration file written to /home/packtpub/chef-repo/.chef/ knife.rb
    

    At the end, you should have the following list of files:

    packtpub@workstation$ ls /home/packtpub/chef-repo/.chef/
    admin.pem chef-validator.pem knife.rb pack-knife.pem
    
  2. Initialize our Git name and e-mail:
     packtpub@workstation$ git config --global user.email "masteropenstack@packtpub.com"
     packtpub@workstation$ git config --global user.name "masteropenstack"
    
  3. Clean up the repository by adding the .chef line to .gitignore:
    packtpub@workstation$ nano /home/packtpub/chef repo/.chef/.gitignore
    
    .rake_test_cache
    .chef/*.pem
    .chef/encrypted_data_bag_secret
    .chef
    
  4. Add and commit the current repository:
    packtpub@workstation$ git add .
    packtpub@workstation$ git commit -m 'Finish setting up'
    
  5. Make sure that you are using the right Ruby version:
    packtpub@workstation$ vi .bash_profile
    packtpub@workstation$ echo 'export PATH="/opt/chef/embedded/bin:$PATH"' >> ~/.bash_profile
    
  6. Populate the bash profile settings:
    packtpub@workstation$ source ~/.bash_profile
    
  7. Test our workstation's Chef server connection:
    packtpub@workstation$ knife user list 
    admin
    packt-knife
    
Time to cook OpenStack

At this stage, we have a complete Chef environment where the OpenStack code infrastructure will be developed, refined, and released to production.

Let's take a look at the environment topology again. We need nodes and instances to test how our cookbooks will be applied and tested.

For this purpose, we will use a great tool for testing purposes: Vagrant.

Note

Vagrant is open source software used to build virtualized development environments. Vagrant requires virtual machines to test Chef Cookbooks before going to production. VirtualBox is a good candidate which works together with Vagrant to provide a complete test environment. For more information on Vagrant, refer to the following link https://docs.vagrantup.com/v2/getting-started/.

Vagrant can be integrated with Chef. Then, from a Vagrant file, we push the button to make Chef run and get instances up, which makes it the cat's meow.

Where is my kitchen?

Be aware that Vagrant will be used for test purposes. This amazing tool will help you make sure you know how your OpenStack Chef cookbooks work.

This is a suitable test for the virtual machine manager candidate to achieve a clean state from your nodes. Furthermore, it might be possible to reproduce a whole test environment in each Chef run, which creates an initial state that mimics a production environment.

You can manage VMs by means of Vagrant using VirtualBox while using a Chef client as a provisioner. Then, we have our test development environment: the OpenStack kitchen. We will describe the use case of Vagrant later in this chapter.

OpenStack cookbooks

There are always challenges facing DevOps, and no doubt, they will occur after you have conducted your design to be deployed in a real environment. Meeting these challenges will drive you to acquire new skills related to creating a large complicated OpenStack infrastructure with simple code that you never thought you could master.

Several organizations and big companies have been involved in writing cookbooks for OpenStack in different ways. You might be tempted to think how you can use the existing cookbooks in the cookbook market as well as which ones to choose and how to develop them for your own needs.

Let's discuss what we need with the help of a simple, generic overview:

  • Controller nodes
  • Compute nodes
  • Neutron nodes
  • Swift as a single cluster

You may note that the controller node, as described in our first design, handles and runs the majority of native OpenStack services. You can derive many recipes from OpenStack cookbooks in GitHub. The Opscode community is also an option. We will base our first cookbooks on StackForge cookbooks. However, before that, we should take care of the cookbook dependencies for a clean setup.

Note

StackForge aims to facilitate the usage of the OpenStack infrastructure by other projects, including continuous integration (Jenkins) and repository mirroring (GitHub). More information on the StackForge project can be found at http://ci.openstack.org/stackforge.html.

Inpidual cookbooks for each OpenStack service have been created in the StackForge GitHub repository, which can be found at https://github.com/stackforge. The cookbooks used by Chef from the StackForge repository are listed and described at https://docs.chef.io/openstack_cookbooks.html.

Resolving OpenStack cookbook dependencies

Without any doubt, the world of dependency is a world of pain! This is when you plan to install a cookbook that another one depends on it. Manual downloading for each one might depend on other cookbooks.

A trick for manual downloading can be to use the knife cookbook site install command, which is somehow great as it installs all the dependencies. However, the dependencies will be installed in your local repository, and you might not like to see them flapping in your directory. You will be delighted when you find out that there is a tool that can do this for you: Berkshelf.

This amazing cookbook manager downloads all dependencies recursively while keeping your local repository clean. Dependencies will be stored in a different location.

Berkshelf uses Berksfile, in which we commit our dependencies to our repository.

The first successful step to make this tool do the magic, is to ensure a proper installation. Somehow, Ruby versioning can be confusing if you have already installed Chef server or Chef workstation within Ruby version 1.8.7. It is recommended that you upgrade or switch to 1.9.1 or higher. Note that Berkshelf requires Ruby version 1.9.1 or higher.

If you already have 1.8.7, no worries; we will perform a trick without ping into Ruby setup errors.

We can use Ruby Version Manager (rvm) to switch between Ruby versions.

Note

Ruby is a very popular programming language that is used by Chef to write cookbooks. Different versions of Ruby may be necessary for different projects. Installing and running other Ruby gems (RubyGems) might require different Ruby versions. Using the rvm will allow you to easily install multiple, contained versions of Ruby and switch between them. For more information on rvm, refer to this link: https://rvm.io/rvm/basics.

  1. Install rvm:
    packtpub@workstation$ curl -L get.rvm.io | bash -s stable fails
    
    Note

    If you get an error issued you will need to specify the gpg2 key. You will need to run a similar command line from the output shown in the curl command as follows: gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3.

  2. Source the rvm variables:
    packtpub@workstation$ source /etc/profile.d/rvm.sh
    
  3. Install Ruby 1.9.2:
    packtpub@workstation$ rvm install 1.9.2
    
  4. Set it as the default Ruby interpreter:
    packtpub@workstation$ rvm --default use 1.9.2
    
  5. Install gem dependencies:
    packtpub@workstation$ sudo yum install rubygems
    
  6. Install Berkshelf dependencies:
    packtpub@workstation$ sudo yum install gecode-devel gcc-c++ -y 
    
  7. Install Berkshelf :
    packtpub@workstation$ gem install berkshelf
    Fetching: nio4r-1.0.1.gem (100%)
    Building native extensions. This could take a while...
    

Knife's command line will start to complain about the Ruby version when you fire it in your shell. Thus, you can always reset your default Ruby version 1.8.7 using this:

packtpub@workstation$ rvm system
Uploading cookbooks using Berkshelf

Let's create our main Berkshelf file, which will define all the cookbooks needed for our first deployment. We will tell Berkshelf to clone the cookbooks and their dependencies mainly from supermarket.getchef.com:

packtpub@workstation$ nano /home/packtpub/chef-repo/Berksfile
source "https://supermarket.getchef.com"

cookbook 'apache2', '1.9.6'
cookbook 'apt', '2.3.8'
cookbook 'aws', '2.1.1'
cookbook 'build-essential', '1.4.2'
cookbook 'database', '2.2.0'
cookbook 'erlang', '1.4.2'
cookbook 'memcached', '1.7.2'
cookbook 'mysql', '5.4.4'
cookbook 'mysql-chef_gem', '0.0.4'
cookbook 'openssl', '1.1.0'
cookbook 'postgresql', '3.3.4'
cookbook 'python', '1.4.6'
cookbook 'rabbitmq', '3.0.4'
cookbook 'xfs', '1.1.0'
cookbook 'yum', '3.1.4'
cookbook 'selinux', '0.7.2'
cookbook 'yum-epel', '0.3.4'
cookbook 'galera', '0.4.1'
cookbook 'haproxy', '1.6.6'
cookbook 'keepalived', '1.2.0'
cookbook 'statsd', github: 'att-cloud/cookbook-statsd'
cookbook 'openstack-block-storage', github: 'stackforge/cookbook-openstack-block-storage'
cookbook 'openstack-common', github: 'stackforge/cookbook-openstack-common'
cookbook 'openstack-compute', github: 'stackforge/cookbook-openstack-compute'
cookbook 'openstack-dashboard', github: 'stackforge/cookbook-openstack-dashboard'
cookbook 'openstack-identity', github: 'stackforge/cookbook-openstack-identity'
cookbook 'openstack-image', github: 'stackforge/cookbook-openstack-image'
cookbook 'openstack-network', github: 'stackforge/cookbook-openstack-network'
cookbook 'openstack-object-storage', github: 'stackforge/cookbook-openstack-object-storage'
cookbook 'openstack-ops-database', github: 'stackforge/cookbook-openstack-ops-database'
cookbook 'openstack-ops-messaging', github: 'stackforge/cookbook-openstack-ops-messaging'

Then, you need to just upload cookbooks as the following:

packtpub@workstation/home/packtpub/chef-repo $ berks install
Resolving cookbook dependencies...
packtpub@workstation/home/packtpub/chef-repo $ berks upload --no-ssl-verify
Defining roles

Chef defines roles as a manner to group nodes, seeking simplicity deployment. From run lists in all nodes, you will just need to assign the node that should be run. Optionally, you will be able to customize them by overriding attribute values within your roles. On the other hand, recipes define roles. Thus, you may notice the running of a list of a bunch of recipes within a role. Besides, it can also include roles from other run lists.

Let's cover a basic example using only recipes in the role run list within OpenStack. In your chef-repo directory, create a new directory named roles.

Create the role:

$ nano roles/packtpub-os-base.json

Eventually, the packtpub-os-base role defines the base role of OpenStack nodes that will be assigned to the majority of servers in our deployment. It provides common attributes and recipes that define the OpenStack deployment, such as setting network interfaces of hosts within the existing endpoints:

{
  "name": "packtpub-os-base.json",
  "description": "PacktPub OpenStack Base Role",
  "json_class": "Chef::Role",
  "default_attributes": {
  },
  "override_attributes": {
  },
  "chef_type": "role",
  "run_list": [
    "recipe[openstack-common]",
    "recipe[openstack-common::logging]",
    "recipe[openstack-common::set_endpoints_by_interface]",
    "recipe[openstack-common::sysctl]"
  ],
  "env_run_lists": {
  }
}

Let's carry on with the second role using the previous one.

Create a new role named packtpub-os-compute-worker.json. This role will define our OpenStack compute node:

{
  "name": "packtpub-os-compute-worker",
  "description": "PacktPub OpenStack Compute Role",
  "json_class": "Chef::Role",
  "default_attributes": {
  },
  "override_attributes": {
  },
  "chef_type": "role",
  "run_list": [
 "role[packtpub-os-base]",
 "recipe[openstack-compute::compute]"
  ],
  "env_run_lists": {
  }
}

You might notice that we have used the base role, packtpub-os-base, within the compute recipe that we have uploaded in our Chef.

At this point, feel free to add any role that will fit your design from our basic cookbooks added from supermarket.getchef.com. Distributing roles will depend on your choice and the number of nodes you plan to deploy for a certain service. We can assume that any change to a certain node deployment will be made from the Chef code.

In our custom design, we will need a controller node, which will run a bunch of services. A good practical design of cookbooks is to wisely break down your infrastructure into reusable roles and recipes. For example, our controller node will include networking, imaging, messaging, identity, and database services; going on making a one blob role which includes all the associated recipes might limit your attention and make you think about scaling out the nodes later. Remember that we are expanding and not rolling up the infrastructure.

Before creating our custom controller role, we will proceed by creating a basic one:

packtpub-os-base-controller

{
  "name": "packtpub-os-base-controller",
  "description": "PacktPub OpenStack Controller Role",
  "json_class": "Chef::Role",
  "default_attributes": {
  },
  "override_attributes": {
  },
  "chef_type": "role",
  "run_list": [
    "role[packtpub-os-base]",
    "role[packtpub-os-ops-database]",
    "recipe[openstack-ops-database::openstack-db]",
    "role[packtpub-os-ops-messaging]",
    "role[packtpub-os-identity]",
    "role[packtpub-os-image]",
    "role[packtpub-os-compute-setup]",
    "role[packtpub-os-compute-conductor]",
    "role[packtpub-os-compute-scheduler]",
    "role[packtpub-os-compute-api]",
    "role[packtpub-os-block-storage]",
    "role[packtpub-os-compute-cert]",
    "role[packtpub-os-compute-vncproxy]",
    "role[packtpub-os-dashboard]"
  ],
  "env_run_lists": {
  }
}

To upload all your created roles, you can use the following command:

packtpub@workstation$ knife role from file /home/packtpub/chef-cookbooks/roles/*.rb
Tip

The basic cookbooks for OpenStack have been downloaded from https://github.com/stackforge. It is recommended that before starting your Chef deployment, you have to verify the roles and their names, the number of environments and their names. A good practice while customizing a cookbook or defining an OpenStack environment in Chef is to add as many thin roles as possible. If you face any error-naming convention while running Chef, try to adjust the role names in attribute files to reflect the same names within the defined roles.

Configuring the environment

Now we have a set of cookbooks uploaded to the Chef server and ready to be deployed. An extra step is needed to make them useful: Defining your environments. Note that we define the playground environment using Vagrant, where we will provision our test infrastructure, and the cooking environment, where we define our infrastructure details from one file and let Chef do the rest:

  • Playground environment: Until now, we have our basic cookbooks ready to be uploaded within defined roles. They need customization and more development to adjust our infrastructure needs.

    Vagrant might be a very cost-effective and the simplest solution to make a full test environment work together with Chef.

    We can use a provider for Vagrant as a VirtualBox, where it can be installed as a virtual machine while our provisioner will be Chef.

    Note

    Provisioning with Vagrant can also be performed using Puppet, and the providers can be VMware and Amazon AWS.

    You can download and install Vagrant from http://downloads.vagrantup.com:

    packtpub@workstation$ wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2_x86_64.rpm
    packtpub@workstation$ rpm –ivh vagrant_1.7.2_x86_64.rpm 
    packtpub@workstation$ vagrant --version 
    Vagrant version 1.7.2
    
    Note

    VirtualBox needs to be installed as a Vagrant provider. VMware is also a second alternative to run Vagrant boxes.

  • Vagrantfile: The vagrant file will define all our OpenStack nodes and the general configuration, such as networking:
    packtpub@workstation$ nano /home/packtpub/chef-repo/Vagrantfile
    

    The contents of the Vagrant file are:

    Vagrant.require_version ">= 1.1"
    
    Vagrant.configure("2") do |config|
       # Omnibus plugin configuration
      config.omnibus.chef_version = :latest
    
      # OpenStack settings
      chef_environment = "vagrant-packtpub"
    
        controller_run_list = [
          "role[packtpub-os-base-controller]",
          "recipe[openstack-network::identity_registration]",
          "role[packtpub-os-network-openvswitch]",
          "role[packtpub-os-network-dhcp-agent]",
          "role[packtpub-os-network-metadata-agent]",
          "role[packtpub-os-network-server]"
        ]
    
      # virtualbox provider settings
      config.vm.provider "virtualbox" do |vb|
        vb.customize ["modifyvm", :id, "--cpus", 2]
        vb.customize ["modifyvm", :id, "--memory", 2048]
        vb.customize ["modifyvm", :id, "--nicpromisc2", "allow-all"]
        vb.customize ["modifyvm", :id, "--nicpromisc3", "allow-all"]
      end
    
      # OpenStack Controller 
     
      config.vm.define :controller1 do |controller1|
        controller1.vm.hostname = "controller1"
        controller1.vm.box = "opscode-centos-6.5"
        controller1.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box"
    
        controller1.vm.network "forwarded_port", guest: 443, host: 9443     # forward to dashboard using ssl : dashboard-ssl
        controller1.vm.network "forwarded_port", guest: 8773, host: 9773    # forward to EC2 api : compute-ec2-api
        controller1.vm.network "forwarded_port", guest: 8774, host: 9774    # forward to Compute API : compute-api
        controller1.vm.network "private_network", ip: "192.168.47.10" 
        controller1.vm.network "private_network", ip: "172.16.11.10"  
    
        controller1.vm.provision :chef_client do |chef|
          chef.run_list = controller_run_list
          chef.environment = chef_environment
          # Where to find our Chef Server by providing the        authorization key
          chef.chef_server_url = "https://chef.packtpub.com:443"
         chef.validation_key_path = "/home/packtpub/chef repo/.chef/chef-validator.pem"
        end
      end
    
     # OpenStack Compute 
    
      config.vm.define :compute1 do |compute1|
        compute1.vm.hostname = "compute1"
        compute1.vm.box = "opscode-centos-6.5"
        compute1.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box"
        compute1.vm.network "private_network", ip: "192.168.47.11"
        compute1.vm.network "private_network", ip: "172.16.11.11"
    
        compute1.vm.provision :chef_client do |chef|
          chef.run_list = [ "role[packtpub-os-compute-worker]" ]
          chef.environment = chef_environment
         # Where to find our Chef Server by providing the authorization key
          chef.chef_server_url = "https://chef.packtpub.com:443"
         chef.validation_key_path = "/home/packtpub/chef-repo/.chef/chef-validator.pem"
        end
      end 
    end
  • Cooking environment: We need to define our Chef environment to accomplish the environment setup within Vagrant.
    Note

    Use different environments for development and production to maintain cookbook changes in isolation.

    You can create a development environment in many ways; from the Chef server GUI or via the Knife command line, as follows:

    # knife environment create vagrant-packtpub -d "PacktPub Testing Environment"
    

    Our Chef environment file looks like the following:

    {
      "name": "vagrant-packtpub",
      "description": "PacktPub Testing Environment", 
     
      "cookbook_versions": {
      },
      "json_class": "Chef::Environment",
      "chef_type": "environment",
      "default_attributes": {
      },
      "override_attributes": {
        "mysql": {
          "allow_remote_root": true,
          "root_network_acl": "%"
        },
        "openstack": {
          "identity": {
            "bind_interface": "eth1"
          },
          "endpoints": {
            "host": "192.168.47.10",
            "mq": {
              "host": "192.168.47.10"
            },
            "db": {
              "host": "192.168.47.10"
            },
            "developer_mode": true,
            "network": {
              "debug": "True",
              "dhcp": {
                "enable_isolated_metadata": "True"
              },
              "metadata": {
                "nova_metadata_ip": "192.168.47.10"
              },
              "openvswitch": {
                "network_vlan_ranges": "physnet1:1000:2999",
                "tenant_network_type": "vlan",
                "external_network_bridge_interface": "eth2"
              },
              "api": {
                "bind_interface": "eth1"
              }
            },
            "image": {
              "api": {
                "bind_interface": "eth1"
              },
              "registry": {
                "bind_interface": "eth1"
              },
              "image_upload": true,
              "upload_images": [
                "centos",
                "cirros"
              ],
              "upload_image": {
                    "centos": "http://cloud.centos.org/centos/7/devel/ CentOS-7-Atomic-CloudDockerHost-20140820_05.qcow2",
                "cirros": "https://launchpad.net/cirros/trunk/0.3.0/ +download/cirros-0.3.0-x86_64-disk.img"
              }
            },
            "compute": {
              "xvpvnc_proxy": {
                "bind_interface": "eth1"
              },
              "novnc_proxy": {
                "bind_interface": "eth1"
              },
              "libvirt": {
                "virt_type": "qemu"
              },
              "network": {
                "public_interface": "eth1",
                "service_type": "neutron"
              },
              "config": {
                "ram_allocation_ratio": 5.0
              }
            }
          }
        }
      }
    }

    As we are using version control, it might be more convenient to create a new directory under chef-repo named; environments, which will hold our environments.

    Additionally, this will help us test cookbooks in different versions with several specific attributes and bring them from development to staging, finishing with promoting them into production. Under chef-repo, create an environments directory, where the vagrant-packtpub.rb file will be placed:

    packtpub@workstation:/chef repo$ git add environments/vagrant-packtpub.rb
    packtpub@workstation:/chef repo$ git commit -a -m "First OpenStack Environment"
    packtpub@workstation:/chef repo$ git push 
    

    Now, you can create the environment on the Chef server from our vagrant-packtpub.rb file by the means of the Knife command line:

    packtpub@workstation:/chef repo$ knife environment from file vagrant-packtpub.rb
    
  • Push the button: At this point, we've done a lot of preparation and configuration to test and deploy OpenStack. Vagrant and Chef work in tandem with each other to bring a test environment with less pain and more simplicity. Everything is in place; what we need to do is to just push the button.

    Set an environment file to specify which Vagrantfile to use:

    packtpub@workstation $ export VAGRANT_VAGRANTFILE=vagrant-packtpub
    

    Start the nodes:

    packtpub@workstation $ vagrant up controller1
    packtpub@workstation $ vagrant up compute1