Hey, I can DevOPS my Network too! – Define Nodes (Part 2)

Hey, I can DevOPS my Network too! – Define Nodes (Part 2)

In the previous post we prepped our environment in order to get everything ready to begin building out our environment. Which means we are now ready to finalize our node definitions to spin up our environment with Vagrant. So to begin with if you look at the drawing below, which was also shown in the intro post, and compare the drawing to our nodes.yml file which is in the root of the downloaded repo you will notice that router5 (r5) is missing.

ossrouting-bgp-drawing - New Page

Below is the original nodes.yml

---
- name: r1
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.101  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.12.11
      auto_config: "True"
      network_name: 01-to-02
      method: static
      type: private_network
    - ip: 192.168.14.11
      auto_config: "True"
      network_name: 01-to-04
      method: static
      type: private_network
    - ip: 192.168.31.11
      auto_config: "True"
      network_name: 03-to-01
      method: static
      type: private_network
    - ip: 1.1.1.10
      auto_config: "True"
      network_name: 1-1-1
      method: static
      type: private_network
- name: r2
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.102  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.23.12
      auto_config: "True"
      network_name: 02-to-03
      method: static
      type: private_network
    - ip: 192.168.12.12
      auto_config: "True"
      network_name: 01-to-02
      method: static
      type: private_network
    - ip: 2.2.2.10
      auto_config: "True"
      network_name: 2-2-2
      method: static
      type: private_network
- name: r3
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.103  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.31.13
      auto_config: "True"
      network_name: 03-to-01
      method: static
      type: private_network
    - ip: 192.168.23.13
      auto_config: "True"
      network_name: 02-to-03
      method: static
      type: private_network
    - ip: 3.3.3.10
      auto_config: "True"
      network_name: 3-3-3
      method: static
      type: private_network
- name: r4
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.104  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.14.14
      auto_config: "True"
      network_name: 01-to-04
      method: static
      type: private_network
    - ip: 192.168.31.14
      auto_config: "True"
      network_name: 03-to-01
      method: static
      type: private_network
    - ip: 192.168.41.14
      auto_config: "True"
      network_name: utopia
      method: static
      type: private_network
    - ip: 4.4.4.10
      auto_config: "True"
      network_name: 4-4-4
      method: static
      type: private_network

So let’s first add router5 (r5) to our nodes.yml file.

Open up nodes.yml with your editor of choice and add the following to the end of the file.

- name: r5
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.105  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.15.15
      auto_config: "True"      
      network_name: 01-to-05
      method: static
      type: private_network
    - ip: 192.168.51.15
      auto_config: "True"
      network_name: utopia
      method: static
      type: private_network
    - ip: 5.5.5.10
      auto_config: "True"
      network_name: 5-5-5
      method: static
      type: private_network

If you also notice, router1 (r1) is missing the interface to connect to the newly added router5 (r5) as well. So we will need to go ahead and add that interface to router1 (r1) which is shown below in bold.

- name: r1
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.101  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.12.11
      auto_config: "True"
      network_name: 01-to-02
      method: static
      type: private_network
    - ip: 192.168.14.11
      auto_config: "True"
      network_name: 01-to-04
      method: static
      type: private_network
    - ip: 192.168.15.11
      auto_config: "True"
      network_name: 01-to-05
      method: static
      type: private_network
    - ip: 192.168.31.11
      auto_config: "True"
      network_name: 03-to-01
      method: static
      type: private_network
    - ip: 1.1.1.10
      auto_config: "True"
      network_name: 1-1-1
      method: static
      type: private_network

So now the whole nodes.yml file should look like below.

---
- name: r1
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.101  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.12.11
      auto_config: "True"
      network_name: 01-to-02
      method: static
      type: private_network
    - ip: 192.168.14.11
      auto_config: "True"
      network_name: 01-to-04
      method: static
      type: private_network
    - ip: 192.168.15.11
      auto_config: "True"
      network_name: 01-to-05
      method: static
      type: private_network
    - ip: 192.168.31.11
      auto_config: "True"
      network_name: 03-to-01
      method: static
      type: private_network
    - ip: 1.1.1.10
      auto_config: "True"
      network_name: 1-1-1
      method: static
      type: private_network
