Modifying base-images with snapshots on Unetlab/EVE-NG Alpha

Introduction

Unetlab/EVE-NG (Alpha) is a great tool you can use for learning about networking with different platforms (Dynamips routers, IOL, QEMU images). I won’t get into details about how to prepare the environment, you can find a lot of useful information on their site http://www.unetlab.com, but I’ll focus on how labs’ devices’ images are managed by EVE (let’s use EVE instead of Unetlab/EVE-NG for the rest of the post).

Browsing the temporary files for a lab with a QEMU node

Let’s create a new lab with a single QEMU node, which in my case is a TinyCore Linux image:

post5_fig1_add_tinycore

The base image I’ve chosen is linux-tiny-core-7.2, which you can find on EVE VM under /opt/unetlab/addons/qemu/linux-tiny-core-7.2:

root@eve-ng:~# ls -l /opt/unetlab/addons/qemu/linux-tiny-core-7.2/
total 74624
-rw-r--r-- 1 root root 76414976 Nov 11 10:21 hda.qcow2

hda.qcow2 is disk1 of the linux box.

What happens when you instantiate this image within your lab and run/modify its contents? As you can imagine, EVE does not modify the source image, otherwise it would be impossible to manage more instantiation for the same base image. Instead, it creates a QEMU snapshot within the lab’s temporary files. Let’s see it.

First, we must get some info about the lab: press Lab Details on the left menu bar and get the lab ID, which in my case is da2b48f4-d910-4e7d-9645-f952457cbf6d.

Go on the temporary lab folder on EVE (the “0” after /tmp is my pod number, zero as I’m working as admin):

cd /opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/

In this folder you can find a subfolder for each device of the lab. In this example we have only device 1, so enter within 1 subfolder (you can get the number of the node, if multiple nodes are running, by right-clicking on the node and looking at the number between the brackets after the name of the node) and look at its contents:

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d# cd 1

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/1# ls -l
total 1284
-rw-r--r-- 1 root unl 1376256 Jan 6 11:43 hda.qcow2
-rw-rw-r-- 1 root unl 0 Jan 6 11:42 wrapper.txt

you can see hda.qcow2 again. Is it a copy? No, it would be a waste of space, it is a snapshot of the base image, let’s see it:

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/1# /opt/qemu/bin/qemu-img info --backing-chain hda.qcow2
image: hda.qcow2
file format: qcow2
virtual size: 614M (643825664 bytes)
disk size: 1.3M
cluster_size: 65536
backing file: /opt/unetlab/addons/qemu/linux-tiny-core-7.2/hda.qcow2
[...]

image: /opt/unetlab/addons/qemu/linux-tiny-core-7.2/hda.qcow2
file format: qcow2
virtual size: 614M (643825664 bytes)
disk size: 73M
cluster_size: 65536
[...]

So, every modification you do to the disk of the instantiated image, it is confined to the snapshot and the base image won’t be modified, as it is quite obvious.

Modifying the base image

Some times ago, I’ve felt the need to modify my base Tiny Core installation in order to add tcpdump package to it, which is useful for troubleshooting. Instead of installing it on every instantiation of TinyCore within my labs, I wanted to modify the base image, but you must not modify a base image after you’ve used it at least in one lab, unless you want to corrupt all the labs that instantiated it. The quick and dirty solution could be creating a new subdirectory within /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2 and copying the original hda.qcow2 file into it, then modify the new base image before using it into any lab. With TinyCore it is just a matter of few Mbytes, so it is perfectly right to make a simple copy. But what if the base image is 2-3 GBytes, such as Radware Alteon or Juniper vMX images? It would be a waste of space, and on my laptop I don’t want to waste it, so let’s try a different approach.

Making a snapshot of the base image

We can use qemu-img to create a new hda.qcow2 which is a snapshot of the original base image. Go into /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2 folder we’ve used in the previous section and delete the copy of the base image we’ve put within that folder. Let’s create a snapshot of the original base image with qemu-img create and the -b flag that specifies a backing file for the new image, thus creating a snapshot:

root@eve-ng:/opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2# /opt/qemu/bin/qemu-img create -f qcow2 -b /opt/unetlab/addons/qemu/linux-tiny-core-7.2/hda.qcow2 hda.qcow2
Formatting 'hda.qcow2', fmt=qcow2 size=643825664 backing_file='/opt/unetlab/addons/qemu/linux-tiny-core-7.2/hda.qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16

root@eve-ng:/opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2# /opt/qemu/bin/qemu-img info hda.qcow2
image: hda.qcow2
file format: qcow2
virtual size: 614M (643825664 bytes)
disk size: 196K
cluster_size: 65536
backing file: /opt/unetlab/addons/qemu/linux-tiny-core-7.2/hda.qcow2
[...]

Preparing the new base image – method 1: running QEMU from CLI

Now, you have a new base image and you want to prepare it before using in future labs. Let’s run it from command line. I won’t go into QEMU details, you can find useful docs on the web or simply run ps aux from EVE VM with some nodes running to see how it runs QEMU nodes. TinyCore can be managed via VNC, so let’s pass -vnc :100 in order to make QEMU listen for VNC connections on port 6000 on every interface (6000 is the result of 5900 base VNC port + 100) for the node we’re running:

root@eve-ng:/opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2# /opt/qemu/bin/qemu-system-x86_64 -m 2048 -hda hda.qcow2 -serial telnet:0.0.0.0:44444,server,nowait -monitor tcp:127.0.0.1:42379,server,nowait -nographic -enable-kvm -vnc 0.0.0.0:100

In the command above you also see how to enable serial connection through telnet, in case your image has console access enabled. If you need to reach the image via IP connection, for example to transfer some content onto it by using SCP, you can manage it in this way: suppose EVE VM has pnetwith eth0 connected in bridge-mode to your own network, configure eth0 on TinyCore (or your own image) with an IP address compatible with your own network through the Console or VNC connection or let it get an IP via your LAN DHCP and then shutdown the image (if you’re using TinyCore, remember to make the changes persistent, otherwise you’ll loose them after reboot). Now, prepare a virtual interface to put within pnet0 bridge and to which we will connect TinyCore:

root@eve-ng:/opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2# ifconfig tmp_iface up

root@eve-ng:/opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2# brctl addif pnet0 tmp_iface

root@eve-ng:/opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2# brctl show pnet0
bridge name   bridge id           STP enabled   interfaces
pnet0         8000.000c29baeb65   no            eth0
                                                tmp_iface

Start qemu again mapping TinyCore eth0 onto tmp_iface we’ve just created:

root@eve-ng:/opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2# /opt/qemu/bin/qemu-system-x86_64 -m 2048 -hda hda.qcow2 -serial telnet:0.0.0.0:44444,server,nowait -monitor tcp:127.0.0.1:42379,server,nowait -nographic -enable-kvm -vnc 0.0.0.0:100 -device virtio-net-pci,netdev=net0,mac=50:01:00:04:00:00 -netdev tap,id=net0,ifname=tmp_iface,script=no

Now you can reach your QEMU node via SSH/SCP and you can do whatever you want in order to prepare the new base image.

After some modifications, let’s see the status of the -v2 base image:

root@eve-ng:/opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2# /opt/qemu/bin/qemu-img info hda.qcow2 | grep "disk size"
disk size: 1.4M

Before my modifications to the image, disk size was 196K, now it is grown to 1.4M. The original base image has not been modified.

Preparing the new base image – method 2: running a new node from GUI

If you don’t want to go through the steps from CLI I’ve explained above, you can instantiate a new node based on -v2 image and run it from the GUI:

post5_fig2_add_tinycore-v2.png

Create a network object mapped on pnet0 and connect it to eth0:

post5_fig3_add_network_pnet0post5_fig4_connect_v2-to-pnet0

Start the node based on the new base image -v2 and modify it as you want. As we’ve already said before, these modifications won’t go onto the original -v2 image we’ve prepared within /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2. Since I’ve added this new node on the same lab with the node based on the original base image, it will be node 2 of the same lab, so let’s move into its temporary folder on EVE VM and have a look at the snapshot image:

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2# cd /

root@eve-ng:/# cd /opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2# ls -l
total 1288
-rw-r--r-- 1 root unl 1376256 Jan 6 13:52 hda.qcow2
-rw-rw-r-- 1 root unl 118 Jan 6 13:52 wrapper.txt

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2# /opt/qemu/bin/qemu-img info hda.qcow2
image: hda.qcow2
file format: qcow2
virtual size: 614M (643825664 bytes)
disk size: 1.3M
cluster_size: 65536
backing file: /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2/hda.qcow2
[...]

What can we do now to put the changes of this snapshot back to the -v2 base image? Let’s use QEMU tools to accomplish this task, but first shutdown the node within the GUI (don’t delete the node now!):

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2# /opt/qemu/bin/qemu-img commit hda.qcow2
Image committed.

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2# /opt/qemu/bin/qemu-img info hda.qcow2
image: hda.qcow2
file format: qcow2
virtual size: 614M (643825664 bytes)
disk size: 260K
cluster_size: 65536
backing file: /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2/hda.qcow2
[...]

The commit command tells QEMU to commit changes we’ve made to the instantiated node’s /opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2/hda.qcow2  disk to the base image /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2/hda.qcow2.

The new node we’ve added into the EVE’s GUI is still valid, the operation above did not corrupt it’s snapshot, but now we can delete it and if you add a new node based on -v2 base image, you will find the modifications you’ve merged into the base image with commit command.

A Snapshot Chain: what happened behind the scenes

As you’ve probably already understood, when you instantiate a new node within the GUI based on -v2 base image, you’re creating a snapshot of a snapshot. This is our snapshots tree:

/opt/unetlab/addons/qemu/linux-tiny-core-7.2/hda.qcow2  
|
 \==> /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2/hda.qcow2
|     |
|     \==> /opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2/hda.qcow2
|
 \==> /opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/1/hda.qcow2

Let’s see the chain of snapshots for node 2 disk:

root@eve-ng:/opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2# /opt/qemu/bin/qemu-img info --backing-chain hda.qcow2
image: hda.qcow2
file format: qcow2
virtual size: 614M (643825664 bytes)
disk size: 1.3M
cluster_size: 65536
backing file: /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2/hda.qcow2
[...]

image: /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2/hda.qcow2
file format: qcow2
virtual size: 614M (643825664 bytes)
disk size: 1.4M
cluster_size: 65536
backing file: /opt/unetlab/addons/qemu/linux-tiny-core-7.2/hda.qcow2
[...]

image: /opt/unetlab/addons/qemu/linux-tiny-core-7.2/hda.qcow2
file format: qcow2
virtual size: 614M (643825664 bytes)
disk size: 73M
cluster_size: 65536
[...]

What you must remember is that modifications to one of the images in the snapshot tree invalidates al the snapshots in the tree under the modified snapshot. For example, committing changes made on /opt/unetlab/addons/qemu/linux-tiny-core-7.2-v2/hda.qcow2 base image forces a modification of original base image, which invalidates node 1 disk /opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/1/hda.qcow2 but does not damage the node 2 disk /opt/unetlab/tmp/0/da2b48f4-d910-4e7d-9645-f952457cbf6d/2/hda.qcow2. If you have doubts before making such important changes, take a snapshot of your EVE VM with the tools offered by your Virtualization Environment (such as VMWare Fusion or VirtualBox) to have a quick rollback solution in case of damages to your labs.

Conclusions

