/cjk cj knowles

Red Hat lab with CentOS, Fedora and Libvirt

Red Hat certifications are uncompromising. The best preparation is practise and the best place to practise is a virtual lab. This is one way to build that lab, with Fedora as the host and CentOS as the guests.

This is a monster guide and it'll take you through more than just the basics.

The end result will be five virtual machines:

server1.virt.lab
server1.virt.lab
freeipa.virt.labFreeIPA server (includes DNS, LDAP, Kerberos KDC)
router.virt.labwith two network cards spanning two subnets
outsider.virt.labon another virtual network

The host will have a Squid-based lazy efficient package repository, mirroring only what you use, enabling fast repeat installations with a small foot-print on your host.

Libvirt has a snapshot mechanism built-in that you can use to tear down and revert machines. As a bonus I'll throw in a script to command your machines as a pack.

What follows is opinionated: it is all command line and expects you to know how work your line. For me? Tmux and vim, but pick your tools.

Versions: Fedora 24, CentOS 7.2

What's the plan?

  1. Prepare your host
  2. Create a second virtual network
  3. Configure a yum repo mirror on the host
  4. Build and configure the first virtual machine - a simple router
  5. Build and configure the rest of the lab
  6. Configure the FreeIPA server
  7. Create a rudimentary lab management script
  8. Snapshot & party

Prepare your host

  1. Check your processor has active virtualization support:

    $ egrep '^flags.*(vmx|svm)' /proc/cpuinfo

  2. Install virtualization tools:

    # su -
    # dnf group install with-optional virtualization
    

    with-optional installs libguestfs-tools, including virt-builder, which you'll use to speed up your builds.

  3. Add the libvirt group to your user login, enabling access to the system libvirt session without switching to root:

    # usermod -aG libvirt username
    # exit
    

  4. Connect virsh and virt-viewer to the system libvirt session by default, using aliases in your user's .bashrc:

    $ vi ~/.bashrc

    Add to the end:

    alias virsh="virsh --connect=qemu:///system"
    alias virt-viewer="virt-viewer --connect=qemu:///system"
    

    Test.

    $ source ~/.bashrc
    $ virsh uri
    qemu:///system
    
    Without these you'll have to switch to root or key in the --connect= statement every time you want to interact with libvirt and your machines.

  5. Disk image storage location. This is your choice, but typically within /home or /var.

    $ mkdir -p /home/username/.config/libvirt/images

  6. Root password for guests. Write to a file. Something short and sweet as you'll be repeatably slamming it in.

    $ vi /home/username/.config/libvirt/password

  7. Domain and machine names. The only rule is that these must be fully qualified, with hostname.domain. The domain will be significant to Kerberos.

    This guide will use the names in the table at the start, but you could have some fun, you'll be typing these a lot.

  8. CentOS version. Find out which RHEL minor-version will be used in your exam, it may not be the latest release and there may be differences.

    To list pre-built images available from virt-builder:

    $ virt-builder -l | grep centos
    centos-6                 x86_64     CentOS 6.6
    centos-7.2               x86_64     CentOS 7.0
    centos-7.1               x86_64     CentOS 7.1
    centos-7.2               x86_64     CentOS 7.2
    

  9. Locale codes. Note if you're not using a US keyboard.

    $ localectl list-locales | grep -i gb
    $ localectl list-keymaps | grep -i gb
    

Second virtual network

This will enable basic host-based security practise, things like restricting access to Apache or SSH by subnet.

You're configuring this early as once the network is defined inside libvirt, virtual cards can be easily plugged in as you import disk images.

Dump the xml definition of the default network to a file and edit:

$ mkdir /home/username/.config/libvirt/xml
$ cd /home/username/.config/libvirt/xml
$ virsh net-dumpxml default > other.xml
$ vi other.xml

Amend the highlighted values:

<network>
  <name>default</name>
  <uuid>29e972d8-e019-4ec5-bc5f-d565676c55ac</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='virbr0' stp='on' delay='0'/>
  <mac address='52:54:00:1a:28:07'/>
  <ip address='192.168.124.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.124.2' end='192.168.124.254'/>
    </dhcp>
  </ip>
</network>

Example:

<network>
  <name>other</name>
  <uuid>179d2156-3de3-42fe-8420-6d0acec4ec15</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='virbr1' stp='on' delay='0'/>
  <mac address='00:16:3e:04:29:b7'/>
  <ip address='192.168.101.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.101.2' end='192.168.101.254'/>
    </dhcp>
  </ip>
</network>

Tips:

  • To generate a fresh UUID -- use uuidgen
  • To generate a fresh MAC address -- use macgen.py

Use virsh net-define to create the new network in libvirt:

$ virsh net-define other.xml
$ virsh net-autostart other
$ virsh net-start other
$ virsh net-list
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 default              active     yes           yes
 other                active     yes           yes

Yum package repository

This is not absolutely essential: you could re-download from internet mirrors every time you reinstall, but a local mirror will markedly speed up re-installations.

There are choices. You could download a multi-gigabyte CentOS ISO and serve as a repository, as described by CertDepot here, but I keep the impact on my local drives to the minimum by using a squid reverse-proxy to only mirror packages downloaded.

Matt Wagner wrote a great guide on how to do this and the version here is cribbed from Matt. Check it out as he explains the configuration in detail.

Before you start, pick a CentOS repository mirror. Pick one near to you from the CentOS Mirror List and use to replace mirror.near.to.you in the instructions below.

On your host.

su -
dnf install squid -y
vi /etc/squid/squid.conf

Just the changes:

# Squid normally listens to port 3128
#http_port 3128
http_port 3128 accel defaultsite=repo.virt.lab vhost

# Uncomment and adjust the following to add a disk cache directory.
#cache_dir ufs /var/spool/squid 100 16 256
# Create a disk-based cache of up to 10GB in size
cache_dir ufs /var/spool/squid 10000 16 256
cache_replacement_policy heap LFUDA

#
# Add any of your own refresh_pattern entries above these.
refresh_pattern -i .rpm$ 129600 100% 129600 refresh-ims override-expire
refresh_pattern -i .iso$ 129600 100% 129600 refresh-ims override-expire
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320

# Increase maximum cached object size from 4MB to 4GB
maximum_object_size 4096 MB

cache_peer mirror.near.to.you parent 80 0 no-query originserver name=lazyrepo
cache_peer_domain lazyrepo repo.virt.lab

Enable and start the squid service.

# systemctl enable squid
# systemctl start squid 

If SELinux blocks, refer to this bug report for a fix.

Open the firewall.

# firewall-cmd --add-service=squid --permanent
# firewall-cmd --reload 

Add the repo to your /etc/hosts.

vi /etc/hosts
127.0.0.1       repo.virt.lab

Test.

$ wget -S http://repo.virt.lab:3128/centos/7/os/x86_64/Packages/ElectricFence-2.2.2-39.el7.x86_64.rpm

On the first run expect 'X-Cache: MISS', on the second run 'X-Cache: HIT'.

Simple router

Time to build the first machine.

You're going to use virt-bulder to create the disk images. There are other options: Kickstart and an ISO for purists or Vagrant for the developer minded, but virt-builder is a fast way to default machines, using pre-built images from a trusted source.

I'll talk you through this step-by-step, so you understand the changes. You'll then be able to adjust the templates that follow for the other machines.

First, to build the image run virt-builder, replacing the marked values with your intended hostname, username and file locations.

$ virt-builder centos-7.2 \
--hostname router.virt.lab \
--format qcow2 \
--output /home/username/.config/libvirt/images/router.virt.lab.img \
--size 6G \
--root-password file:/home/username/.config/libvirt/password \
--selinux-relabel

Things to note:

  • qcow2 is QEMU's copy-on-write file format, VM and snapshot optimised.
  • --selinux-relabel sets SELinux labels on the image after adjustment by virt-builder.

