Install and run the Cloonix network emulator on Packet.net

December 11, 2017

This tutorial shows how to set up the Cloonix network emulator on a Packet.net server. It builds on top of my previous post about how to set up a virtualization server on Packet.net. Now, I focus on a specific case: setting up the Cloonix network emulator on the virtualization server. You should read my previous post before reading this one.

Running Cloonix on a remote server enables users to work with more complex network emulation scenarios than would be possible on a standard laptop computer. For example. Cloonix recently added a feature which allows users to run Cisco router images in a Cloonix network emulation scenario. Cisco router images require a large amount of computer resources so I cannot run more than a few on my personal laptop computer. If I use a remote Packet server, I could run dozens of Cisco images in a network emulation scenario if I wanted to.

In this post, I will set up a Cloonix network emulation server on Packet.net so it can be started, stopped, and restarted relatively quickly.

Table of Contents

  1. Cloonix v37 overview
  2. Packet.net overview
  3. Tutorial summary
  4. Start a server and attach storage
  5. Load Files onto Block Storage Disk
  6. Set Up Cloonix on Server
  7. Run Cloonix on Packet.net
  8. Shutting Down so You Can Start Up Again
  9. Starting up again
  10. Example: Emulating Network of Cisco Routers on Cloonix
  11. Remote Cloonix Servers
  12. Conclusion
  13. Appendix A: 3router script

Bash prompt formats

In this post, I am jumping around a lot between my local PC and multiple userids on a remote Packet server. To show which computer and which user I ams using in the command examples, I will include the bash prompt in all listings.

The prompts will be:

  • local@T420:$ → My local account on my personal Linux computer

  • root@packet:# → The default root account on the Packet.net server

  • brian@packet:$ → The user account I created on the Packet.net server which, in my examples, is brian.

  • # → A command run on a node in the network emulation scenario

Cloonix v37 overview

Cloonix is an open-source network emulator that can spawn QEMU-KVM guests and link them together through sockets emulating LAN wires. It can also copy files between the host computer (or remote computers) and guests and it can run commands in the guests without any prior configuration1.

New features in version 37

Cloonix is an active project that is regularly updated. The newest version is version 37. The last time I used Cloonix, I used version 33. Below, I highlight some of the major changes in Cloonix since version 33.

Cloonix now supports Cisco Cloud Services Routers. The Cloonix web site provides instructions on how to build a QCOW image from a Cisco CSR 1000v ISO image. Users must provide their own Cisco software because it would be illegal for Cloonix to offer pre-built Cisco images. The main reason I am using a Packet.net server to run Cloonix is because Cisco router images require more CPU and RAM resources than my laptop computer support. If you use only open-source software to build and emulate network nodes, Cloonix works well on any modern laptop computer.

In version 37, Cloonix added two new client commands: cloonix_osh and cloonix_ocp. These are similar to the already-existing cloonix_ssh and cloonix_scp commands, except that they work via Linux sockets connected to the Cloonix nat object. The targeted quest’s DHCP-configured interface is connected to the nat object. This enables Cloonix users to connect to nodes running proprietary operating systems, like Cisco, that cannot be pre-configured or cannot be modified to run the Cloonix agent.

Packet.net overview

Packet is a hardware-as-a-service vendor that provides dedicated servers on demand at very low cost, which enables users to perform activities they could not run on a normal personal computer.

Since each Packet server is a dedicated server, users can run any hypervisor on the Packet server. It is usually not possible to run a hypervisor on a VM provided by other cloud vendors like Amazon2. For now, Packet.net seems to me to offer the most cost-effective way to run open-source network emulators that use KVM virtual machines in the cloud.

In my previous blog post about building a virtualization server on Packet, I described how to deploy a Packet server and attach it to a block storage device using the Packet web app. You must follow the procedures in my previous post before starting the procedures in this post.

Tutorial summary

After completing the procedures in my previous post, I assume you already have the following infrastructure set up on your Packet.net project:

  1. A Packet project is already created and SSH keys saved
  2. The project contains a block storage volume already formatted with an ext4 file system
  3. That volume’s file system has ACLs configured to allow members of the sims group full privileges on all files and folders created on the volume
  4. The volume is not attached currently to a server
  5. No Packet servers are deployed

This tutorial will walk through the Cloonix-set-up-on-Packet process in two phases:

  1. Phase 1: Deploy a small server which is used to create all directories and load all required Cloonix files onto the block storage volume.
    • This minimizes cost while we set up
    • We will also run a simple Cloonix network emulation project and save the project files on the block storage volume, as a demonstration of how to use Cloonix in this environment.
    • Then we will detach the block storage volume, shut the server down, and delete the server.
  2. Phase 2: Deploy a powerful — and more expensive — server to run a complex Cloonix network emulation using resource-hungry Cisco images.
    • I will demonstrate how this procedure allows users to swap the “brains” of the Cloonix emulator with more powerful servers as needed, while preserving the emulator’s data.
    • We will re-attach the block storage volume and rebuild the Cloonix system from files stored on the volume.

Start a server and attach storage

