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 thoughts on “Resize and manage cloud-init on kvm with centos cloud images

  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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s