Vagrant Dev EnvironmentToday, we are going to learn how to setup an environment with the awesome tool that any DevOps should know, Vagrant.

Behind this name is a wonderful software which automates the use of virtual machines (VMs) to create reproducible environments on-the-fly.

By creating a simple configuration file, within minutes you will have a fresh virtual machine started and provisioning without any other human interaction. The Vagrant Dev Environment!

Since Vagrant is not a pure virtualization tool by itself, it makes use of providers to do the virtualization such as VMWare, VirtualBox, etc…

And what a better way to demonstrate the power of this tool if not by setting up a distributed file system!

And this is a good thing because RozoFS is exactly what we are going to need. RozoFS is a high performance and scalable open source distributed file system.

You may take a look at what they do, it’s pretty interesting! http://rozosystems.com/

rozofs_logo

This demonstration will go as follows: first we will setup the RozoFS cluster, then we will run some rozo commands to show how it works.

In this tutorial, I will suppose that Vagrant and VirtualBox are already installed in your computer, if not here are the download links:

That being said, let’s get to the heart of the matter!

The Vagrant file

The Vagrant file will be the heart of our environment. It contains all the instructions to setup our system.

So to start, create a text file named Vagrantfile and copy paste the code below:

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

Vagrant.configure(2) do |config|
        file_to_disk = "./tmp/large_disk_rozo01.vdi"
        node.vm.box = "bento/ubuntu-14.04"
        node.vm.hostname = "rozo01"
        node.vm.network "private_network", ip: "10.0.42.11"
        node.vm.provider :virtualbox do |vb|
            vb.cpus = 2
            vb.memory = 2048
            vb.customize ['createhd', '--filename', file_to_disk, '--size', 50 * 1024]
            vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk]
        end
end

Basically, here we have defined all the basic stuff for a VM : Operating System, hostname, IP, disk and the provider (VirtualBox in our case).

But this will create only one VM, and it’s not really what we need. Since we are building a cluster, we will need more machines, so let’s modify this Vagrantfile to look more like our goal.

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

Vagrant.configure(2) do |config|
    (2..4).each do |i|
        file_to_disk = "./tmp/large_disk_rozo0#{i}.vdi"
        config.vm.define "rozo0#{i}" do |node|
            node.vm.box = "bento/ubuntu-14.04"
            node.vm.hostname = "rozo0#{i}"
            node.vm.network "private_network", ip: "10.0.42.1#{i}"
            node.vm.provider :virtualbox do |vb|
                vb.cpus = 2
                vb.memory = 2048
                unless File.exist?(file_to_disk)
                    vb.customize ['createhd', '--filename', file_to_disk, '--size', 50 * 1024]
                end
                vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk]
            end
        end
    end
end

So now it will deploy 3 VM’s with the same configuration except for the hostname and IP.

Then we will need to execute some shell commands into each VM. So for that, there is a vagrant instruction that allows us to run a shell command just after the VM creation;

node.vm.provision "shell", inline:

The shell commands that we need to run will install and configure everything for RozoFS.

Let’s see now how our Vagrantfile looks.

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

Vagrant.configure(2) do |config|
    (2..4).each do |i|
        file_to_disk = "./tmp/large_disk_rozo0#{i}.vdi"
        config.vm.define "rozo0#{i}" do |node|
            node.vm.box = "bento/ubuntu-14.04"
            node.vm.hostname = "rozo0#{i}"
            node.vm.network "private_network", ip: "10.0.42.1#{i}"
            node.vm.provider :virtualbox do |vb|
                vb.cpus = 2
                vb.memory = 2048
                unless File.exist?(file_to_disk)
                    vb.customize ['createhd', '--filename', file_to_disk, '--size', 50 * 1024]
                end
                vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk]
            end
            node.vm.provision "shell", inline: <<-SHELL
                wget -O - http://dl.rozofs.org/deb/devel@rozofs.com.gpg.key | apt-key add -
                echo deb http://dl.rozofs.org/deb/master $(lsb_release -sc) main | tee /etc/apt/sources.list.d/rozofs.list
                apt-get update
                apt-get install -y rozofs-storaged
                apt-get install -y rozofs-exportd
                apt-get install -y rozofs-rozofsmount
                apt-get install -y rozofs-manager-lib
                apt-get install -y rozofs-manager-cli
                apt-get install -y rozofs-manager-agent
                apt-get install -y rozofs-rozodiag
                apt-get install -y nagios-plugins-rozofs
                apt-get install -y vim
                mkdir -p /srv/rozofs/storages/storage_1_#{i}
                mkfs.ext4 /dev/sdb -F
                mount /dev/sdb /srv/rozofs/storages/storage_1_#{i}
                /etc/init.d/rozofs-storaged restart
                cp /vagrant/storage.conf /etc/rozofs/storage.conf
                sed -i \'s/storage_1_1/storage_1_#{i}/\' /etc/rozofs/storage.conf
                sed -i \'s/sid = 1/sid = #{i}/\' /etc/rozofs/storage.conf
                /etc/init.d/rozofs-storaged restart
            SHELL
        end
    end