Use the Packet.net web app to provision a new Packet server in your project server by performing the following steps, which are described in more detail in my previous post about setting up a virtualization server:

  1. Start a small Type 0 server using the Packet web app
  2. Attach the block storage volume to the server using the Packet web app
  3. Log into the server using SSH from your Windows PC, Mac, or Linux PC).

For example, to log into the new Packet server from a Linux or Mac computer, run the following command:

local@T420:$ ssh -X -i /.ssh/packet root@203.0.113.25

In this example, the server’s IP address is 203.0.113.253 and the private SSH key is in the file ~/.ssh/packet.

Next, perform the following steps in the terminal window running on the Packet server. All these steps are also described in more detail in my previous post:

  1. Create a new user
    • Assign the user to the sims and sudo groups
    • Copy SSH keys to the new user
    • Log out and then log back in as the new user
  2. Mount the block storage volume

The commands I use are listed below. In my example, the user I create has username brian:

root@packet:# addgroup sims
root@packet:# adduser brian
root@packet:# usermod -aG sims brian 
root@packet:# usermod -aG sudo brian

Copy the SSH keys to the new user:

root@packet:# su brian
brian@packet:$ cd ~
brian@packet:$ mkdir ~/.ssh
brian@packet:$ chmod 700 ~/.ssh
brian@packet:$ sudo cat /root/.ssh/authorized_keys | tee /home/brian/.ssh/authorized_keys
brian@packet:$ chmod 600 ~/.ssh/authorized_keys

Log out of the server:

brian@packet:$ exit
root@packet:# exit

Login back in as the new user. For example:

local@T420:$ ssh -X -i /.ssh/packet brian@203.0.113.25

Then mount the partition on the block storage volume which, in this example, is /dev/mapper/volume-4d03ece6-part1.

brian@packet:$ sudo packet-block-storage-attach -m queue
brian@packet:$ sudo mkdir /mnt/disk1
brian@packet:$ sudo mount -t ext4 /dev/mapper/volume-4d03ece6-part1 /mnt/disk1
brian@packet:$ sudo echo '/dev/mapper/volume-4d03ece6-part1 /mnt/disk1 ext4 _netdev 0 0' | sudo tee -a /etc/fstab

Note that the ACLs for the block storage volume were configured in my previous post so I do not need to install the acl package again or change any ACLs at this time.

Load files onto block storage disk

Each Packet server come with SSD storage for the operating system and data files. When I compile Cloonix, the Cloonix files are installed on the SSD. However, I choose to keep all my Cloonix source files and all my Cloonix data files on the attached block storage volume.

I could choose to copy all these files to the SSD when starting a project and then copy any modified or new data files back to the block storage volume before I shut down and delete the server. However, I found it was easier to keep all files on the block storage volume when running Cloonix. Then I did not have to remember which files to copy back from the SSD to the block storage volume.

The block storage volume performance is fast enough for my needs. If you need very high performance, you might consider copying key files over to the SSD.

Load Cloonix source files onto block storage

Clone Cloonix code and compile it on the new server. You may need to install git:

brian@packet:$ sudo apt-get update
brian@packet:$ sudo apt-get install git
brian@packet:$ cd /mnt/disk1
brian@packet:$ git clone https://github.com/clownix/cloonix.git

The Cloonix source code and install scripts are now stored in the directory /mnt/disk1/cloonix/.

Updates

If you are updating existing Cloonix files on the block storage volume, run the following commands:

brian@packet:$ cd /mnt/disk1/cloonix
brian@packet:$ git pull

Load Cloonix file systems onto block storage

Download and create Cloonix project files on the block storage device so you can quickly access them every time you create a Cloonix server on Packet.

Go to the mounted block storage volume:

brian@packet:$ cd /mnt/disk1

Create Cloonix directories:

brian@packet:$ mkdir cloonix_data
brian@packet:$ mkdir cloonix_data/bulk

Download Cloonix file systems into the bulk directory. I chose the following Cloonix file systems for my experiments:

  • Debian Jessie – because, while it is an older release, it is used in most of the Cloonix demo scripts
  • Ubuntu Zesty – because the latest version of Ubuntu is nice to have

Run the following commands to download the required files. Note that these links may change as new version of Cloonix are released.

brian@packet:$ cd cloonix_data/bulk
brian@packet:$ wget http://cloonix.fr/bulk_stored/v-37-02/jessie.qcow2.xz
brian@packet:$ wget http://cloonix.fr/bulk_stored/v-38-00/zesty.qcow2.xz
brian@packet:$ unxz *.xz

I also downloaded a Cisco QCOW image and named it cisco_16.03.04.qcow2 so it works with the Cloonix Cisco demo script but I cannot provide the reader with a link. Readers must have their own legally-obtained Cisco ISO image and convert it to a QCOW image using the instructions in the Cloonix documentation. Then, download it to the bulk directory on the block storage device along with the other Cloonix file systems.

Load Cloonix demo scripts onto block storage

Download and unpack the Cloonix demo scripts to the block device:

brian@packet:$ cd /mnt/disk1/
brian@packet:$ wget http://cloonix.fr/demo_stored/v-37-02/cloonix_demo_all.tar.gz
brian@packet:$ tar -xvf cloonix_demo_all.tar.gz
brian@packet:$ rm cloonix_demo_all.tar.gz

