Saving a Cloonix network topology

The Cloonix network simulator has been updated to version 29, which adds the ability to save network simulation topologies and node configurations to a directory.

Users may save a network topology and all node configurations to a directory of their choice. They may also load saved topologies into Cloonix so they can restore a network scenario they previously created. The save function of Cloonix v29 supports copy-on-write filesystems and also allows users to save the full filesystems of nodes, if they wish.

This post will work through a detailed tutorial showing how to save, load, and re-save topologies and node configurations using the Cloonix GUI or command-line interface.

Different methods to save a Cloonix project

In this tutorial we will show three ways Cloonix may be used to save filesystems and network topologies:

  1. Create a new base filesystem by starting a VM in Cloonix, loading software and configurations, then saving either a full VM disk image or a derived VM disk image.
    • This simple case is useful when upgrading or modifying disk images that will be used in simulation scenarios.
       
  2. Start the Cloonix graph, set up the VMs, load software, and configure them. Then save the topology and filesystems.
    • This method is simple to understand and reliable, but results in large files sizes.
       
  3. Write a script of Cloonix commands that sets up the VMs, loads software, and configures everything remotely.
    • This results in small file sizes because only the script is needed to create the topology, but it can take longer to set up because the script downloads filesystems and software.
    • The script may be written from scratch, or you may modify a script created by a previously saved topology.

New Cloonix commands

Cloonix version 29 adds the sav command to save network topologies. To see all the cloonix commands, run the command cloonix_ctrl , as shown in the example below.

$ cloonix_ctrl nemo

|-------------------------------------------------------|
| cloonix_ctrl nemo                                     |
|-------------------------------------------------------|
|  kil  : Destroys all objects, cleans and kills switch |
|  rma  : Destroys all cloonix objects and graphs       |
|  dmp  : Dump topo                                     |
|  lst  : List commands to replay topo                  |
|  add  : Add one cloonix object to topo                |
|  del  : Del one cloonix object from topo              |
|  sav  : Save sub-menu                                 |
|  cnf  : Configure a cloonix object                    |
|  pkt  : Counters of packet throughput                 |
|  mud  : Dialog with mulan, mutap, musnf and mueth     |
|  hop  : dump 1 hop debug                              |
|  pid  : dump pids of processes                        |
|  evt  : prints events                                 |
|  sys  : prints system stats                           |
|-------------------------------------------------------|

The cloonix sav command has four subcommands. You may see the available subcommands by entering an incomplete sav command at the command line:

$ cloonix_ctrl nemo sav

|-------------------------------------------------------|
| cloonix_ctrl nemo sav                                 |
|-------------------------------------------------------|
|  derived    : Save derived qcow2                      |
|  full       : Save backing and derived in one qcow2   |
|  topo       : Save all derived and replay script      |
|  topo_full  : Save all full and replay script         |
|-------------------------------------------------------|

Also, note that a few of the other cloonix_ctrl commands have changed again in version 29. For example, the version 28 -k command used to stop and clean up a cloonix session is changed to kil in version 29.

Saving a single VM filesystem

The simplest case involves saving only a VM’s filesystem. In this case, we use either the sav full or the sav derived commands to save a single filesystem.

The Cloonix project provides VM disk images we can download and use in our network emulation scenarios. We may want to add some software to a VM and then save a copy of it as a new base VM.

For example, we may have different base VMs for the virtual PC nodes and for the virtual Router nodes in our network. This would simplify setting up a network scenario because we can do all the router setup on one base virtual machine and then every virtual router we start using that base VM inherits the basic router setup.

In this tutorial, we will use two node types: a PC and a Router.

  • The PC nodes will use the jessie.qcow2 disk image we downloaded from the Cloonix web site.
  • The Router nodes will use a modified version of the jessie.qcow2 disk image that we will create by adding software and modifying configuration files, and then save it under a new name.

First, create a cloonix topology with one KVM based on the jessie.qcow2 disk image. Start cloonix with the commands:

$ cloonix_startnet nemo
$ cloonix_graph nemo

Then configure a KVM using the following settings:

Cloonix KVM setup
Cloonix KVM setup

Next add the KVM to the Cloonix graph and connect interface 2 (eth2) to the cloonix_slirp_admin_lan LAN object. Connect the highest-numbered interface to the cloonix_slirp_admin_lan because only the highest numbered interface works when connected to that object.

Connect Cloonix KVM to admin LAN
Connect Cloonix KVM to admin LAN

After the KVM boots up, double-click on it to open an xterm and enter the following command to set up networking on interface eth2:

# dhclient eth2

Now the virtual machine will connect to the internet, assuming the host computer has a connection to the internet.

Router setup

We will modify this virtual machine so it can support OSPF routing using the quagga router software. Install the quagga package and then configure the Quagga VTY shell. This will create the basic setup for a router.