end

Finally we need to declare one more VM for our master rozo node. The reason why it’s not included in the first loop is because this host needs a specific shell command to run in it.

So here is the final Vagrantfile:

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

Vagrant.configure(2) do |config|
    (2..4).each do |i|
        file_to_disk = "./tmp/large_disk_rozo0#{i}.vdi"
        config.vm.define "rozo0#{i}" do |node|
            node.vm.box = "bento/ubuntu-14.04"
            node.vm.hostname = "rozo0#{i}"
            node.vm.network "private_network", ip: "10.0.42.1#{i}"
            node.vm.provider :virtualbox do |vb|
                vb.cpus = 2
                vb.memory = 2048
                unless File.exist?(file_to_disk)
                    vb.customize ['createhd', '--filename', file_to_disk, '--size', 50 * 1024]
                end
                vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk]
            end
            node.vm.provision "shell", inline: <<-SHELL
                wget -O - http://dl.rozofs.org/deb/devel@rozofs.com.gpg.key | apt-key add -
                echo deb http://dl.rozofs.org/deb/master $(lsb_release -sc) main | tee /etc/apt/sources.list.d/rozofs.list
                apt-get update
                apt-get install -y rozofs-storaged
                apt-get install -y rozofs-exportd
                apt-get install -y rozofs-rozofsmount
                apt-get install -y rozofs-manager-lib
                apt-get install -y rozofs-manager-cli
                apt-get install -y rozofs-manager-agent
                apt-get install -y rozofs-rozodiag
                apt-get install -y nagios-plugins-rozofs
                apt-get install -y vim
                mkdir -p /srv/rozofs/storages/storage_1_#{i}
                mkfs.ext4 /dev/sdb -F
                mount /dev/sdb /srv/rozofs/storages/storage_1_#{i}
                /etc/init.d/rozofs-storaged restart
                cp /vagrant/storage.conf /etc/rozofs/storage.conf
                sed -i \'s/storage_1_1/storage_1_#{i}/\' /etc/rozofs/storage.conf
                sed -i \'s/sid = 1/sid = #{i}/\' /etc/rozofs/storage.conf
                /etc/init.d/rozofs-storaged restart
            SHELL
        end
    end
    config.vm.define "rozomds" do |rozomds|
        rozomds.vm.box = "bento/ubuntu-14.04"
        rozomds.vm.hostname = "rozomds"
        rozomds.vm.network "private_network", ip: "10.0.42.11"
        file_to_disk = "./tmp/large_disk_rozo.vdi"
        file_to_disk_export = "./tmp/export_disk.vdi"
        rozomds.vm.provider :virtualbox do |vb|
            vb.cpus = 2
            vb.memory = 2048
            unless File.exist?(file_to_disk)
                vb.customize ['createhd', '--filename', file_to_disk, '--size', 50 * 1024]
            end
            vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium', file_to_disk]
            unless File.exist?(file_to_disk_export)
                vb.customize ['createhd', '--filename', file_to_disk_export, '--size', 50 * 1024]
            end
            vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', file_to_disk_export]
        end
        rozomds.vm.provision "shell", inline: <<-SHELL
            wget -O - http://dl.rozofs.org/deb/devel@rozofs.com.gpg.key | apt-key add -
            echo deb http://dl.rozofs.org/deb/master $(lsb_release -sc) main | tee /etc/apt/sources.list.d/rozofs.list
            apt-get update
            apt-get install -y rozofs-storaged
            apt-get install -y rozofs-exportd
            apt-get install -y rozofs-rozofsmount
            apt-get install -y rozofs-manager-lib
            apt-get install -y rozofs-manager-cli
            apt-get install -y rozofs-manager-agent
            apt-get install -y rozofs-rozodiag
            apt-get install -y nagios-plugins-rozofs
            apt-get install -y vim
            mkdir -p /srv/rozofs/storages/storage_1_1
            mkfs.ext4 /dev/sdb -F
            mount /dev/sdb /srv/rozofs/storages/storage_1_1
            /etc/init.d/rozofs-storaged restart
            cp /vagrant/storage.conf /etc/rozofs/storage.conf
            sed -i \'s/storage_1_1/storage_1_1/\' /etc/rozofs/storage.conf
            sed -i \'s/sid = 1/sid = 1/\' /etc/rozofs/storage.conf
            /etc/init.d/rozofs-storaged restart
            rozo agent restart
            rozo volume expand 10.0.42.11 10.0.42.12 10.0.42.13 10.0.42.14 -E 10.0.42.11
            sleep 20
            rozo export create 1 -E 10.0.42.11
            sleep 20
            rozo mount create -E 10.0.42.11
        SHELL
    end
    config.vm.post_up_message = "
        vagrant ssh rozomds
        vagrant ssh rozo02
        vagrant ssh rozo03
        vagrant ssh rozo04"