Run virt-install to import the image, configure the virtual network cards and wire in the random-number generator (RNG) pass-through.

$ virt-install --connect=qemu:///system \
--name router.virt.lab \
--memory 2048 \
--disk "/home/username/.config/libvirt/images/router.virt.lab.img" \
--os-variant=centos7.0 \
--network network=default \
--network network=other \
--rng /dev/random \
--noreboot \
--noautoconsole \
--import

Things to note:

  • Virtual network cards are attached and configured using --network.
  • Passing-through the RNG will become valuable when you generate SSL keys. VMs can struggle to generate entropy, forcing you to wait.
  • --noreboot suppresses booting the machine post-install
  • --noautoconsole suppresses spawning a virt-viewer graphical console
  • Note the slight difference in OS name convention, osinfo-query os for options

Use virsh to start the machine and get the DHCP provisioned IP, then connect via ssh.

$ virsh start router.virt.lab
Domain router.virt.lab started
$ virsh net-dhcp-leases default
 Expiry Time          MAC address        Protocol  IP address                Hostname        Client ID or DUID
-------------------------------------------------------------------------------------------------------------------
 2016-09-01 19:24:32  52:54:aa:38:f5:10  ipv4      192.168.124.103/24        router          -

$ ssh root@192.168.124.103
root@192.168.124.162's password:
# ping disney.com 

Staying on the guest...

Static IP configuration

This is essential for the consistent configuration of some network services, like iSCSI, and will make your life easier, as you can add the IP and hostname to your hosts /etc/hosts.

Ask nmcli to show the connections, then modify.

# nmcli con show 
NAME                UUID                                  TYPE            DEVICE 
Wired connection 1  fb025729-6e61-4b98-8ba4-553d147a4bae  802-3-ethernet  eth1   
eth0                05aa7060-4f43-416b-a9d0-5bfceb397193  802-3-ethernet  eth0

# nmcli connection modify eth0 ipv4.method manual ipv4.addresses "192.168.124.5/24 192.168.124.1" ipv4.dns "192.168.124.1"
# nmcli connection modify "Wired connection 1" ipv4.method manual ipv4.addresses "192.168.101.5/24 192.168.101.1" ipv4.dns "192.168.101.1"

Reboot the guest.

Update /etc/hosts on the host and connect via ssh using the machines hostname.

$ su -
# vi /etc/hosts
# cat /etc/hosts
127.0.0.1        localhost.localdomain localhost
::1              localhost6.localdomain6 localhost6
127.0.0.1        repo.virt.lab
192.168.124.5    router.virt.lab
$ ssh root@router.virt.lab

Yum repo configuration

The long way is to edit the files in /etc/yum.repos.d, comment mirrorlist, uncomment baseurl and point towards the local squid instance (repo.virt.lab:3128).

The quick way is to use these two sed commands:

sed -i '/mirrorlist/ s/^/#/' /etc/yum.repos.d/CentOS-Base.repo
sed -i '/baseurl=http/ s/#//;s/mirror.centos.org/repo.virt.lab:3128/' /etc/yum.repos.d/CentOS-Base.repo

/etc/hosts configuration for the Yum repo

Add the yum repo hostname (repo.virt.lab) and the hosts IP address inside the virtual network to the guests /etc/hosts file. From the point-of-view of machines inside the virtual network, the hosts IP address is the gateway xxx.xxx.xxx.1 address.

Libvirt's dnsmasq will hoover up the hosts /etc/hosts each time the network is started, so if you don't change the guest's /etc/hosts file, it'll ask dnsmasq's DNS and be told that repo.virt.lab is 127.0.0.1, and end up trying to talk to itself.

# vi /etc/hosts
192.168.124.1   repo.virt.lab

You should now be able to test the yum configuration with a dry run, say 'yum install tmux' but do not install, as you want clean defaults.

Router configuration

Forwarding packets is disabled by default, as this capability could be dangerous if the system was deployed into an open network. For our purposes this is not a concern as the guests are isolated from unsolicited connections by the hosts firewall.