- name: r2
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.102  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.23.12
      auto_config: "True"
      network_name: 02-to-03
      method: static
      type: private_network
    - ip: 192.168.12.12
      auto_config: "True"
      network_name: 01-to-02
      method: static
      type: private_network
    - ip: 2.2.2.10
      auto_config: "True"
      network_name: 2-2-2
      method: static
      type: private_network
- name: r3
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.103  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.31.13
      auto_config: "True"
      network_name: 03-to-01
      method: static
      type: private_network
    - ip: 192.168.23.13
      auto_config: "True"
      network_name: 02-to-03
      method: static
      type: private_network
    - ip: 3.3.3.10
      auto_config: "True"
      network_name: 3-3-3
      method: static
      type: private_network
- name: r4
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.104  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.14.14
      auto_config: "True"
      network_name: 01-to-04
      method: static
      type: private_network
    - ip: 192.168.31.14
      auto_config: "True"
      network_name: 03-to-01
      method: static
      type: private_network
    - ip: 192.168.41.14
      auto_config: "True"
      network_name: utopia
      method: static
      type: private_network
    - ip: 4.4.4.10
      auto_config: "True"
      network_name: 4-4-4
      method: static
      type: private_network
- name: r5
  box: ubuntu/trusty64
  mem: 512
  cpus: 1
  ansible_ssh_host_ip: 192.168.250.105  #HostOnly interface
  interfaces:  #Internal only interfaces
    - ip: 192.168.15.15
      auto_config: "True"
      network_name: 01-to-05
      method: static
      type: private_network
    - ip: 192.168.51.15
      auto_config: "True"
      network_name: utopia
      method: static
      type: private_network
    - ip: 5.5.5.10
      auto_config: "True"
      network_name: 5-5-5
      method: static
      type: private_network

At this point you are probably wondering what all of these settings are for in nodes.yml, correct? So let’s go over what they are for.

  • name: defines the name of the node that Vagrant will define as the hostname
  • box: defines the Vagrant Box that will be used as the OS for the node
  • mem: defines the amount of memory to allocate to the node
  • cpus: defines the number of vCPUS to allocate to the node
  • ansible_ssh_host_ip: defines the interface/IP that will be defined as eth1 and used for all Ansible related tasks
  • interfaces:
    • ip: defines the IP address for each additional interface to create
    • auto_config: defines if Vagrant should automatically configure the interface with the defined IP address. If set to False you can configure /etc/network/interfaces manually outside of Vagrant.
    • network_name: defines the internal network name that VirtualBox will place the interface on. Node interfaces need to reside on the same network_name in order to communicate internally to VirtualBox
    • method: defines if the interface should be static or dhcp
    • type: defines if interface should be NAT, Bridged, Internal (“private_network”) or Host-Only…more info here. We are using private_network which is internal only to the nodes. Not accessible from our HostOS.

Now let’s go ahead and commit our changed code to GitHub.
Check the status of our local git repo.

git status
........
On branch dev
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

	modified:   nodes.yml

no changes added to commit (use "git add" and/or "git commit -a")

The above shows us that nodes.yml has been modified and we should commit the changes.

git commit -a

Now type in a description of whatever you want…I am using “updated nodes.yml in preparation of Vagrant deployment” and save the file.

[dev a06b879] updated nodes.yml in preparation of Vagrant deployment
 1 file changed, 26 insertions(+)

Now let’s push our changes to GitHub into our dev branch.

git push --set-upstream origin dev
.........
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 413 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To https://github.com/everythingshouldbevirtual/vagrant-ansible-routing-template.git
   caf5002..a06b879  dev -> dev
Branch dev set up to track remote branch dev from origin.