In the virtual machine’s open xterm window enter the commands:

# apt-get update
# apt-get install quagga

Then, configure the Quagga daemons by editing the file /etc/quagga/daemons and start the zebra and ospfd daemons.

# nano /etc/quagga/daemons

Modify the file so it looks like:

zebra=yes
bgpd=no
ospfd=yes
ospf6d=no
ripd=no
ripngd=no
isisd=no
babeld=no

Save the file and quit the editor.

Create config files for the zebra and ospfd daemons. These can be blank files.

# touch /etc/quagga/ospfd.conf
# touch /etc/quagga/zebra.conf

Set up environment variables so we avoid the vtysh END problem. Edit the /etc/bash.bashrc file:

# nano /etc/bash.bashrc

Add the following line at the end of the file:

export VTYSH_PAGER=more

Save the file and quit the editor. Then, edit the /etc/environment file:

# nano /etc/environment

Then add the following line to the end of the file:

VTYSH_PAGER=more

Save the file and quit the editor.

Save the new virtual machine filesystem

Now that our modifications are complete, we will save the virtual machine’s filesystem as a new disk image in the ~/cloonix/bulk directory, where it can be used in future projects. We will call it jessie-router.qcow2

We will save it as a full disk image because we will use this as a base VM for routers. Right-click on the KVM in the Cloonix graph window and select save whole rootfs from the menu that appears.

Saving a VM
Saving a VM

In the dialogue box, enter the path and filename of the new filesystem. I named it jessie-router.qcow2 and stored it in the ~/cloonix/bulk directory where it can be used as a base filesystem for experiments.

Save to bulk directory
Save to bulk directory

If you prefer to use the Cloonix command-line interface, enter the following command into the host computer’s teminal window:

$ cloonix_ctrl nemo sav full Cloon1 ~/cloonix/bulk/jessie-router.qcow2

Quit the topology by killing cloonix with the kil command:

$ cloonix_ctrl nemo kil

Next step

Now we should have two disk images in the ~/cloonix/bulk directory. The image jessie.qcow2 and the image jessie-router.qcow2.

$ cd ~/cloonix?bulk
$ ls
jessie.qcow2          jessie-router.qcow2  

We will use these as building blocks for a more complex network simulation scenario.

Saving a Cloonix topology

In the example below, we will create a topology of three PCs connected to a network of three routers.

Creating a basic topology

I created the network below, consisting of six VMs connected together, and also connected to the cloonix_slirp_admin_lan.

  • The PC nodes use the jessie.qcow2 filesystem.
  • The Router nodes use the jessie-router.qcow2 filesystem we created and saved in the Saving a single VM filesystem section, above.
  • Every node should have the ballooning option checked so it uses less RAM on the host computer.

I won’t cover the steps for creating a topology on the Cloonix graph in this post. If you need a tutorial on using the Cloonix graph, please see my previous posts about Cloonix and the Cloonix documentation.

New tolopogy
New tolopogy

Now we have a basic network topology that could be used as a base for future experiments. All the nodes are connected to each other but no networking information has been configured yet.

We do not need to use the cloonix_slirp_admin_lan LAN right now but we connect it to al the KVM nodes in case we need to add additional software in the future. We can hide the cloonix_slirp_admin_lan LAN and all attached interfaces, to make the network topology look cleaner.

Hide unused LAN and interfaces
Hide unused LAN and interfaces

Save the topology

When we save a network topology, Cloonix creates a new directory and saves the filesystem of each node and a script that will rebuild the topology.

To save a cloonix topology, you may use the Save Topo command in the Cloonix graph menu.

Save the topology from the Cloonix GUI
Save the topology from the Cloonix GUI

Enter the name of the directory into which the topology script and COW filesystems will be saved.

The topology directory name
The topology directory name

The directory must not exist. If a directory of the same name already exists, the save will fail.

Saving using the Cloonix CLI

If you wish, you may use the Cloonix command line tool, cloonix_ctrl to save the topology. In the example above, save the topology using the command:

$ cloonix_ctrl nemo sav topo ~/simple-ospf

Where simple-ospf is the directory into which Cloonix saves the topology. Remember, if the directory simple-ospf already exists the save will fail.

The topology directory

Look at the directory created when we saved the Cloonix topology. We will see a file for each VM’s filesystem and an executable script file nemo.sh that contains the commands required to rebuild the topology. When starting this topology in the future, we will run the shell script nemo.sh from a terminal window.

$ cd simple-ospf
$ ls
Router-1.qcow2  Router-3.qcow2  PC-1.qcow2  PC-3.qcow2
Router-2.qcow2  nemo.sh       PC-2.qcow2

Note that the default saving method is to save derived filesystems, which save only the changes compared to a base filesystem image, which in this case is the jessie.qcow2 file in the ~/cloonix/bulk directory.