This will create a directory named /mnt/disk1/cloonix_demo_all containing the demo files. Remember, because we set up ACLs for group permissions on this volume, all the files are in group sims so we can make the files available to other users by adding those users to the sims group.

Set up Cloonix on server

All the Cloonix files are stored on the block storage volume mounted at /mnt/disk1/. When we compile Cloonix, the executable and data files will be built on the Packet server’s SSD in the directory /usr/local/bin/cloonix/. This means that when we finish a project and delete the server, we will lose the Cloonix installation. We have to build Cloonix every time we start a new server.

To build Cloonix, set up KVM for all users. KVM must be enabled for users before we run the Cloonix install script.

brian@packet:$ sudo chmod 666 /dev/kvm

Compile Cloonix from the source files stored on the block storage volume:

brian@packet:$ cd /mnt/disk1/cloonix
brian@packet:$ sudo ./install_depends build
brian@packet:$ sudo apt-get install wireshark-qt 
brian@packet:$ sudo ./allclean  
brian@packet:$ ./doitall

Edit the Cloonix configuration file so that Cloonix will look for its working directories on the block storage volume:

brian@packet:$ sudo nano /usr/local/bin/cloonix/cloonix_config

Change the default directories at the top of the file to:

CLOONIX_WORK=/mnt/disk1/cloonix_data
CLOONIX_BULK=/mnt/disk1/cloonix_data/bulk

Save the file.

Run Cloonix on Packet.net

Users can create network emulation scenarios by building nodes and networks in the Cloonix GUI. In my example, I will use a cloonix_cli script to build a network quickly.

I created a three-router network script in Appendix A: The 3router.sh script. Copy the script from Appendix A so you can paste it into a file on the server.

I chose to create a directory named brian to store my scripts:

brian@packet:$ mkdir /mnt/disk1/cloonix_demo_all/brian
brian@packet:$ cd /mnt/disk1/cloonix_demo_all/brian
brian@packet:$ nano 3router.sh

Then paste the script text from Appendix A into the file. Save the file and then set the permissions to enable running the file:

brian@packet:$ chmod 775 3router.sh

Finally, run the file:

brian@packet:$ ./3router.sh

If you have configured everything correctly on the remote server and on your host PC, you will see the Cloonix GUI appear in an X window on your host PC and it will eventually display a three router network, as shown below.

Cloonix GUI X window: results of 3router script.

To test the emulation, double-click on the node PC-1 and, in the Xterm window that appears, enter the following command:

# ping -c 2 192.168.2.1

This should send ICMP packets to node PC-2. You should see successful ping messages in the Xterm window, as shown below:

Ping command running on emulated Linux node.

Now you may perform more investigations and make configuration changes.

Shutting Down so You Can Start Up Again

As discussed in my previous post, leaving a Packet server running while you are not using it costs you money. Even when the server is stopped, Packet will bill you the same hourly rate. You must delete the server to stop the charges.

We need to shut down the Cloonix server properly before deleting it so that our files are saved. The procedures we followed to set up Cloonix ensures that our source code and our data files — such as topology scripts and file systems — will be saved on the block storage volume and can be used when we rebuild a new Cloonix server.

First, save your work. Save the network topology and the configuration changes made on each node in the topology so you can restart the network emulation using the saved state in the future. Run the following command to save all files related to the network emulation scenario:

brian@packet:$ cloonix_cli nemo sav topo /mnt/disk1/cloonix_data/3routers

Then, kill the emulation:

brian@packet:$ cloonix_cli nemo kil

Remember that the next person to use Cloonix may have a different username configured on their server. Set the permissions of the new directory 3routers that Cloonix created when saving the topology so that users from the sims group can access the files:

brian@packet:$ chmod 775 /mnt/disk1/cloonix_data/3routers

Then, unmount and detach the block storage volume:

brian@packet:$ cd
brian@packet:$ umount /mnt/disk1
brian@packet:$ sudo packet-block-storage-detach

Then, once again, detach the block storage volume and delete the Packet server via the Packet.net web app.

The data we saved on the block storage volume remains there and we can use it when we are ready to run Cloonix again, on a new Packet server. While it is active, the block storage volume costs less than $1.50 per month.

Starting up again

At this point, we have a block storage volume on Packet.net that contains all the files we need to start up a new server, build Cloonix, and resume any activity from files we saved during our previous experiments.

Let’s start up a new server and get to the point where we can resume from saved files.

Also, let’s use a more powerful server this time. Previously, we used a Type 0 server which is low-cost but also low-powered. This time, start a Type 1 Packet server. This demonstrates how the “block storage volume method” enables us to swap out the “compute engine” any time we need more power while reusing all the config files and other data from previous experiments.

Follow the steps from the Start a server and attach storage chapter, above. Then, set up Cloonix on the new server using the steps from the Set up Cloonix on server chapter, above.

I summarize all the commands below:

Login to the new Packet server as root

local@T420:$ ssh -X -i /.ssh/packet root@203.0.113.25

Create new user. Remember, user must be a member of group sims.