The other important file here at this time is our Vagrantfile. This is the file that Vagrant will use to spin up the nodes that we have defined in our nodes.yml file. There should not be any changes required at this time in this file. However if you do decide to make changes, make sure to commit those changes and push up to your GitHub repo. Below is what our Vagrantfile looks like.

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

# Ensure yaml module is loaded
require 'yaml'

# Read yaml node definitions to create **Update nodes.yml to reflect any changes
nodes = YAML.load_file('nodes.yml')

Vagrant.configure(2) do |config|
#  config.ssh.insert_key = false
#  config.vm.provision :shell, path: "bootstrap.sh"

  nodes.each do |nodes|
    config.vm.define nodes["name"] do |node|
      node.vm.hostname = nodes["name"]
      node.vm.box = nodes["box"]
#      node.vm.provision :shell, path: "bootstrap_ansible.sh"
      if nodes["ansible_ssh_host_ip"] != "None"
        node.vm.network "private_network", ip: nodes["ansible_ssh_host_ip"]
      end
      ints = nodes["interfaces"]
      ints.each do |int|
        if int["method"] == "static" and int["type"] == "private_network" and int["network_name"] != "None" and int["auto_config"] == "True"
          node.vm.network "private_network", ip: int["ip"], virtualbox__intnet: int["network_name"]
        end
        if int["method"] == "static" and int["type"] == "private_network" and int["network_name"] != "None" and int["auto_config"] == "False"
          node.vm.network "private_network", ip: int["ip"], virtualbox__intnet: int["network_name"], auto_config: false
        end
        if int["method"] == "static" and int["type"] == "private_network" and int["network_name"] == "None" and int["auto_config"] == "True"
          node.vm.network "private_network", ip: int["ip"]
        end
        if int["method"] == "static" and int["type"] == "private_network" and int["network_name"] == "None" and int["auto_config"] == "False"
          node.vm.network "private_network", ip: int["ip"], auto_config: false
        end
        if int["method"] == "dhcp" and int["type"] == "private_network"
          node.vm.network "private_network", type: "dhcp"
        end
      end
      node.vm.synced_folder ".", "/vagrant"
      node.vm.provider "virtualbox" do |v|
        v.memory = nodes["mem"]
        v.cpus = nodes["cpus"]
      end
    end
  end
  config.vm.provision :ansible do |ansible|
    ansible.playbook = "bootstrap.yml"
  end
#  if Vagrant.has_plugin?("vagrant-cachier")
#    config.cache.scope = :box
#  end
end

So this concludes our node definitions which we will be using here on out for this series.

Up next…Vagrant UP

About Larry Smith Jr.

vExpert 2013-2016 | Old-School coder coming back around to my roots #DevOPS and #automation | #Ansible junky!

9 thoughts on “Hey, I can DevOPS my Network too! – Define Nodes (Part 2)

  1. Pingback: Hey, I can DevOPS my Network too! – Prep-Work (Part 1) - Everything Should Be Virtual

  2. Hey Larry. Is using the YAML file just for the purpose demonstration or do you see some benefit in having the configuraiton split in this way (scaling perhaps)?

    Also, I wonder, is there some way the repetitive parts of the YAML file can be specified for all hosts just the once (in the YAML file or perhaps the Vagrantfile) or variablized in some way?

    • I find that using the separate yaml file works much better for me for keeping more complex configurations cleaner. But may not be the best choice for all. You can definitely change the repetitive parts to use single variables. But at least for me I have found as I begin mixing and matching different boxes, networking and etc. it works very well. However I have been working on some additional ways to add functionality so definitely stay tuned for that.

  3. Pingback: Hey, I can DevOPS my Network too! – Vagrant Up (Part 3) - Everything Should Be Virtual

    • I removed the previous message. Too early and not enough coffee. The git commit -a command is handling the addition of the changed file in the example. Which is just a shortcut of doing the following.
      git add . or git add -A and then git commit

Leave a Reply

Your email address will not be published. Required fields are marked *

*