Even so, this still creates large files over 500 MB for each derived filesystem.

Open the topology script file, nemo.sh, in a text editor to see the commands that will run to produce the topology. Below, we list the top 10 lines of the file:

#!/bin/bash
#cloonix_startnet nemo
#cloonix_graph nemo
cloonix_ctrl nemo add kvm Router-1 1000 1 classic,classic,classic /home/brian/simple-ospf/Router-1.qcow2 --persistent &
sleep 5
cloonix_ctrl nemo add lan eth Router-1 0 lan06
cloonix_ctrl nemo add lan eth Router-1 1 lan01
cloonix_ctrl nemo add lan eth Router-1 2 lan03
cloonix_ctrl nemo add kvm Core-2 1000 1 classic,classic,classic /home/brian/simple-ospf/Router-2.qcow2 --persistent &

Note that the second and third lines are commented out so you must already have started both the Cloonix server and GUI before running the script. If you wish to start Cloonix using the script, just remove the hashes at the front of the second and third lines in this script. So they look like:

#!/bin/bash
cloonix_startnet nemo
cloonix_graph nemo

Kill the current simulation

Now we are done setting up our basic simulation topology. Imagine we need to stop for a while and start again tomorrow. We may kill the running simulation with the following Cloonix command:

$ cloonix_ctrl nemo kil

This stops all the nodes, deletes all Cloonix devices, and stops both the Cloonix server and Cloonix graph processes. Now we can shut off our computer and re-load this network topology at a later date.

Loading an existing topology

Imagine that you want to load a previously-saved topology. You load a cloonix network topology by running the topology script in the directory you used to save the topology.

First, ensure the cloonix server nemo and graph are running, or edit the script so it will start the cloonix server and graph when you run it.

In this case, where we previously saved the topology in the simple-ospf-v2 directory in my $HOME directory. The cloonix server and graph have not yet been started and the script has not been modified to start them, so I will start them before running the script. I ran the following commands to load the topology again:

$ cloonix_startnet nemo
$ cloonix_graph nemo
$ ~/simple-ospf-v2/nemo.sh

Network configurations

At this point, we created a base topology and upgrades some nodes with required software. Then we saved the topology so we can use it as a base for future experiments.

One experiment we could perform would be to set up a simple OSPF configuration and test that each node can reach every other node in the network.

Now that we have rebuilt this network topology by running it’s topology script, let’s add configurations to each node as described below.

PC-1

Double-click on the PC-1 node in the Cloonix graph to open an xterm. In the PC-1 xterm window, use a text editor to add the following lines to the /etc/network/interfaces file, then save the file. The node supports both the vi and nano text editors.

auto eth0
iface eth0 inet static
   address 192.168.1.1
   netmask 255.255.255.0

Then, add a static route the sends all traffic in the 102.168.0.0/16 network out eth0.

# ip route add 192.168.0.0/16 via 192.168.1.254 dev eth0

To make this static route available after a system reboot, add the following line to the /etc/rc.local file

ip route add 192.168.0.0/16 via 192.168.1.254 dev eth0

Restart the networking service

# /etc/init.d/networking restart
PC-2

On PC-2, add the following lines to the /etc/network/interfaces file, then save the file.

auto eth0
iface eth0 inet static
   address 192.168.2.1
   netmask 255.255.255.0

Then, add a static route the sends all traffic in the 102.168.0.0/16 network out eth0.

# ip route add 192.168.0.0/16 via 192.168.2.254 dev eth0

To make this static route available after a system reboot, add the following line to the /etc/rc.local file

ip route add 192.168.0.0/16 via 192.168.2.254 dev eth0

Restart the networking service

# /etc/init.d/networking restart
PC-3

On PC-3, add the following lines to the /etc/network/interfaces file, then save the file.

auto eth0
iface eth0 inet static
   address 192.168.3.1
   netmask 255.255.255.0

Then, add a static route the sends all traffic in the 102.168.0.0/16 network out eth0.

# ip route add 192.168.0.0/16 via 192.168.3.254 dev eth0

To make this static route available after a system reboot, add the following line to the /etc/rc.local file

ip route add 192.168.0.0/16 via 192.168.3.254 dev eth0

Restart the networking service

# /etc/init.d/networking restart
Router-1

Start the Quagga shell with the command vtysh on each router:

# vtysh

On router Router-1, enter the following Quagga commands:

configure terminal
router ospf
 network 192.168.1.0/24 area 0
 network 192.168.100.0/24 area 0 
 network 192.168.101.0/24 area 0 
 passive-interface eth0    
 exit
interface eth0
 ip address 192.168.1.254/24
 exit
interface eth1
 ip address 192.168.100.1/24
 exit
interface eth2
 ip address 192.168.101.2/24
 exit