root@packet:# addgroup sims
root@packet:# adduser brian
root@packet:# usermod -aG sims brian 
root@packet:# usermod -aG sudo brian
root@packet:# su brian
brian@packet:$ cd ~
brian@packet:$ mkdir ~/.ssh
brian@packet:$ chmod 700 ~/.ssh
brian@packet:$ sudo cat /root/.ssh/authorized_keys | tee /home/brian/.ssh/authorized_keys
brian@packet:$ chmod 600 ~/.ssh/authorized_keys

Log out of the server:

brian@packet:$ exit
root@packet:# exit

From your local PC, login as new user:

local@T420:$ ssh -X -i /.ssh/packet brian@203.0.113.25

Remember to also start Xming on your PC or X-Quartz on your Mac. If you are using a Linux PC, X will already be started.

Then, mount the block storage volume

brian@packet:$ sudo packet-block-storage-attach -m queue
brian@packet:$ sudo mkdir /mnt/disk1
brian@packet:$ sudo mount -t ext4 /dev/mapper/volume-e7bbc5cb-part1 /mnt/disk1
brian@packet:$ sudo echo '/dev/mapper/volume-e7bbc5cb-part1 /mnt/disk1 ext4 _netdev 0 0' | sudo tee -a /etc/fstab    

Compile Cloonix from the source files stored on the block storage volume:

brian@packet:$ cd /mnt/disk1/cloonix
brian@packet:$ sudo ./install_depends build
brian@packet:$ sudo apt-get install wireshark-qt
brian@packet:$ sudo ./allclean  
brian@packet:$ sudo chmod 666 /dev/kvm
brian@packet:$ ./doitall

Edit the Cloonix configuration file so that Cloonix will look for its working directories on the block storage volume:

brian@packet:$ sudo nano /usr/local/bin/cloonix/cloonix_config

Change the default directories at the top of the file to:

CLOONIX_WORK=/mnt/disk1/cloonix_data
CLOONIX_BULK=/mnt/disk1/cloonix_data/bulk

Save the file.

Now, start the saved topology 3routers:

brian@packet:$ /mnt/disk1/cloonix_data/3routers/nemo.sh

This will start up the network emulation scenario from the saved state, with all configuration changes made during the previous experiments intact.

After completing any experiments, you may save the topology again and then kill it. Remember that you must use a new name every time you save. You cannot save over an existing topology.

brian@packet:$ cloonix_cli nemo sav topo /mnt/disk1/cloonix_data/3routers-v2

Then kill the emulation:

brian@packet:$ cloonix_cli nemo kil

Example: Cisco routers on Cloonix

As I wrote earlier, I am using Packet.net so I can run network emulation scenarios that cannot run on my personal laptop computer. For example, I can now run resource-hungry commercial router images in Cloonix. Cloonixv37 adds some features to support Cisco IOS-on-Linux images.

In this example, I will run the Cloonix Cisco script that is provided with the standard Cloonix demos. I have already downloaded and saved the Cisco file system on the block storage volume.

Go to the Cisco demo folder:

brian@packet:$ cd /mnt/disk1/cloonix_demo_all/cisco

NOTE: When I ran the Cisco demo script I found an error. I corresponded with the Cloonix developers and they told me to modify script and replace “mud” with “cnf” in all occurrences. So, if the Cisco script does not work for you, check the file and make this change.

Run the Cisco script:

brian@packet:$ ./cisco.sh

After the script runs, start the Cloonix GUI to view the topology:

Brian@packet:$ cloonix_gui nemo

Cisco servers stay red in the Cloonix GUI because they do not — and cannot — have the cloonix agent installed. But they are really running and you can connect to the Cisco terminal interface by double-clicking on each Cisco router on the Cloonix GUI.

The Cisco router password is “cisco”.

Cisco routers running on Packet.net server

Now we can add Cisco routers into network emulation experiments using the Cloonix network emulator.

Using a remote Cloonix Server

We’ve accessed the Cloonix GUI using X windows because this will work with your local PC for all major operating systems: Windows, Mac, and Linux. But, if you are using a Linux PC and would like a smoother GUI experience you may install Cloonix on both your local PC and on the remote Packet server and then configure your local PC as the Cloonix GUI and the remote Packet server as the Cloonix server.

First, install Cloonix on your local Linux PC:

local@T420:$ sudo apt-get update
local@T420:$ sudo apt-get install git
local@T420:$ cd ~
local@T420:$ git clone https://github.com/clownix/cloonix.git
local@T420:$ sudo chmod 666 /dev/kvm
local@T420:$ cd ~/cloonix
local@T420:$ sudo ./install_depends build
local@T420:$ sudo apt-get install wireshark-qt   
local@T420:$ ./doitall

Edit the Cloonix configuration file on the local PC so that the Cloonix GUI can connect to the remote Cloonix server. Change the IP address of the remote nemo server.

local@T420:$ sudo nano /usr/local/bin/cloonix/cloonix_config

Change the default configuration of the nemo server to:

CLOONIX_NET: nemo {
  cloonix_ip       127.0.0.1
  cloonix_port     43211
  cloonix_passwd   nemoclown
}

Then save the file.