On the guest:

$ vi /etc/sysctl.d/router.conf
net.ipv4.ip_forward = 1
$ sysctl --system

Configure the firewall to allow this behaviour:

$ firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i eth0 -o eth1 -j ACCEPT
$ firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i eth1 -o eth0 -j ACCEPT

To display the firewall configuration:

$ firewall-cmd --direct --get-all-rules

Finally, set your keymap and timezone location, if non-US.

localectl set-keymap *keymap-code*
localectl set-locale *locale-code*

The rest of the lab

Now to repeat, building two default servers, a third on another network and the final machine that will become our FreeIPA server.

This time taking the quick-route, bundling all the configuration into the virt-builder and virt-install commands. These commands will not run as is, you need to amend for your environment, key sections highlighted.

Run each command one-by-one, or save in a file, make executable and run. If you're using vim: :%s/username/actual/g.

Notes:

  • --firstboot-command inserts the network and yum configurations
  • --noautoconsole suppresses the console typically spawned by virt-install
  • Static routes set in /etc/sysconfig/network-scripts/route-eth0
#!/bin/bash

# server1.virt.lab

virt-builder centos-7.2 \
--hostname server1.virt.lab \
--format qcow2 \
--output "/home/username/.config/libvirt/images/server1.virt.lab.img" \
--size 8G \
--root-password file:/home/username/.config/libvirt/password \
--firstboot-command 'nmcli connection modify eth0 ipv4.method manual ipv4.addresses "192.168.124.10/24" ipv4.gateway "192.168.124.1" ipv4.dns "192.168.124.1"' \
--firstboot-command 'echo "192.168.101.0/24 via 192.168.124.5 dev eth0" > /etc/sysconfig/network-scripts/route-eth0' \
--firstboot-command 'echo "192.168.124.1 repo.virt.lab" >> /etc/hosts' \
--firstboot-command 'sed -i "/mirrorlist/ s/^/#/" /etc/yum.repos.d/CentOS-Base.repo' \
--firstboot-command 'sed -i "/baseurl=http/ s/#//;s/mirror.centos.org/repo.virt.lab:3128/" /etc/yum.repos.d/CentOS-Base.repo' \
--firstboot-command 'shutdown -h now' \
--selinux-relabel

virt-install --connect=qemu:///system \
--name server1.virt.lab \
--memory 2048 \
--disk "/home/username/.config/libvirt/images/server1.virt.lab.img" \
--os-variant=centos7.0 \
--network network=default \
--network network=default \
--network network=default \
--rng /dev/random \
--noautoconsole \
--import

# server2.virt.lab

virt-builder centos-7.2 \
--hostname server2.virt.lab \
--format qcow2 \
--output "/home/username/.config/libvirt/images/server2.virt.lab.img" \
--size 8G \
--root-password file:/home/username/.config/libvirt/password \
--firstboot-command 'nmcli connection modify eth0 ipv4.method manual ipv4.addresses "192.168.124.20/24 ipv4.gateway "192.168.124.1" ipv4.dns "192.168.124.1"' \
--firstboot-command 'echo "192.168.101.0/24 via 192.168.124.5 dev eth0" > /etc/sysconfig/network-scripts/route-eth0' \
--firstboot-command 'echo "192.168.124.1 repo.virt.lab" >> /etc/hosts' \
--firstboot-command 'sed -i "/mirrorlist/ s/^/#/" /etc/yum.repos.d/CentOS-Base.repo' \
--firstboot-command 'sed -i "/baseurl=http/ s/#//;s/mirror.centos.org/repo.virt.lab:3128/" /etc/yum.repos.d/CentOS-Base.repo' \
--firstboot-command 'shutdown -h now' \
--selinux-relabel

virt-install --connect=qemu:///system \
--name server2.virt.lab \
--memory 2048 \
--disk "/home/username/.config/libvirt/images/server2.virt.lab.img" \
--os-variant=centos7.0 \
--network network=default \
--network network=default \
--network network=default \
--rng /dev/random \
--noautoconsole \
--import