exit
ip forward
write
exit
Router-2

On router Router-2, enter the following Quagga commands:

configure terminal
router ospf
 network 192.168.2.0/24 area 0
 network 192.168.100.0/24 area 0 
 network 192.168.102.0/24 area 0 
 passive-interface eth0    
 exit
interface eth0
 ip address 192.168.2.254/24
 exit
interface eth1
 ip address 192.168.100.2/24
 exit
interface eth2
 ip address 192.168.102.2/24
 exit
exit
ip forward
write
exit
Router-3

On router Router-3, enter the following Quagga commands:

configure terminal
router ospf
 network 192.168.3.0/24 area 0
 network 192.168.101.0/24 area 0 
 network 192.168.102.0/24 area 0 
 passive-interface eth0    
 exit
interface eth0
 ip address 192.168.3.254/24
 exit
interface eth1
 ip address 192.168.101.1/24
 exit
interface eth2
 ip address 192.168.102.1/24
 exit
exit
ip forward
write
exit

Re-saving a topology

After making all the above configuration changes, you may want to save the topology again to preserve the changes you made. However, you must use a new directory name because you cannot save over an existing topology.

For example, if we loaded a topology named simple-ospf and wanted to save it again after making changes, we will have to use the Save Topo menu command and save it to a new directory like simple-ospf-v2.

$ cloonix_ctrl nemo sav topo ~/simple-ospf-v2

Cleaning up old versions

If you wish to remove old versions of topologies, delete the corresponding directory. For example:

$ rm -r simple-ospf

But, I personally find it better to keep older versions of topologies because the serve as “snapshots” that I can go back to if I need to.

Next steps

Now we have a Cloonix topology directory with filesystems and a topology script. The contents of this directory will create a simulated simple OSPF network that can be used as a basis for experimentation and study.

It is possible to share this setup with others by bundling the contents of the directory into a compressed .tar archive and placing the file on a server. The file would be much too large to share by e-mail.

In the next section, we will show how to start a Cloonix topology using just a script, which would be small enough to send in an e-mail.

Building a Cloonix topology script

There is a way to create a topology file that is very compact and that can be used to build any topology. If we keep the filesystems used in the topology on an accessible server, we can share a Cloonix topology script that contains commands that will download the needed filesystems, make the necessary configurations, and create — in this example — a simulated simple OSPF network.

See the cloonix documentation for some demo scripts that can be used as a basis for creating your own scripts. (Note that the link may change as new versions of Cloonix are released. See section 2.8 of the Cloonix documentation.)

In the example below, we will write a script that creates the same simple OSPF topology with the same configurations as the Saving a Cloonix topology section above.

Cloonix commands for scripts

In addition to the cloonix_ctrl commands, Cloonix provides two other commands that are useful for interacting with virtual machines from the host computer’s command line. These may also be integrated into scripts to add configurations to nodes.

cloonix_dbscp — A version of the standard Linux SCP command, modified to work with Cloonix. Use it from the host computer’s terminal window or in a script to copy files from the host computer to a Cloonix VM, or vice-versa. Example of usage:

cloonix_dbscp nemo <path-and-file> vm_name:<path-and-file>

For example, if we create a file named tests.txt on our host computer in the ~/Documents directory, we can copy it to the root directory on a virtual node Router-3 using the command:

cloonix_dbscp nemo ~/Documents/tests.txt Router-3:/tests.txt

cloonix_dbssh — A version of the standard Linux SSH command, modified to work with Cloonix. Use it to run commands on a Cloonix virtual machine from the host computer’s terminal window or from a script. Example of usage:

cloonix_dbssh nemo vm_name "<shell command>"

For example, to create a file test-file.txt on the Router-3 node using cloonix_dbssh type the following in the host computer’s terminal window:

cloonix_dbssh nemo Router-3 "touch /test-file.txt"

And, to write some text to the end of that file. enter the command:

$  cloonix_dbssh nemo PC-1 "echo 'This is the first line' /test-file.txt"
$  cloonix_dbssh nemo PC-1 "echo 'This is the second line' /test-file.txt"

Modify an existing script

The easiest way to create a Cloonix script is to modify an existing script or capture the output of the Cloonix topology list command, lst.

For example, after creating a topology, run the lst command and pipe the output to a file called script.sh:

$ cloonix_ctrl nemo lst > script.sh

And then start editing the file script.sh file to add the necessary lines to turn it into a useful script.

Alternatively, you could save the topology using the Cloonix sav command and then copy the shell script in the topology directory to a new filename and then start editing it.

For example, copy the simple OSPF topology script we ceated above:

$ cp ~/simple-ospf-v2/nemo.sh ~/script.sh

The script.sh file will contain all the basic topology information, such as the virtual machine disk images and interface information, the connections between nodes and LANs, and the locations of nodes on the graph. Now, we need to add all the node configuration information to the script.