Now, assuming you have started the Cloonix server nemo on the remote Packet.net server, you may run the Cloonix GUI on your local machine and interact with the network topology running on the remote server.

local@T420:$ cloonix_gui nemo

Cloonix server running on remote server, Cloonix GUI running on local PC.

Above, we see the Cloonix GUI running on my local laptop computer. The Cloonix server is running on a remote Packet server.

Conclusion

I showed how we can cost-effectively install and use the Cloonix network emulator on a powerful remote server provided by Packet.net. The main point of this post is to show how one can use the block storage to save project files and speed up the re-provisioning of new servers when you need them. This makes it easier to control costs since you must completely delete a server to stop charges, so you will want a way to rebuild your network emulation setup to a known state, quickly and relatively easily.

Similar projects

Similar work has been published related to running other network emulators on Packet.net. The GNS3 team described how to run the GNS3 network emulator on Packet.net, Justin Guagliata described how to run the EVE-NG network emulator on Packet.net, and the Packet.net team described how to run the Cisco VIRL network emulator on Packet.net.

Appendix A: The 3router.sh script


#!/bin/bash

#-------------------------------------------------------
# Variables
#
# Modify these variables to match the directory
# structure you created on your own system and to
# match the file system you chose to use
#-------------------------------------------------------
DIST=jessie
NET=nemo
ROUTER_NAME=router-
PC_NAME=PC-
CLOONIX_CONFIG=/usr/local/bin/cloonix/cloonix_config

#-------------------------------------------------------
# Set Cloonix Bulk directory from cloonix_config file
#-------------------------------------------------------
CLOONIX_BULK=$(cat $CLOONIX_CONFIG |grep CLOONIX_BULK | awk -F = "{print \$2}")
BULK=$(eval echo $CLOONIX_BULK)

#-------------------------------------------------------
# Start cloonix. Comment-out these two lines if we will
# already have Cloonix started before running this 
# script 
#-------------------------------------------------------

echo "Starting Cloonix"
cloonix_net ${NET}
cloonix_gui ${NET}
echo "Cloonix started"

#-------------------------------------------------------
# Start KVMs and define interfaces
# The sleep timers should be set to a value that works
# best on your computer. Since I am running this
# on a 5-year-old laptop, I set the sleep timers to a 
# higher value of 15 seconds 
#-------------------------------------------------------

echo "Building topology"

echo "adding NAT"
cloonix_cli ${NET} add nat nat01
cloonix_cli ${NET} add lan nat01 0 nat_lan


# Router-1
echo "Adding ${ROUTER_NAME}1"
cloonix_cli ${NET} add kvm ${ROUTER_NAME}1 1000 1 4 ${BULK}/${DIST}.qcow2 --balloon &
sleep 15
cloonix_cli ${NET} add lan ${ROUTER_NAME}1 0 lan06
cloonix_cli ${NET} add lan ${ROUTER_NAME}1 1 lan01
cloonix_cli ${NET} add lan ${ROUTER_NAME}1 2 lan03
cloonix_cli ${NET} add lan ${ROUTER_NAME}1 3 nat_lan

# Router-2
echo "Adding ${ROUTER_NAME}2"
cloonix_cli ${NET} add kvm ${ROUTER_NAME}2 1000 1 4 ${BULK}/${DIST}.qcow2 --balloon &
sleep 15
cloonix_cli ${NET} add lan ${ROUTER_NAME}2 0 lan04
cloonix_cli ${NET} add lan ${ROUTER_NAME}2 1 lan01
cloonix_cli ${NET} add lan ${ROUTER_NAME}2 2 lan02
cloonix_cli ${NET} add lan ${ROUTER_NAME}2 3 nat_lan

# Router-3
echo "Adding ${ROUTER_NAME}3"
cloonix_cli ${NET} add kvm ${ROUTER_NAME}3 1000 1 4 ${BULK}/${DIST}.qcow2 --balloon &
sleep 15
cloonix_cli ${NET} add lan ${ROUTER_NAME}3 0 lan05
cloonix_cli ${NET} add lan ${ROUTER_NAME}3 1 lan03
cloonix_cli ${NET} add lan ${ROUTER_NAME}3 2 lan02
cloonix_cli ${NET} add lan ${ROUTER_NAME}3 3 nat_lan

# PC-1
echo "Adding ${PC_NAME}1"
cloonix_cli ${NET} add kvm PC-1 1000 1 2 ${BULK}/${DIST}.qcow2 --balloon &
sleep 15
cloonix_cli ${NET} add lan ${PC_NAME}1 0 lan06
cloonix_cli ${NET} add lan ${PC_NAME}1 1 nat_lan

# PC-2
echo "Adding ${PC_NAME}2"
cloonix_cli ${NET} add kvm ${PC_NAME}2 1000 1 2 ${BULK}/${DIST}.qcow2 --balloon &
sleep 15
cloonix_cli ${NET} add lan ${PC_NAME}2 0 lan04
cloonix_cli ${NET} add lan ${PC_NAME}2 1 nat_lan

# PC-3
echo "Adding ${PC_NAME}3"
cloonix_cli ${NET} add kvm ${PC_NAME}3 1000 1 2 ${BULK}/${DIST}.qcow2 --balloon &
sleep 15
cloonix_cli ${NET} add lan ${PC_NAME}3 0 lan05
cloonix_cli ${NET} add lan ${PC_NAME}3 1 nat_lan

#-------------------------------------------------------
# Stop motion
#-------------------------------------------------------
cloonix_cli ${NET} cnf lay stop
sleep 1

#-------------------------------------------------------
# Set size of Cloonix Graph window
#-------------------------------------------------------
cloonix_cli ${NET} cnf lay width_height 574 489
sleep 1
cloonix_cli ${NET} cnf lay scale 216 212 574 489
sleep 1

#-------------------------------------------------------
# Move nodes to their final places in the graph
#-------------------------------------------------------
echo "Moving nodes in topology"
cloonix_cli ${NET} cnf lay abs_xy_kvm ${PC_NAME}3 218 402
cloonix_cli ${NET} cnf lay abs_xy_eth ${PC_NAME}3 0 0
cloonix_cli ${NET} cnf lay abs_xy_eth ${PC_NAME}3 1 239
cloonix_cli ${NET} cnf lay abs_xy_kvm ${PC_NAME}2 425 45
cloonix_cli ${NET} cnf lay abs_xy_eth ${PC_NAME}2 0 194
cloonix_cli ${NET} cnf lay abs_xy_eth ${PC_NAME}2 1 254
cloonix_cli ${NET} cnf lay abs_xy_kvm ${PC_NAME}1 1 49
cloonix_cli ${NET} cnf lay abs_xy_eth ${PC_NAME}1 0 94
cloonix_cli ${NET} cnf lay abs_xy_eth ${PC_NAME}1 1 37
cloonix_cli ${NET} cnf lay abs_xy_kvm ${ROUTER_NAME}3 221 253
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}3 0 154
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}3 1 264
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}3 2 15
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}3 3 301
cloonix_cli ${NET} cnf lay abs_xy_kvm ${ROUTER_NAME}2 291 118
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}2 0 48
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}2 1 227
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}2 2 160
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}2 3 298
cloonix_cli ${NET} cnf lay abs_xy_kvm ${ROUTER_NAME}1 131 128
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}1 0 260
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}1 1 57
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}1 2 117
cloonix_cli ${NET} cnf lay abs_xy_eth ${ROUTER_NAME}1 3 5
cloonix_cli ${NET} cnf lay abs_xy_lan lan05 216 325
cloonix_cli ${NET} cnf lay abs_xy_lan lan02 262 186
cloonix_cli ${NET} cnf lay abs_xy_lan lan04 359 84
cloonix_cli ${NET} cnf lay abs_xy_lan lan03 172 191
cloonix_cli ${NET} cnf lay abs_xy_lan lan01 208 117
cloonix_cli ${NET} cnf lay abs_xy_lan lan06 69 85
cloonix_cli ${NET} cnf lay abs_xy_sat nat01 184 -2
cloonix_cli ${NET} cnf lay abs_xy_lan nat_lan 184 -10
sleep 5

#-------------------------------------------------------
# Hide the nat01 and connected 
# interfaces
#-------------------------------------------------------
cloonix_cli ${NET} cnf lay hide_lan nat_lan 1
cloonix_cli ${NET} cnf lay hide_sat nat01 1
cloonix_cli ${NET} cnf lay hide_eth ${ROUTER_NAME}1 3 1
cloonix_cli ${NET} cnf lay hide_eth ${ROUTER_NAME}2 3 1
cloonix_cli ${NET} cnf lay hide_eth ${ROUTER_NAME}3 3 1
cloonix_cli ${NET} cnf lay hide_eth ${PC_NAME}1 1 1
cloonix_cli ${NET} cnf lay hide_eth ${PC_NAME}2 1 1
cloonix_cli ${NET} cnf lay hide_eth ${PC_NAME}3 1 1

#-------------------------------------------------------
# wait 30 seconds for all VMs to finish starting up
#-------------------------------------------------------
echo "Waiting 60 seconds for all nodes to start"
sleep 60
echo "Topology is ready"

#-------------------------------------------------------
# Install quagga on the three routers
# Each router is already connected to the slirp-lan
# on its highest-numbered interface, eth3 
#-------------------------------------------------------

echo "Installing quagga software"

cloonix_ssh ${NET} ${ROUTER_NAME}1 "dhclient eth3"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "apt-get update"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "apt-get --allow-unauthenticated --assume-yes install quagga"

cloonix_ssh ${NET} ${ROUTER_NAME}2 "dhclient eth3"
cloonix_ssh ${NET} ${ROUTER_NAME}2 "apt-get update"
cloonix_ssh ${NET} ${ROUTER_NAME}2 "apt-get --allow-unauthenticated --assume-yes install quagga"

cloonix_ssh ${NET} ${ROUTER_NAME}3 "dhclient eth3"
cloonix_ssh ${NET} ${ROUTER_NAME}3 "apt-get update"
cloonix_ssh ${NET} ${ROUTER_NAME}3 "apt-get --allow-unauthenticated --assume-yes install quagga"

sleep 30
echo "Completed software install"