# outsider.virt.lab - different virtual network

virt-builder centos-7.2 \
--hostname outsider.virt.lab \
--format qcow2 \
--output "/home/username/.config/libvirt/images/outsider.virt.lab.img" \
--size 8G \
--root-password file:/home/username/.config/libvirt/password \
--firstboot-command 'nmcli connection modify eth0 ipv4.method manual ipv4.addresses "192.168.101.101/24 ipv4.gateway  "192.168.101.1" ipv4.dns "192.168.101.1"' \
--firstboot-command 'echo "192.168.124.0/24 via 192.168.101.5 dev eth0" > /etc/sysconfig/network-scripts/route-eth0' \
--firstboot-command 'echo "192.168.101.1 repo.virt.lab" >> /etc/hosts' \
--firstboot-command 'sed -i "/mirrorlist/ s/^/#/" /etc/yum.repos.d/CentOS-Base.repo' \
--firstboot-command 'sed -i "/baseurl=http/ s/#//;s/mirror.centos.org/repo.virt.lab:3128/" /etc/yum.repos.d/CentOS-Base.repo' \
--firstboot-command 'shutdown -h now' \
--selinux-relabel

virt-install --connect=qemu:///system \
--name outsider.virt.lab \
--memory 2048 \
--disk "/home/username/.config/libvirt/images/outsider.virt.lab.img" \
--os-variant=centos7.0 \
--network network=other \
--rng /dev/random \
--noautoconsole \
--import

# freeipa.virt.lab

virt-builder centos-7.2 \
--hostname freeipa.virt.lab \
--format qcow2 \
--output "/home/username/.config/libvirt/images/freeipa.virt.lab.img" \
--size 8G \
--root-password file:/home/username/.config/libvirt/password \
--firstboot-command 'nmcli connection modify eth0 ipv4.method manual ipv4.addresses "192.168.124.30/24 ipv4.gateway "192.168.124.1" ipv4.dns "192.168.124.1"' \
--firstboot-command 'echo "192.168.101.0/24 via 192.168.124.5 dev eth0" > /etc/sysconfig/network-scripts/route-eth0' \
--firstboot-command 'echo "192.168.124.1 repo.virt.lab" >> /etc/hosts' \
--firstboot-command 'sed -i "/mirrorlist/ s/^/#/" /etc/yum.repos.d/CentOS-Base.repo' \
--firstboot-command 'sed -i "/baseurl=http/ s/#//;s/mirror.centos.org/repo.virt.lab:3128/" /etc/yum.repos.d/CentOS-Base.repo' \
--firstboot-command 'shutdown -h now' \
--selinux-relabel

virt-install --connect=qemu:///system \
--name freeipa.virt.lab \
--memory 2048 \
--disk "/home/username/.config/libvirt/images/freeipa.virt.lab.img" \
--os-variant=centos7.0 \
--network network=default \
--rng /dev/random \
--noautoconsole \
--import

Add the machine IP and hostname combinations to your host's /etc/hosts.

$ su -
# vi /etc/hosts
# cat /etc/hosts
127.0.0.1         localhost.localdomain localhost
::1               localhost6.localdomain6 localhost6
192.168.124.5     router.virt.lab
192.168.124.10    server1.virt.lab
192.168.124.20    server2.virt.lab
192.168.101.101   outsider.virt.lab
192.168.124.200   freeipa.virt.lab

There are ways to handle this without editing /etc/hosts, my favourite of which is described here by Dominic Cheal, where the host's NetworkManager routes DNS queries for your lab's domain via the dnsmasq instance spawned by libvirt for your virtual network, but I had trouble with this for Red Hat exam practise, where you have single machines with multiple NICs that need to have reverse-lookup'able hostnames, due to the way dnsmasq seems to handle IP assignment to the multiple NICs.

This may be a topic of a future post when I have tied it down, but for now trust me and set in your /etc/hosts file.