In this small tutorial you’ve seen how you can use QEMU tools to manage snapshots of base images in Unetlab/EVE-NG, in order to setup new base images based on older base images, without wasting space with full clones. As EVE-NG is being developed (now it is in Alpha stage) a lot of this stuff could integrated within the GUI, but I hope it can be useful to someone experimenting with now 🙂

In the next tutorial I’ll show you how to enable compression on base images, let’s move on with Enabling compression on base-images in Unetlab/EVE-NG Alpha!

This entry was posted in Networking, Uncategorized and tagged , , , , . Bookmark the permalink.

12 Responses to Modifying base-images with snapshots on Unetlab/EVE-NG Alpha

  1. Pingback: Enabling compression on base-images in Unetlab/EVE-NG Alpha | Networking Pills

  2. Matt says:

    Great write up! Very useful information. I wish I would have came across this a month before you released it. I do like that set up but now I’m just running Linux in Virtual Machines and then hooking them up via VMNETs. What are the benefits of running qcow2 vs just running the VM on the VMNET and added into the network? It works both ways.

    Liked by 1 person

    • Hi Matt, this setup is very useful if you want to manage virtual devices based on a lot of different technologies, such as dynamips routers, IOU/IOL routers and switches, qcow2 VMs (Linux, Radware virtual appliances, BigIP F5 devices), Juniper vMX etc.. you can easily interconnect those different kinds of devices, easily capture packets from wireshark running on your host system, clone labs, export configurations. If you use only few Linux guests all interconnected on a virtual LAN segment via vmnet maybe you don’t need EVE/Unetlab,it depends on your networking needs ☺

      Like

  3. Danil says:

    Hi Gianni,

    Nice tutorial. I tried to follow the steps above bot got an error:
    root@eve-ng:/opt/unetlab/tmp/0/88575041-7224-4eda-9caa-876cf9403e82/1# /opt/qemu/bin/qemu-img commit virtioa.qcow2
    Co-routine re-entered recursively
    Aborted

    Could you advice something?

    Like

  4. Hey there Gianni,
    Like some others posted, I sure wish I can across your help guide much sooner! This information is great and thank you for contributing. I have run across a problem with the GUI method, after I use qemu-img to ‘commit” the sanpshot differences to the base image, delete the node, then create a new node from new base image, the interfaces on the new base image get mangled. For example, I have an orginal linux base image with two interfaces eth0 and eth1, but after making the qemu-img commits from the snapshot, the new base image wants to use interfaces eth3 and eth4, resulting in a broken network on the new base image. Have you come encountered this and if so, what is the cure?
    Best

    Like

    • Hi Perry, I didn’t encounter this problem… BTW do you mean that you launch the node based on the new base image and within linux it creates eth3 and eth4 or do you see eth3 and eth4 within EVE-NG GUI? If the former is true, maybe it is due to the way linux creates interfaces etc (look at the UDEV rules).. what is the mac address of eth3 within the linux box? If you can upload the modified image I can try to load it within a lab.

      Like

      • Hi Gianni,

        Yes, it created two new interfaces, actually eth2 and eth3, not eth4, in linux. The entries were created in the udev rules file. Not sure why this happens, but to fix I just used questfish to mount the new image and correct the udev rules file. I would upload, but the image is way too large. It is an Ubuntu 14.2 LT image and I imagine that the qemu snapshot commit would have the same affect on any linux distribution flavor. I’ll be using the same commit method on other vendors virtual images, such as Cisco ASA, and see if the interfaces get whacked on that. If so, that would be a problem because it may be difficult to hack some images using guestfish.

        Like

  5. carlfugate says:

    Incredibly useful post! Thanks for taking the time to do this!

    Like

  6. rachiud says:

    the command /opt/qemu/bin/qemu-img commit virtioa.qcow2 take many many many time , I lanced it yesterday et it does not finished , is this normal ?

    Like

Leave a reply to Danil Cancel reply