#-------------------------------------------------------
# Write quagga config files on Router-1.
#
# One method is to use cloonix_dbssh to execute echo or
# sed commands on at a time to build configuration files
# line-by-line.
#-------------------------------------------------------

echo "starting ${ROUTER_NAME}1 configuration"

# Router-1 ospfd.conf file
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface eth0' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface eth1' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface eth2' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface eth3' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface lo' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'router ospf' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' passive-interface eth0' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' network 192.168.1.0/24 area 0.0.0.0' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' network 192.168.100.0/24 area 0.0.0.0' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' network 192.168.101.0/24 area 0.0.0.0' >>/etc/quagga/ospfd.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'line vty' >>/etc/quagga/ospfd.conf"

# Router-1 zebra.conf file
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface eth0' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' ip address 192.168.1.254/24' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' ipv6 nd suppress-ra' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface eth1' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' ip address 192.168.100.1/24' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' ipv6 nd suppress-ra' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface eth2' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' ip address 192.168.101.2/24' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' ipv6 nd suppress-ra' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface eth3' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo ' ipv6 nd suppress-ra' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'interface lo' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'ip forwarding' >>/etc/quagga/zebra.conf"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'line vty' >>/etc/quagga/zebra.conf"

# modify /etc/quagga/daemons file
cloonix_ssh ${NET} ${ROUTER_NAME}1 "sed -i s'/zebra=no/zebra=yes/' /etc/quagga/daemons"
cloonix_ssh ${NET} ${ROUTER_NAME}1 "sed -i s'/ospfd=no/ospfd=yes/' /etc/quagga/daemons"

# modify /etc/environment file
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'VTYSH_PAGER=more' >>/etc/environment"
 
# modify /etc/bash.bashrc file
cloonix_ssh ${NET} ${ROUTER_NAME}1 "echo 'export VTYSH_PAGER=more' >>/etc/bash.bashrc"


echo "completed ${ROUTER_NAME}1 configuration"

#-----------------------------------------------------
# Write quagga config files on ${ROUTER_NAME}2
#
# Another method is to create temporary files 
# containing the required configuration and then copy 
# them to ${ROUTER_NAME}2 using the cloonix_dpscp command.
# 
# This results in a script file that is easier for 
# humans to read.
#-----------------------------------------------------

echo "starting ${ROUTER_NAME}2 configuration"

mkdir /tmp/${ROUTER_NAME}2

# Router-2 ospfd.conf file
cat > /tmp/${ROUTER_NAME}2/ospfd.conf << EOF
interface eth0
!
interface eth1
!
interface eth2
!
interface lo
!
router ospf
 passive-interface eth0
 network 192.168.2.0/24 area 0.0.0.0
 network 192.168.100.0/24 area 0.0.0.0
 network 192.168.102.0/24 area 0.0.0.0
!
line vty
!
EOF

# Router-2 zebra.conf file
cat > /tmp/${ROUTER_NAME}2/zebra.conf << EOF
interface eth0
 ip address 192.168.2.254/24
 ipv6 nd suppress-ra
!
interface eth1
 ip address 192.168.100.2/24
 ipv6 nd suppress-ra
!
interface eth2
 ip address 192.168.102.2/24
 ipv6 nd suppress-ra
!
interface lo
!
ip forwarding
!
line vty
!
EOF

