Resize and manage cloud-init on kvm with centos cloud images

Hi there. The following tools will help you to create virsh domains using CentOS Cloud images (those images can be downloaded from http://cloud.centos.org/centos/7/images). the difference with my previous post “USING CENTOS CLOUD IMAGES WITH VIRSH AND NUAGE METADATA” is I am not using Nuage now. I am using a simple linux bridge to eth0 interface. This could be used to create your own linux lab at home.

the bridge configuration

An example of the bridge at follow

[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-bridge0 
DEVICE="bridge0"
ONBOOT="yes"
TYPE=Bridge
BOOTPROTO=static
IPADDR=192.168.1.5
NETMASK=255.255.255.0

A the wired interface:

[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-enp0s3 
BOOTPROTO="static"
DEVICE="enp0s3"
NM_CONTROLLED="no"
ONBOOT="yes"
BRIDGE=bridge0

the script

I’ll create domains using a fixed IP address and resizing the boot disk. The script that I am showing it’s based on Giovanni’s Post: Create a Linux Lab on KVM Using Cloud Images.

I am highlighting some lines over the script that you may change to fit what you have. Be aware I am using virt-install and virt-resize. be sure to install them in advance.

virt-resize and qemu-img can take long depending on the size of the disk.

Check on the cloud-init details. I am using metadata to change the IP address. Also, you would change the ssh public key. However, I am setting centos’s password to reverse if you want to check this out thru console.

Don’t forget to install virt-install and libguestfs-tools packages.

#!/bin/bash

# Take one argument from the commandline: VM name
if ! [ $# -eq 5 ]; then
    echo "Usage: $0 <node-name> <memory> <vcpus> <disk-GB> <ip-address>"
    exit 1
fi

# Check if domain already exists
virsh dominfo $1 > /dev/null 2>&1
if [ "$?" -eq 0 ]; then
    echo -n "[WARNING] $1 already exists.  "
    read -p "Do you want to overwrite $1 [y/N]? " -r
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        echo ""
    else
        echo -e "\nNot overwriting $1. Exiting..."
        exit 1
    fi
fi

# Directory to store images
DIR=/var/lib/libvirt/images

# Location of cloud image
IMAGE=$DIR/CentOS-6-x86_64-GenericCloud.qcow2

# Amount of RAM in MB
MEM=$2

# Number of virtual CPUs
CPUS=$3
DISK_GB=$4
IPADDR=$5
GWTY=192.168.1.254
MSK=255.255.255.0
DNS=192.168.1.1
DOMAIN=nuage.lab

# Cloud init files
USER_DATA=user-data
META_DATA=meta-data
CI_ISO=$1-cidata.iso
DISK=$1.qcow2

# Bridge for VMs (default on Fedora is bridge0)
BRIDGE=bridge0

# Start clean
rm -rf $DIR/$1
mkdir -p $DIR/$1

pushd $DIR/$1 > /dev/null

    # Create log file
    touch $1.log

    echo "$(date -R) Destroying the $1 domain (if it exists)..."

    # Remove domain with the same name
    virsh destroy $1 >> $1.log 2>&1
    virsh undefine $1 >> $1.log 2>&1

    # cloud-init config: set hostname, remove cloud-init package,
    # and add ssh-key 
    cat > $USER_DATA << _EOF_
#cloud-config

# Hostname management
preserve_hostname: False
hostname: $1
fqdn: $1.$DOMAIN

# Remove cloud-init when finished with it
runcmd:
  - [ yum, -y, remove, cloud-init ]
  - echo "GATEWAY=$GWTY" >> /etc/sysconfig/network
  - echo "nameserver $DNS" >> /etc/resolv.conf
  - echo "domain $DOMAIN" >> /etc/resolv.conf
  - /etc/init.d/network restart
  - ifdown eth0
  - ifup eth0

# Configure where output will go
output:
  all: ">> /var/log/cloud-init.log"

chpasswd:
  list: |
    centos:reverse
  expire: False

# configure interaction with ssh server
ssh_svcname: ssh
ssh_deletekeys: True
ssh_genkeytypes: ['rsa', 'ecdsa']

# Install my public ssh key to the first user-defined user configured 
# in cloud.cfg in the template (which is centos for CentOS cloud images)
ssh_authorized_keys:
  - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCetM2yjjUNYO8pm4IJxj8KzOWJirdOYu/VNZvhQ95hcgvi6VtgDhwFrCsPRqCzOD8+XSfI2evkvNCsj8LOpB8K3VUJxsqNzcKuv5l2157rl6+XksyH8bLHUxA2XG1zPIYeFs+2cwbNvENnKRzl7ZgEeCRYKbS+OcAOmk0+rGBx7rHTSg+MfkLtX3VgfNdUxx+ZKeAMqDkSuKSTlOZJDjIbAW0pCffp mau@nuage.lab
_EOF_

# Manging metadata cloud-init now
    cat > $META_DATA << _EOF_
instance-id: $1
local-hostname: $1
network-interfaces: |
  iface eth0 inet static
  address $IPADDR
  network ${IPADDR%.*}.0
  netmask $MSK
  broadcast ${IPADDR%.*}.255

# bootcmd:
#  - ifdown eth0
#  - ifup eth0
_EOF_
    #echo "instance-id: $1; local-hostname: $1" > $META_DATA

    echo "$(date -R) Copying template image..."
    echo "INFO: qemu-img create -f qcow2 -o preallocation=metadata $DISK ${DISK_GB}G"
    qemu-img create -f qcow2 -o preallocation=metadata $DISK ${DISK_GB}G
    virt-resize --expand /dev/sda1 $IMAGE $DISK 
    
    echo "Converting and sizing $IMAGE to $DISK"
    #cp $IMAGE $DISK

    # Create CD-ROM ISO with cloud-init config
    echo "$(date -R) Generating ISO for cloud-init..."
    genisoimage -output $CI_ISO -volid cidata -joliet -r $USER_DATA $META_DATA &>> $1.log

    echo "$(date -R) Installing the domain and adjusting the configuration..."
    echo "[INFO] Installing with the following parameters:"
    echo "virt-install --import --name $1 --ram $MEM --vcpus $CPUS --disk \
    $DISK,format=qcow2,bus=virtio --disk $CI_ISO,device=cdrom --network \
    bridge=$BRIDGE,model=virtio --os-type=linux --os-variant=rhel6 --noautoconsole --noapic"


    virt-install --import --name $1 --ram $MEM --vcpus $CPUS --disk \
    $DISK,format=qcow2,bus=virtio --disk $CI_ISO,device=cdrom --network \
    bridge=$BRIDGE,model=virtio --os-type=linux --os-variant=rhel6 --noautoconsole --noapic \
    --accelerate 

    #virsh console $1
    
    
    FAILS=0   
    while true; do
        ping -c 1 $IPADDR >/dev/null 2>&1
        if [ $? -ne 0 ] ; then #if ping exits nonzero...
           FAILS=$[FAILS + 1]
           echo "INFO: Checking if server $1 with IP $IPADDR is online. ($FAILS out of 20)"
        else
           echo "INFO: server $1 is alive. let's remove cloud init files"
           break
        fi
        if [ $FAILS -gt 20 ]; then
           echo "INFO: Server is still offline after 20min. I will end here!"
           exit 
        fi
        sleep 60
    done

    # Eject cdrom
    echo "$(date -R) Cleaning up cloud-init..."
    virsh change-media $1 hda --eject --config >> $1.log

    # Remove the unnecessary cloud init files
    rm $USER_DATA $CI_ISO

    echo "$(date -R) DONE. SSH to $1 using $IP, with  username 'centos'."

popd > /dev/null

Running the script

The expected output is:

[root@localhost ~]# ./virt-create.sh test 1024 1 12 192.168.1.7
[WARNING] test already exists.  Do you want to overwrite test [y/N]? y

Mon, 01 Aug 2016 10:57:21 -0500 Destroying the test domain (if it exists)...
Mon, 01 Aug 2016 10:57:22 -0500 Copying template image...
INFO: qemu-img create -f qcow2 -o preallocation=metadata test.qcow2 12G
Formatting 'test.qcow2', fmt=qcow2 size=12884901888 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off 
Examining /var/lib/libvirt/images/CentOS-6-x86_64-GenericCloud.qcow2 ...
 100% ⟦▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒⟧ 00:00
**********

Summary of changes:

/dev/sda1: This partition will be resized from 8.0G to 12.0G.  The 
    filesystem ext4 on /dev/sda1 will be expanded using the 'resize2fs' 
    method.
    
    **********
Setting up initial partition table on test.qcow2 ...
Copying /dev/sda1 ...
 100% ⟦▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒⟧ 00:00
 100% ⟦▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒⟧ 00:00
Expanding /dev/sda1 using the 'resize2fs' method ...

Resize operation completed with no errors.  Before deleting the old disk, 
carefully check that the resized disk boots and works correctly.
Converting and sizing /var/lib/libvirt/images/CentOS-6-x86_64-GenericCloud.qcow2 to test.qcow2
Mon, 01 Aug 2016 11:00:47 -0500 Generating ISO for cloud-init...
Mon, 01 Aug 2016 11:00:47 -0500 Installing the domain and adjusting the configuration...
[INFO] Installing with the following parameters:
virt-install --import --name test --ram 1024 --vcpus 1 --disk     test.qcow2,format=qcow2,bus=virtio --disk test-cidata.iso,device=cdrom --network     bridge=bridge0,model=virtio --os-type=linux --os-variant=rhel6 --noautoconsole --noapic
WARNING  KVM acceleration not available, using 'qemu'

Starting install...
Creating domain...                                                                                                                                        |    0 B  00:00:00     
Domain creation completed.
INFO: Checking if server test with IP 192.168.1.7 is online. (1 out of 20)
INFO: Checking if server test with IP 192.168.1.7 is online. (2 out of 20)
INFO: Checking if server test with IP 192.168.1.7 is online. (3 out of 20)
INFO: Checking if server test with IP 192.168.1.7 is online. (4 out of 20)
INFO: Checking if server test with IP 192.168.1.7 is online. (5 out of 20)
INFO: server test is alive. let's remove cloud init files
Mon, 01 Aug 2016 11:06:03 -0500 Cleaning up cloud-init...
Mon, 01 Aug 2016 11:06:03 -0500 DONE. SSH to test using , with  username 'centos'.

See you later

5 replies »

  1. Great post and great script actually it will be so useful for me thanks! but be careful you define the variable BRIDGE but you never use it.

    Gettings

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: