#!/bin/bash ### This script will create a new virtual disk using the passed name and size and attaches it on the passed vm guest. ### It also modifies the config file for the guest, so the disk will be attached again after a restart ### The script will do some checking after each step to verify a correct outcome, but will not check upfront if enough disk space is available (still to be added) ### ### This script needs to be executed as root on the dom0 of the server on which the virtual disk needs to be created ### Required parameters are , and ### Do NOT add the img suffix to the disk name ### The disk size needs to be suffixed with the unit (eg 20G, to create a disk of 20 GB) ### ### Important to know is that this script will probably fail if the disk device mappings has "gaps", as it simply counts the number of disk devices for the given vm ### to determine the next free front device ### Get the input parameters guest_name=$1 disk_name=$2 disk_size=$3 ### Check if all mandatory input parameters are given if [ "${guest_name}" == "" ] || [ "${disk_name}" == "" ] || [ "${disk_size}" == "" ] then echo "usage: $0 guest_name disk_name disk_size" echo "guest_name is the name of the virtual guest on which the disk needs to be attached" echo "disk_name is the name of the disk to be created \(without the .img suffix\)" echo "disk_size is the size of the disk, including the unit \(eg 20G\)" exit -1 fi ### generate the array of disk devices ### the current limit of attached devices is 37 drive_array=(xvda xvdb xvdc xvdd xvde xvdf xvdg xvdh xvdi xvdj xvdk xvdl xvdm xvdn xvdo xvdp xvdq xvdr xvds xvdt xvdv xvdw xvdx xvdy xvdz xvdaa xvdab xvdac xvdad xvdae xvdae xvdaf xvdag xvdah xvdai xvdaj xvdak) ### get the uuid of the guest on which the new disk needs to be added guest_uuid=$(xl vm-list | grep ${guest_name}| tr -d '-' |cut -d' ' -f1) if [ "${guest_uuid}" == "" ] then echo "FAIL - Could not get guest uuid, pleace check guest name" exit -1 else echo "Guest UUID: ${guest_uuid}" fi ### get the number of current attached block devices, as the output also includes a header, this is already the next available slot number ### subtract 1 to compensate for the arrays, which start at 0 and not 1 ### also, using xm and not xl here as xl seems to not list the disks that are attached on a running instance (exact reason still to be verified) next_slot=$(($(xm block-list ${guest_name} | wc -l)-1)) if [ "${next_slot}" == "" ] then echo "FAIL - Could not determine a free slot number, check outcome of xm block list ${guest_name}" exit -1 else echo "Next drive slot: ${next_slot}" fi ### convert the new slot number to a drive name next_drive=${drive_array[${next_slot}]} if [ "${next_drive}" == "" ] || [[ ${next_drive} != xvd* ]] then echo "FAIL - Could not convert ${next_slot} to drive, check the drive_array variable" exit -1 else echo "The new disk will be known on the vm as /dev/${next_drive}" fi ### generate a new uuid to be used for the new disk disk_uuid=$(uuidgen | tr -d '-') if [ "${disk_uuid}" == "" ] then echo "FAIL - Could not generate a new disk_uuid, check path variable for uuidgen" exit -1 else echo "Generated disk UUID: ${disk_uuid}" fi ### create the virtual disk based upon the input parameters ### check first if the disk not already exists if [ -e "/EXAVMIMAGES/GuestImages/${guest_name}/${disk_name}.img" ] then echo "FAIL - File /EXAVMIMAGES/GuestImages/${guest_name}/${disk_name}.img already exists, use a different disk name" exit -1 fi ### create the disk echo "creating the disk now" qemu-img create /EXAVMIMAGES/GuestImages/${guest_name}/${disk_name}.img ${disk_size} ### check if the disks exists if [ ! -e "/EXAVMIMAGES/GuestImages/${guest_name}/${disk_name}.img" ] then echo "FAIL - File /EXAVMIMAGES/GuestImages/${guest_name}/${disk_name}.img was not created, check free disk space" exit -1 else echo "Created disk image /EXAVMIMAGES/GuestImages/${guest_name}/${disk_name}.img" fi ### create the symbolic link, using the uuid of the vm guest and the newly generated uuid ln -s /EXAVMIMAGES/GuestImages/${guest_name}/${disk_name}.img /OVS/Repositories/${guest_uuid}/VirtualDisks/${disk_uuid}.img ### check if the symbolic link was correctly created if [ ! -h "/OVS/Repositories/${guest_uuid}/VirtualDisks/${disk_uuid}.img" ] then echo "FAIL - Could not create symbolic link /OVS/Repositories/${guest_uuid}/VirtualDisks/${disk_uuid}.img" exit -1 else echo "Symbolic link /OVS/Repositories/${guest_uuid}/VirtualDisks/${disk_uuid}.img generated" fi ### attach the block xm block-attach ${guest_name} file:/OVS/Repositories/${guest_uuid}/VirtualDisks/${disk_uuid}.img /dev/${next_drive} w result_code=$? if [ ${result_code} -ne 0 ] then echo "FAIL - An error occured during the attach of the virtual disk, check console output" exit -1 else echo "New disk was successfully attached to VM" fi ### add the new disk to the vm config file, so it is attached when restarted ### The sed commands searches for a line with the format "disk = []" and inserts the new disk into it. ### It does this by using grouping and back references (eg \1) ### The first group is "disk = [", the second contains the existing disk strings and the third "]" ### The new string is then inserted between the second and third back reference sed -i.$(date '+%Y%m%d%H%M%S') "s/\(^disk = \[\)\(.*\)\(\]\)/\1\2,\'file:\/OVS\/Repositories\/${guest_uuid}\/VirtualDisks\/${disk_uuid}.img,${next_drive},w\'\3/" /EXAVMIMAGES/GuestImages/${guest_name}/vm.cfg result_code=$? if [ ${result_code} -ne 0 ] then echo "FAIL - An error occured during the modification of the vm config file, check console output" exit -1 else echo "Disk added to config file /EXAVMIMAGES/GuestImages/${guest_name}/vm.cfg" fi exit 0