Resize and manage cloud-init in KVM for Centos QCOW2 images

Resize and manage cloud-init in KVM for Centos QCOW2 images post thumbnail image

The following tools will help you to create KVM VMS or domains using CentOS Cloud images. Those images can be downloaded from http://cloud.centos.org/centos/7/images. Those images are ready to use with cloud-init scripts. cloud-init basically requires two files in a CD ISO image you have to insert during the VM creation with virt-install. Basically this post we will resize and manage cloud-init in KVM for Centos QCOW2 images using a /bin/bash script. We’ll start creating user-data and meta-data files and put them into a CD ISO image like this.

#!/bin/bash
cat > ./user-data << _EOF_ 
#cloud-config

# Hostname management
preserve_hostname: False
hostname: server_a
fqdn: server_a.example.com

# Remove cloud-init when finished with it
runcmd:
  - [ yum, -y, remove, cloud-init ]
  - echo "GATEWAY=192.168.1.1" >> /etc/sysconfig/network
  - echo "nameserver 8.8.8.8" >> /etc/resolv.conf
  - echo "domain example.com" >> /etc/resolv.conf
  - /etc/init.d/network restart
  - ifdown eth0
  - ifup eth0
# Configure where output will go
output: 
  all: ">> /var/log/cloud-init.log"
users:
- name: centos
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: server_a 
local-hostname: server_a 
_EOF_     

genisoimage -output cidata.iso -volid cidata -joliet -r user-data meta-data


# this script is part of the post: "Resize and manage cloud-init in KVM for Centos QCOW2 images"

Then, finally you can just add that iso as a CD image into your virt-install command and wait for a couple of minutes.

Now, if you want to add a little more and create a more advanced script with arguments, we can also add the resize QCOW2 images into the process.

Check this example where I am using a simple linux bridge called bridge0 linked to enp0s3 interface in this case.

[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

the wired interface:

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

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 a long time in processing 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. Also, 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 to add a root password.
Well, then, let’s go with our script to Resize and manage cloud-init in KVM for Centos QCOW2 images.

#!/bin/bash
# Resize and manage cloud-init in KVM for Centos QCOW2 images
# Usage ./script_name <node-name> <memory> <vcpus> <disk-GB> <ip-address>

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 
_EOF_


    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
#End of script "Resize and manage cloud-init in KVM for Centos QCOW2 images"
#Check more tips like those in cloud-native-everything.com

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'<span 				data-mce-type="bookmark" 				id="mce_SELREST_end" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>

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 and thanks for checking this out: “Resize and manage cloud-init in KVM for Centos QCOW2 images”

Tags: ,

Leave a Reply

Related Post