# move files to ${ROUTER_NAME}2
cloonix_scp ${NET} -r /tmp/${ROUTER_NAME}2/* ${ROUTER_NAME}2:/etc/quagga

# modify /etc/quagga/daemons file
cloonix_ssh ${NET} ${ROUTER_NAME}2 "sed -i s'/zebra=no/zebra=yes/' /etc/quagga/daemons"
cloonix_ssh ${NET} ${ROUTER_NAME}2 "sed -i s'/ospfd=no/ospfd=yes/' /etc/quagga/daemons"

# modify /etc/environment file
cloonix_ssh ${NET} ${ROUTER_NAME}2 "echo 'VTYSH_PAGER=more' >>/etc/environment"
 
# modify /etc/bash.bashrc file
cloonix_ssh ${NET} ${ROUTER_NAME}2 "echo 'export VTYSH_PAGER=more' >>/etc/bash.bashrc"

echo "completed ${ROUTER_NAME}2 configuration"

#-------------------------------------------------------
# Write quagga config files on ${ROUTER_NAME}3
#
# Create a temporary file and then copy it
# to ${ROUTER_NAME}3.
#-------------------------------------------------------

echo "starting ${ROUTER_NAME}3 configuration"

mkdir /tmp/${ROUTER_NAME}3

# Router-3 ospfd.conf file
cat > /tmp/${ROUTER_NAME}3/ospfd.conf << EOF
interface eth0
!
interface eth1
!
interface eth2
!
interface lo
!
router ospf
 passive-interface eth0
 network 192.168.3.0/24 area 0.0.0.0
 network 192.168.101.0/24 area 0.0.0.0
 network 192.168.102.0/24 area 0.0.0.0
!
line vty
!
EOF

# $Router-3 zebra.conf file
cat > /tmp/${ROUTER_NAME}3/zebra.conf << EOF
interface eth0
 ip address 192.168.3.254/24
 ipv6 nd suppress-ra
!
interface eth1
 ip address 192.168.101.1/24
 ipv6 nd suppress-ra
!
interface eth2
 ip address 192.168.102.1/24
 ipv6 nd suppress-ra
!
interface lo
!
ip forwarding
!
line vty
!
EOF

# move files to ${ROUTER_NAME}3
cloonix_scp ${NET} -r /tmp/${ROUTER_NAME}3/* ${ROUTER_NAME}3:/etc/quagga

# modify /etc/quagga/daemons file
cloonix_ssh ${NET} ${ROUTER_NAME}3 "sed -i s'/zebra=no/zebra=yes/' /etc/quagga/daemons"
cloonix_ssh ${NET} ${ROUTER_NAME}3 "sed -i s'/ospfd=no/ospfd=yes/' /etc/quagga/daemons"

# modify /etc/environment file
cloonix_ssh ${NET} ${ROUTER_NAME}3 "echo 'VTYSH_PAGER=more' >>/etc/environment"
 
# modify /etc/bash.bashrc file
cloonix_ssh ${NET} ${ROUTER_NAME}3 "echo 'export VTYSH_PAGER=more' >>/etc/bash.bashrc"

echo "completed ${ROUTER_NAME}3 configuration"

#-------------------------------------------------------
# Set up interfaces and default route on ${PC_NAME}1
#-------------------------------------------------------

echo "starting ${PC_NAME}1 configuration"

# interfaces file
cloonix_ssh ${NET} ${PC_NAME}1 "echo 'auto eth0' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}1 "echo 'iface eth0 inet static' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}1 "echo '   address 192.168.1.1' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}1 "echo '   netmask 255.255.255.0' >>/etc/network/interfaces"

# rc.local file
cloonix_ssh ${NET} ${PC_NAME}1 "sed -i '/exit 0/i ip route add 192.168.0.0/16 via 192.168.1.254 dev eth0' /etc/rc.local"

echo "completed ${PC_NAME}1 configuration"

#-------------------------------------------------------
# Set up interfaces and default route on ${PC_NAME}2
#-------------------------------------------------------

echo "starting ${PC_NAME}2 configuration"

# interfaces file
cloonix_ssh ${NET} ${PC_NAME}2 "echo 'auto eth0' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}2 "echo 'iface eth0 inet static' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}2 "echo '   address 192.168.2.1' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}2 "echo '   netmask 255.255.255.0' >>/etc/network/interfaces"

# rc.local file
cloonix_ssh ${NET} ${PC_NAME}2 "sed -i '/exit 0/i ip route add 192.168.0.0/16 via 192.168.2.254 dev eth0' /etc/rc.local"

echo "completed ${PC_NAME}2 configuration"

#-------------------------------------------------------
# Set up interfaces and default route on ${PC_NAME}3
#-------------------------------------------------------

echo "starting ${PC_NAME}3 configuration"

# interfaces file
cloonix_ssh ${NET} ${PC_NAME}3 "echo 'auto eth0' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}3 "echo 'iface eth0 inet static' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}3 "echo '   address 192.168.3.1' >>/etc/network/interfaces"
cloonix_ssh ${NET} ${PC_NAME}3 "echo '   netmask 255.255.255.0' >>/etc/network/interfaces"

# rc.local file
cloonix_ssh ${NET} ${PC_NAME}3 "sed -i '/exit 0/i ip route add 192.168.0.0/16 via 192.168.3.254 dev eth0' /etc/rc.local"

echo "completed ${PC_NAME}3 configuration"

#-------------------------------------------------------
# Reboot all nodes to enable all changes
#-------------------------------------------------------

echo "rebooting nodes"
cloonix_ssh ${NET} ${PC_NAME}1 "reboot"
echo "${PC_NAME}1"
sleep 5
cloonix_ssh ${NET} ${PC_NAME}2 "reboot"
echo "${PC_NAME}2"
sleep 5
cloonix_ssh ${NET} ${PC_NAME}3 "reboot"
echo "${PC_NAME}3"
sleep 5
cloonix_ssh ${NET} ${ROUTER_NAME}1 "reboot"
echo "${ROUTER_NAME}1"
sleep 5
cloonix_ssh ${NET} ${ROUTER_NAME}2 "reboot"
echo "${ROUTER_NAME}2"
sleep 5
cloonix_ssh ${NET} ${ROUTER_NAME}3 "reboot"
echo "${ROUTER_NAME}3"
sleep 5
echo "Wait until nodes complete rebooting, then start your testing."

#-------------------------------------------------------
# Setup is now complete
#------------------------------------------------------- 

  1. From Cloonix documentation at http://cloonix.net/doc_stored/build-37-02/singlehtml/index.html 

  2. This is changing. Google recently announced nested virtualization support so users can run a hypervisor on a VM — KVM in KVM for example. Oracle offers nested virtualization support via their Ravello service. 

  3. I am using example IP addresses defined for documentation in RFC5737 https://tools.ietf.org/html/rfc5737 

One response to Install and run the Cloonix network emulator on Packet.net

  1. Good work as usual, thanks Brian!