end

If you want more details on a specific command, you may check Vagrant documentation, you will surely find what you want : https://www.vagrantup.com/docs/

Now, from where the Vagrantfile is located, run the following command:

vagrant up

It will execute all the instructions of the Vagrantfile and once it finishes you will get a fresh environment with RozoFS setup in it.

vagrant-diagram

So now, let’s run some RozoFS commands!

Test the environment with RozoFS commands

Like many cluster architectures, there is a master server. It will be from the master server that the RozoFS commands will be run.

So to connect to this master, named rozomds (according to our Vagrantfile), run the vagrant command:

vagrant ssh rozomds

Now we are inside our Vagrant box. From there, we are going to create an export and with one command we’ll mount it on our cluster.

First, let’s see if we already have an export. Run the following command:

root@rozomds:~# rozo node status -E 10.0.42.11
10.0.42.12:
- STORAGED: running
- ROZOFSMOUNT:
  - /mnt/rozofs@10.0.42.11/export_1: mounted
10.0.42.13:
- STORAGED: running
- ROZOFSMOUNT:
  - /mnt/rozofs@10.0.42.11/export_1: mounted
10.0.42.11:
- EXPORTD: running
- STORAGED: running
- ROZOFSMOUNT:
  - /mnt/rozofs@10.0.42.11/export_1: mounted
10.0.42.14:
- STORAGED: running
- ROZOFSMOUNT:
  - /mnt/rozofs@10.0.42.11/export_1: mounted

As you can see, we already have an export named export_1 and it’s already mounted on all our vagrant hosts.

The other command to see all your exports with more details is:

root@rozomds:~# rozo export get -E 10.0.42.11
EXPORTS:
- EXPORT 1:
  - vid: 1
  - root: /srv/rozofs/exports/export_1
  - md5: ''
  - squota: ''
  - hquota: ''

Note that the rozo command has a very detailed manual and it could be very useful! man rozo 

Now we want to create a new export. It’s as simple as following:

root@rozomds:~# rozo export create -n export_2 1 -E 10.0.42.11

Run the command again to get our exports:

root@rozomds:~# rozo export get -E 10.0.42.11
EXPORTS:
- EXPORT 1:
  - vid: 1
  - root: /srv/rozofs/exports/export_1
  - md5: ''
  - squota: ''
  - hquota: ''
- EXPORT 2:
  - vid: 1
  - root: /srv/rozofs/exports/export_2
  - md5: ''
  - squota: ''
  - hquota: ''

Now we mount our export:

root@rozomds:~# rozo mount create -e export_2 -E 10.0.42.11
10.0.42.12:
- export export_2 (eid=2) on /mnt/rozofs@10.0.42.11/export_2:
    configuration: added
    status: mounted
10.0.42.13:
- export export_2 (eid=2) on /mnt/rozofs@10.0.42.11/export_2:
    configuration: added
    status: mounted
10.0.42.11:
- export export_2 (eid=2) on /mnt/rozofs@10.0.42.11/export_2:
    configuration: added
    status: mounted
10.0.42.14:
- export export_2 (eid=2) on /mnt/rozofs@10.0.42.11/export_2:
    configuration: added
    status: mounted

Our export has been successfully mounted on all our hosts.

If you want to go further with RozoFS file system, this documentation will be very helpful: https://media.readthedocs.org/pdf/rozofs/latest/rozofs.pdf

Conclusion

In this article, we have seen how to build a functional distributed file system running anywhere with the help of Vagrant. Now you can provide to all your developers this Vagrantfile and they will be able to run the embedded solution from their laptop or their development machine.

About TrackIt

TrackIt is an international AWS cloud consulting, systems integration, and software development firm headquartered in Marina del Rey, CA.

We have built our reputation on helping media companies architect and implement cost-effective, reliable, and scalable Media & Entertainment workflows in the cloud. These include streaming and on-demand video solutions, media asset management, and archiving, incorporating the latest AI technology to build bespoke media solutions tailored to customer requirements.

Cloud-native software development is at the foundation of what we do. We specialize in Application Modernization, Containerization, Infrastructure as Code and event-driven serverless architectures by leveraging the latest AWS services. Along with our Managed Services offerings which provide 24/7 cloud infrastructure maintenance and support, we are able to provide complete solutions for the media industry.