FreeIPA server

FreeIPA is a great shortcut to central Kerberos, LDAP and DNS services. Kerberos and LDAP in particular require verbose configuration if installed from the package-up.

Installation is super simple. Where there are gaps , hit ENTER to accept the default.

$ ssh root@freeipa.virt.lab
# yum install ipa-server ipa-server-dns -y
# ipa-server-install

The log file for this installation can be found in /var/log/ipaserver-install.log
==============================================================================
This program will set up the IPA Server.

This includes:
  * Configure a stand-alone CA (dogtag) for certificate management
  * Configure the Network Time Daemon (ntpd)
  * Create and configure an instance of Directory Server
  * Create and configure a Kerberos Key Distribution Center (KDC)
  * Configure Apache (httpd)

To accept the default shown in brackets, press the Enter key.

Do you want to configure integrated DNS (BIND)? [no]: yes

Enter the fully qualified domain name of the computer
on which you're setting up server software. Using the form
.
Example: master.example.com.

Server host name [freeipa.virt.lab]:  

Warning: skipping DNS resolution of host freeipa.virt.lab
The domain name has been determined based on the host name.

Please confirm the domain name [virt.lab]:  

The kerberos protocol requires a Realm name to be defined.
This is typically the domain name converted to uppercase.

Please provide a realm name [VIRT.LAB]:  
Certain directory server operations require an administrative user.
This user is referred to as the Directory Manager and has full access
to the Directory for system management tasks and will be added to the
instance of directory server created for IPA.
The password must be at least 8 characters long.

Directory Manager password: password
Password (confirm): password

The IPA server requires an administrative user, named 'admin'.
This user is a regular system account used for IPA server administration.

IPA admin password: password
Password (confirm): password

Existing BIND configuration detected, overwrite? [no]: yes
Do you want to configure DNS forwarders? [yes]:  
Enter an IP address for a DNS forwarder, or press Enter to skip: 8.8.8.8
DNS forwarder 8.8.8.8 added. You may add another.
Enter an IP address for a DNS forwarder, or press Enter to skip:  
Checking DNS forwarders, please wait ...
Do you want to configure the reverse zone? [yes]:  
Please specify the reverse zone name [124.168.192.in-addr.arpa.]:  
Using reverse zone(s) 124.168.192.in-addr.arpa.

The IPA Master Server will be configured with:
Hostname:       freeipa.virt.lab
IP address(es): 192.168.124.30
Domain name:    virt.lab
Realm name:     VIRT.LAB

BIND DNS server will be configured to serve IPA domain with:
Forwarders:    8.8.8.8
Reverse zone(s):  124.168.192.in-addr.arpa.

Continue to configure the system with these values? [no]: yes

The following operations may take some minutes to complete.
Please wait until the prompt is returned.

Adding [192.168.124.5 freeipa.virt.lab] to your /etc/hosts file

Configuring NTP daemon (ntpd)
  [1/4]: stopping ntpd

  [ cut configuration confirmation log ] 

==============================================================================
Setup complete

Next steps:
        1. You must make sure these network ports are open:
                TCP Ports:
                  * 80, 443: HTTP/HTTPS
                  * 389, 636: LDAP/LDAPS
                  * 88, 464: kerberos
                  * 53: bind
                UDP Ports:
                  * 88, 464: kerberos
                  * 53: bind
                  * 123: ntp

        2. You can now obtain a kerberos ticket using the command: 'kinit admin'
           This ticket will allow you to use the IPA tools (e.g., ipa user-add)
           and the web user interface.

Be sure to back up the CA certificates stored in /root/cacert.p12
These files are required to create replicas. The password for these 
files is the Directory Manager password

Open the firewall.

# firewall-cmd --permanent --add-service={ntp,http,https,ldap,ldaps,kerberos,kpasswd,dns}
# firewall-cmd --reload

FreeIPA serves up an admin panel on port 80.

Connect via your browser on the host and have a poke around, but do not make any changes until the machine has been snapshot!