Example script

Here we will discuss some of the details of writing the Cloonix script. See Appendix B for the full script.

I created the script by starting with a copy of the nemo.sh script called script.sh.

The top of the file script.sh has two lines commented out. Remove the comment hash marks so these commands start the Cloonix server and graph GUI.

#!/bin/bash
cloonix_startnet nemo
cloonix_graph nemo

The first half of the script is copied from the original topology script, or from the output of the cloonix_ctrl nemo lst command. It starts up KVMs with the correct settings, adds interfaces and LANs, positions nodes in the GUI, and hides the cloonix_slirp_admin_lan and connected interfaces.

I made minor changes to the copied script. I increased the duration of sleep timers and added blank lines and comments to make the script more readable. I moved a few lines around so they are grouped with similar actions.

In the second half of the file, I added the commands that will update the configuration files on the nodes to create a functioning OSPF network.

How to create or modify files on Cloonix KVM nodes

We may update files on the virtual nodes using one of two methods:

  • Use the cloonix_dbssh command to execute the echo or sed commands on the virtual node as a root user. Each command adds one more line to the already-exisiting configuration files on that node.
  • Or, create temporary files on the host computer containing the required configurations and then copy them to the virtual node using the cloonix_dpscp command. This results in a script file that is easier for humans to read.

In the modified script, I used both methods. I used the cloonix_dbssh command to set up the configuration files on Router-1 and the PC nodes. I used the cloonix_dpscp command to set up the configuration files on Router-2 and Router-3.

cloonix_dbssh examples

The cloonix_dbssh command executing echo commands is useful for adding short configurations to empty files, or to the end of existing files. Below is an example of setting up the etc/network/interfaces file on node PC-1 in the script:

cloonix_dbssh nemo PC-1 "echo 'auto eth0' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-1 "echo 'iface eth0 inet static' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-1 "echo '   address 192.168.1.1' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-1 "echo '   netmask 255.255.255.0' >>/etc/network/interfaces"

Use the sed command to insert lines into existing files or to modify lines in files. In this script, we use sed to insert a static route command into the rc.local file. For example:

cloonix_dbssh nemo PC-1 "sed -i '/exit 0/i ip route add 192.168.0.0/16 via 192.168.1.254 dev eth0' /etc/rc.local"
cloonix_dbscp examples

To create configuration files on the host computer in the script, use the Linux bash shell here documents syntax to create the file, then copy it to the virtual node. Below is an example of adding configurations to an ospfd.conf file for Router-2, then copying it to router 3:

cat > /tmp/router-2/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

cloonix_dbscp nemo -r /tmp/router-2/* Router-2:/etc/quagga

Add these commands to the script to set up the nodes with the configurations we need. We are chooisng to update configuration files to make our setup permanent after saving the topology.

Again, please see the whole script in Appendix B.

Running a Cloonix topology script

To set up a Cloonix topology from a script like this, make it executable and then run it. First, ensure that the filesystems you need are already in the correct directory — assuming the script does not download them for you.

$ chown +x script.sh
$ ./script.sh

Conclusion

We showed how to save a Cloonix topology and any configuration changes made to the filesystems in the topology. We showed how to reload a saved topology.

When sharing topologies with other users, you may find that the large files generated by saving filesystems are hard to share. We showed how to create a standalone script that builds a topology by downloading the files it needs and adding configurations to nodes. This script is a small text file that can be shared via e-mail.

 

Appendix A: Upgrade to Cloonix v29

We require Cloonix v29 to save topologies.

If you have a previous version of Cloonix installed, run the following commands to download the version 29.08 source code, compile it, and install it.

$ cd ~/Downloads
$ wget http://cloonix.fr/cloonix/built_cloonix-2016-01-15/cloonix_cli-29.08.tar.gz
$ wget http://cloonix.fr/cloonix/built_cloonix-2016-01-15/cloonix_serv-29.08.tar.gz
$ tar -xvf cloonix_cli-29.08.tar.gz
$ tar -xvf cloonix_serv-29.08.tar.gz
$ rm cloonix_cli-29.08.tar.gz
$ rm cloonix_serv-29.08.tar.gz
$ cd ~/cloonix_cli-29.08
$ ./doitall
$ ./install_cli.sh
$ cd ~/cloonix_serv-29.08
$ ./doitall    
$ ./install_serv.sh
$ source ~/.bashrc

If you are installing cloonix for the first time, please see my post about Cloonix version 28, for the correct procedure to install prerequisite packages.

Install filesystems

We need a base filesystem for my topology. I chose the Debian Jessie filesystem, jessie.qcow, provided by the Cloonix development team:

$ cd ~/cloonix/bulk
$ wget http://cloonix.fr/vm/bulk-2016-01-01/jessie.qcow2.xz
$ unxz jessie.qcow2.xz

Start Cloonix

Whenever you want to start Cloonix, use the following commands.

$ cloonix_startnet nemo
$ cloonix_graph nemo

In the example above, we are using the server named nemo. Other servers may be used and are configured in the file, ~/cloonix/cloonix_conf.

 

Appendix B: Stand-alone Cloonix script example

The following listing shows a full listing of a script that will set up a simple network topology and configure the nodes to run the OSPF routing protocol. This script downloads the filesystems jessie.qcow2 from the Cloonix web site, then configures each node in the scenario. The script stands alone and does not need to be bundled with a filesystem when sharing it with others.

#!/bin/bash

#-------------------------------------------------------
# Download a base filesystem. In this example, we
# get the file from the Cloonix web site. This is a
# large file so it will take a long time. You should 
# consider posting a base filesystem on an internal
# server. 
#-------------------------------------------------------
echo "Downloading jessie.qcow2.xz from http://cloonix.fr"
cd ~/cloonix/bulk
wget http://cloonix.fr/vm/bulk-2016-01-01/jessie.qcow2.xz -q --show-progress
unxz jessie.qcow2.xz
echo "jessie.qcow2 filesystem ready"

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

echo "Starting Cloonix"
cloonix_startnet nemo
cloonix_graph nemo
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"

# Router-1
cloonix_ctrl nemo add kvm Router-1 1000 1 classic,classic,classic,classic /home/brian/cloonix/bulk/jessie.qcow2 --balloon &
sleep 15
cloonix_ctrl nemo add lan eth Router-1 0 lan06
cloonix_ctrl nemo add lan eth Router-1 1 lan01
cloonix_ctrl nemo add lan eth Router-1 2 lan03
cloonix_ctrl nemo add lan eth Router-1 3 cloonix_slirp_admin_lan

# Router-2
cloonix_ctrl nemo add kvm Router-2 1000 1 classic,classic,classic,classic /home/brian/cloonix/bulk/jessie.qcow2 --balloon &
sleep 15
cloonix_ctrl nemo add lan eth Router-2 0 lan04
cloonix_ctrl nemo add lan eth Router-2 1 lan01
cloonix_ctrl nemo add lan eth Router-2 2 lan02
cloonix_ctrl nemo add lan eth Router-2 3 cloonix_slirp_admin_lan

# Router-3
cloonix_ctrl nemo add kvm Router-3 1000 1 classic,classic,classic,classic /home/brian/cloonix/bulk/jessie.qcow2 --balloon &
sleep 15
cloonix_ctrl nemo add lan eth Router-3 0 lan05
cloonix_ctrl nemo add lan eth Router-3 1 lan03
cloonix_ctrl nemo add lan eth Router-3 2 lan02
cloonix_ctrl nemo add lan eth Router-3 3 cloonix_slirp_admin_lan

# PC-1
cloonix_ctrl nemo add kvm PC-1 1000 1 classic,classic /home/brian/cloonix/bulk/jessie.qcow2 --balloon &
sleep 15
cloonix_ctrl nemo add lan eth PC-1 0 lan06
cloonix_ctrl nemo add lan eth PC-1 1 cloonix_slirp_admin_lan

# PC-2
cloonix_ctrl nemo add kvm PC-2 1000 1 classic,classic /home/brian/cloonix/bulk/jessie.qcow2 --balloon &
sleep 15
cloonix_ctrl nemo add lan eth PC-2 0 lan04
cloonix_ctrl nemo add lan eth PC-2 1 cloonix_slirp_admin_lan

# PC-3
cloonix_ctrl nemo add kvm PC-3 1000 1 classic,classic /home/brian/cloonix/bulk/jessie.qcow2 --balloon &
sleep 15
cloonix_ctrl nemo add lan eth PC-3 0 lan05
cloonix_ctrl nemo add lan eth PC-3 1 cloonix_slirp_admin_lan

#-------------------------------------------------------
# Stop motion
#-------------------------------------------------------
cloonix_ctrl nemo cnf lay stop
sleep 1

#-------------------------------------------------------
# Set size of Cloonix Graph window
#-------------------------------------------------------
cloonix_ctrl nemo cnf lay width_height 574 489
sleep 1
cloonix_ctrl nemo cnf lay scale 216 212 574 489
sleep 1

#-------------------------------------------------------
# Move nodes to their final places in the graph
#-------------------------------------------------------
cloonix_ctrl nemo cnf lay abs_xy_kvm PC-3 218 402
cloonix_ctrl nemo cnf lay abs_xy_eth PC-3 0 0
cloonix_ctrl nemo cnf lay abs_xy_eth PC-3 1 239
cloonix_ctrl nemo cnf lay abs_xy_kvm PC-2 425 45
cloonix_ctrl nemo cnf lay abs_xy_eth PC-2 0 194
cloonix_ctrl nemo cnf lay abs_xy_eth PC-2 1 254
cloonix_ctrl nemo cnf lay abs_xy_kvm PC-1 1 49
cloonix_ctrl nemo cnf lay abs_xy_eth PC-1 0 94
cloonix_ctrl nemo cnf lay abs_xy_eth PC-1 1 37
cloonix_ctrl nemo cnf lay abs_xy_kvm Router-3 221 253
cloonix_ctrl nemo cnf lay abs_xy_eth Router-3 0 154
cloonix_ctrl nemo cnf lay abs_xy_eth Router-3 1 264
cloonix_ctrl nemo cnf lay abs_xy_eth Router-3 2 15
cloonix_ctrl nemo cnf lay abs_xy_eth Router-3 3 301
cloonix_ctrl nemo cnf lay abs_xy_kvm Router-2 291 118
cloonix_ctrl nemo cnf lay abs_xy_eth Router-2 0 48
cloonix_ctrl nemo cnf lay abs_xy_eth Router-2 1 227
cloonix_ctrl nemo cnf lay abs_xy_eth Router-2 2 160
cloonix_ctrl nemo cnf lay abs_xy_eth Router-2 3 298
cloonix_ctrl nemo cnf lay abs_xy_kvm Router-1 131 128
cloonix_ctrl nemo cnf lay abs_xy_eth Router-1 0 260
cloonix_ctrl nemo cnf lay abs_xy_eth Router-1 1 57
cloonix_ctrl nemo cnf lay abs_xy_eth Router-1 2 117
cloonix_ctrl nemo cnf lay abs_xy_eth Router-1 3 5
cloonix_ctrl nemo cnf lay abs_xy_lan lan05 216 325
cloonix_ctrl nemo cnf lay abs_xy_lan lan02 262 186
cloonix_ctrl nemo cnf lay abs_xy_lan lan04 359 84
cloonix_ctrl nemo cnf lay abs_xy_lan lan03 172 191
cloonix_ctrl nemo cnf lay abs_xy_lan lan01 208 117
cloonix_ctrl nemo cnf lay abs_xy_lan lan06 69 85
cloonix_ctrl nemo cnf lay abs_xy_lan cloonix_slirp_admin_lan 184 -2
sleep 5

#-------------------------------------------------------
# Hide the cloonix_slirp_admin_lan and connected 
# interfaces
#-------------------------------------------------------
cloonix_ctrl nemo cnf lay hide_lan cloonix_slirp_admin_lan 1
cloonix_ctrl nemo cnf lay hide_eth Router-1 3 1
cloonix_ctrl nemo cnf lay hide_eth Router-2 3 1
cloonix_ctrl nemo cnf lay hide_eth Router-3 3 1
cloonix_ctrl nemo cnf lay hide_eth PC-1 1 1
cloonix_ctrl nemo cnf lay hide_eth PC-2 1 1
cloonix_ctrl nemo cnf lay hide_eth PC-3 1 1

#-------------------------------------------------------
# wait 30 seconds for all VMs to finish starting up
#-------------------------------------------------------
echo "Waiting 30 seconds for all nodes to start"
sleep 30
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_dbssh nemo Router-1 "dhclient eth3"
cloonix_dbssh nemo Router-1 "apt-get update"
cloonix_dbssh nemo Router-1 "apt-get --allow-unauthenticated --assume-yes install quagga"

cloonix_dbssh nemo Router-2 "dhclient eth3"
cloonix_dbssh nemo Router-2 "apt-get update"
cloonix_dbssh nemo Router-2 "apt-get --allow-unauthenticated --assume-yes install quagga"

cloonix_dbssh nemo Router-3 "dhclient eth3"
cloonix_dbssh nemo Router-3 "apt-get update"
cloonix_dbssh nemo Router-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-1 configuration"

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

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

# modify /etc/quagga/daemons file
cloonix_dbssh nemo Router-1 "sed -i s'/zebra=no/zebra=yes/' /etc/quagga/daemons"
cloonix_dbssh nemo Router-1 "sed -i s'/ospfd=no/ospfd=yes/' /etc/quagga/daemons"

# modify /etc/environment file
cloonix_dbssh nemo Router-1 "echo 'VTYSH_PAGER=more' >>/etc/environment"
 
# modify /etc/bash.bashrc file
cloonix_dbssh nemo Router-1 "echo 'export VTYSH_PAGER=more' >>/etc/bash.bashrc"


echo "completed Router-1 configuration"

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

echo "starting Router-2 configuration"

mkdir /tmp/router-2

# Router-2 ospfd.conf file
cat > /tmp/router-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-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-2
cloonix_dbscp nemo -r /tmp/router-2/* Router-2:/etc/quagga

# modify /etc/quagga/daemons file
cloonix_dbssh nemo Router-2 "sed -i s'/zebra=no/zebra=yes/' /etc/quagga/daemons"
cloonix_dbssh nemo Router-2 "sed -i s'/ospfd=no/ospfd=yes/' /etc/quagga/daemons"

# modify /etc/environment file
cloonix_dbssh nemo Router-2 "echo 'VTYSH_PAGER=more' >>/etc/environment"
 
# modify /etc/bash.bashrc file
cloonix_dbssh nemo Router-2 "echo 'export VTYSH_PAGER=more' >>/etc/bash.bashrc"

echo "completed Router-2 configuration"

#-------------------------------------------------------
# Write quagga config files on Router-3
#
# Create a temporary file and then copy it
# to Router-3.
#-------------------------------------------------------

echo "starting Router-3 configuration"

mkdir /tmp/router-3

# Router-3 ospfd.conf file
cat > /tmp/router-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-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-3
cloonix_dbscp nemo -r /tmp/router-3/* Router-3:/etc/quagga

# modify /etc/quagga/daemons file
cloonix_dbssh nemo Router-3 "sed -i s'/zebra=no/zebra=yes/' /etc/quagga/daemons"
cloonix_dbssh nemo Router-3 "sed -i s'/ospfd=no/ospfd=yes/' /etc/quagga/daemons"

# modify /etc/environment file
cloonix_dbssh nemo Router-3 "echo 'VTYSH_PAGER=more' >>/etc/environment"
 
# modify /etc/bash.bashrc file
cloonix_dbssh nemo Router-3 "echo 'export VTYSH_PAGER=more' >>/etc/bash.bashrc"

echo "completed Router-3 configuration"

#-------------------------------------------------------
# Set up interfaces and default route on PC-1
#-------------------------------------------------------

echo "starting PC-1 configuration"

# interfaces file
cloonix_dbssh nemo PC-1 "echo 'auto eth0' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-1 "echo 'iface eth0 inet static' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-1 "echo '   address 192.168.1.1' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-1 "echo '   netmask 255.255.255.0' >>/etc/network/interfaces"

# rc.local file
cloonix_dbssh nemo PC-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-1 configuration"

#-------------------------------------------------------
# Set up interfaces and default route on PC-2
#-------------------------------------------------------

echo "starting PC-2 configuration"

# interfaces file
cloonix_dbssh nemo PC-2 "echo 'auto eth0' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-2 "echo 'iface eth0 inet static' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-2 "echo '   address 192.168.2.1' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-2 "echo '   netmask 255.255.255.0' >>/etc/network/interfaces"

# rc.local file
cloonix_dbssh nemo PC-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-2 configuration"

#-------------------------------------------------------
# Set up interfaces and default route on PC-3
#-------------------------------------------------------

echo "starting PC-3 configuration"

# interfaces file
cloonix_dbssh nemo PC-3 "echo 'auto eth0' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-3 "echo 'iface eth0 inet static' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-3 "echo '   address 192.168.3.1' >>/etc/network/interfaces"
cloonix_dbssh nemo PC-3 "echo '   netmask 255.255.255.0' >>/etc/network/interfaces"

# rc.local file
cloonix_dbssh nemo PC-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-3 configuration"

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

echo "rebooting nodes"
cloonix_dbssh nemo PC-1 "reboot"
echo "PC-1"
sleep 5
cloonix_dbssh nemo PC-2 "reboot"
echo "PC-2"
sleep 5
cloonix_dbssh nemo PC-3 "reboot"
echo "PC-3"
sleep 5
cloonix_dbssh nemo Router-1 "reboot"
echo "Router-1"
sleep 5
cloonix_dbssh nemo Router-2 "reboot"
echo "Router-2"
sleep 5
cloonix_dbssh nemo Router-3 "reboot"
echo "Router-3"
sleep 5
echo "Wait until nodes complete rebooting, then start your testing."

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

8 thoughts on “Saving a Cloonix network topology”

    1. Hey, does clownix.net requires any permission? I’m getting a ‘Forbidden, you don’t have access to this page’ message when I try to open that in my browser.

  1. Mehreen Arshad

    You are a great guy and I like your way of defining things. But can you please assist me little? I want to use the already saved machines, so how I can use that through cloonix v29?

    1. You may be able to use VMs you’ve already created. Specify each VM as a new root filesystem for each new node you create. This may work. But Cloonix guests require some specific updates (see the documentation) to support Cloonix clients (DropBear SSH is one…).

      1. Mehreen Arshad

        Thanks for quick response Brain. One more thing which I want to know. Why I’m unable to write in spice desktop even I ungrab the mouse too? Because in your one article you told about the way of running desktop environment on guest VM and still I’m unable to write. And thanks again I got that article of DropBear SSH.

Comments are closed.

Scroll to Top