Stop and test

Time to check that everything is correct, but crucially, do not install anything extra, the machines have not yet been snapshot and you want pristine defaults.

From the host try connecting to each of the machines and try pings across the two networks.

$ virsh list --all
$ virsh start router.virt.lab
$ virsh start server1.virt.lab
$ virsh start server2.virt.lab
$ virsh start outsider.virt.lab
$ virsh start freeipa.virt.lab
$ ssh root@outsider.virt.lab
$ ping server1.virt.lab
$ ping google.com 

Once you are done testing shutdown each of the machines, either from your ssh sessions or with virsh shutdown commands from the host.

Lab script

The next job is to snapshot the machines, freezing a copy of their state, to revert back to after practise configurations.

You might have noticed when shutting down after testing that you had to issue commands five times. This could be a lot of keyboard work, starting, stopping and reverting.

To make this nicer I crafted a rudimentary script, which takes a list of machines and issues commands via virsh to every machine.

#!/bin/bash

VIRSH="virsh --connect=qemu:///system"
INPUT="$HOME/.config/libvirt/lab/machines"

usage() {
    printf "Usage: lab [start|stop|snapshot[tag|timestamp|revert[SNAPSHOT]]]\n\n"
    printf "List virtual machines in "$INPUT"\n\n"
    printf "Example:\n"
    printf "    cat "$INPUT"\n"
    printf "    machine1.example.com\n"
    printf "    machine2.example.com\n\n"
    printf "Commands:\n"
    printf "    start                           start all\n"
    printf "    stop                            stop all\n"
    printf "    snapshot [OPTION]               snapshot all\n\n"
    printf "Snapshot options:\n"          
    printf "    snapshot tag                    create snapshots with name \'tag\'\n"
    printf "    snapshot timestamp              create snapshots with name \'timestamp\' in format \'YYYYMMDD-HH:MM:SS\'\n"
    printf "    snapshot revert [SNAPSHOT]      revert to specified name set\n\n"
    exit
}

timestamp() {
    date +"%Y%m%d-%H:%M:%S"
}

case "$1" in
        start)
            while read -r line; do 
                $VIRSH start "$line"
            done < "$INPUT"
            ;;

        stop)
            while read -r line; do 
                $VIRSH shutdown "$line"
            done < "$INPUT"
            ;;

        snapshot)
            case "$2" in
                   tag)
                        if [ $# -eq 2 ]; then
                            usage
                        fi
                        while read -r line; do
                            $VIRSH snapshot-create-as "$line" "$3"
                        done < "$INPUT"
                        ;;

                    timestamp)
                        while read -r line; do
                            $VIRSH snapshot-create-as "$line" $(timestamp) 
                        done < "$INPUT"                       
                        ;;

                    revert)
                        if [ $# -eq 2 ]; then
                            usage
                        fi    
                        while read -r line; do
                            $VIRSH snapshot-revert "$line" "$3"
                        done < "$INPUT"
                        ;;

                    *)
                        usage
                        ;;
            esac
            ;;

        *)
            usage
            ;;
esac

To make use of this, create a new directory in ~/.config/libvirt named 'lab' and create two files: 'machines', a list of machine names and 'lab.sh', containing the script. Make executable and test.

$ mkdir -p ~/.config/libvirt/lab
$ vi ~/.config/libvirt/lab/machines
$ cat ~/.config/libvirt/lab/machines
router.virt.lab
server1.virt.lab
server2.virt.lab
outsider.virt.lab
freeipa.virt.lab
$ vi ~/.config/libvirt/lab/lab.sh
# chmod 775 lab.sh
$ ./lab.sh

Make available from the command line:

$ su -
# ln -s /home/username/.config/libvirt/lab/lab.sh /usr/local/bin/lab
# exit

Now when you type lab.

Snapshot & party

To create a snapshot named 'baseline' for every machine in your lab:

$ lab snapshot tag baseline

Party time. Start them up.

$ lab start

The greatest party of all time right?



Comments