如何动态增加虚拟机镜像模版的磁盘空间?且保证新增磁盘空间不创建新的分区?

来源:互联网 发布:rj45网络接口 编辑:程序博客网 时间:2024/05/26 16:00

插曲:grep提取字符串里的数字(非常有用)

   预期该指令可以提取字符串里的数字:echo a11b222c3333d44444|grep -o "[0-9]*"

但是因为*表示前面的iteam匹配0次或多次,匹配0次就是空,而空是任何字符串的子集。

用 grep -o "[0-9]\+" 可以准确提取字符串,或者 grep -o "[0-9]*[0-9]" 


我自己写的脚本如下,存在一定的不完善,稍后讲解。

#dynamiclly resize virtual machine's img's disk

#!/bin/bash
# input args : path of VR template img,      ( *.img ) 
#              path of target VR             (*.qcow2)
#              target size of VR             (  %d   )
# note, minimum size of VR is 2G , if smaller than , exit directly


#set x;


TEMPLATE=$1        #虚拟机模版路径
TARGET=$2           #新生成的虚拟机镜像路径
SIZE=$3                #目标磁盘空间大小


PER_KB=1024           #二进制转换的单位:1024

#提取虚拟机镜像第2块磁盘容量
IMG_INFO=`qemu-img info $TEMPLATE | grep "virtual size" | awk '{print $4}' | grep -o "[0-9]\+"`    

#计算磁盘的大小,以GB为单位
ORIGIN_SIZE=$[IMG_INFO / PER_KB / PER_KB / PER_KB]


if [ "$SIZE" -le "$ORIGIN_SIZE" ]      #默认是2G,如目标磁盘空间小于等于2G,直接返回,无操作
  then
    echo "target size no bigger than minimum size[2 G], do nothing"
    exit 0
fi
add=`expr "$SIZE" - "$ORIGIN_SIZE"`
echo "$add G will be added.."


#before getting partition table , it's essential to convert *.img or *.qcow2 to *.raw .


TEMP=temp.raw
echo "temp name is $TEMP"
qemu-img convert -O raw $TEMPLATE $TEMP      #虚拟机镜像格式转换,在动态扩容之前,需要转换格式


if [ -f "$TEMP" ]
  then
  echo "$TEMP has been converted !"
else
  echo fail to convert $TEMPLATE
  exit 0
fi


echo begin to resize
size=+"$add"G
echo begin to  $size
qemu-img resize $TEMP $size


PER_SECTOR=512
START_SEC=`parted temp.raw unit s print | tail -n 2 | awk '{print $2}'`
oldSector=$(parted $TEMP  unit s print  | tail -n 2 | head -n1 | awk '{print $3}')
echo "original oldSector size : "$oldSector""
oldSecDig=${oldSector%*s}
newSector=$[add * PER_KB * PER_KB * PER_KB / PER_SECTOR]
tarSector=$[newSector + oldSecDig]
echo target Sector : $tarSector
echo "start to delete second partition.."
lastPartition=`parted $TEMP unit s print | tail -n 2 | awk '{print $1}'`
parted $TEMP  unit s rm $lastPartition
echo "finish deleting second partition, start to resize partition"
echo "start : $START_SEC, end : $tarSector"
parted $TEMP  unit s mkpart primary $START_SEC ${tarSector}s
echo "write back new sector size finished !"


loopdev=`losetup -f`     #采用系统环回设备挂载镜像,其特点是可以在挂载的时候指定偏移地址,即只挂载镜像的第二块磁盘
echo "available loop dev : $loopdev"
losetup $loopdev -o $[${START_SEC%*s} * PER_SECTOR]  $TEMP
e2fsck -f $loopdev           #采用系统命令,让新的磁盘可用
resize2fs -d 2 $loopdev
e2fsck -f $loopdev
sync
losetup -d $loopdev


echo convert $TEMP to $TARGET
qemu-img convert -O qcow2 $TEMP $TARGET
echo deleting $TEMP
#rm -rf $temp

老大帮忙修改后的脚本如下,考虑了更多的细节和出错处理

#!/bin/bash
# input args : path of VR template img,      ( *.img ) 
#              path of target VR             (*.qcow2)
#              target size of VR             (  %d   )
# note, minimum size of VR is 2G , if smaller than , exit directly


set -e;


function usage() {
echo "$0 <temp> <target> <size>"
}


function cleanup() {
if [ -n "$TEMP_DISKIMG" -a "$keep_TEMP" = n ]
then
echo "delete $TEMP_DISKIMG"
rm -f $TEMP_DISKIMG
fi
if [ -n "$loopdev" ]
then
echo "unmap $loopdev"
losetup -d $loopdev
fi
}
function cleanup_signal() {
echo "cleanup on got signal"
cleanup
}
function cleanup_exit() {
echo "cleanup on exit"
cleanup
}


if [ $# -lt 3 ]
then
usage
exit 1
fi
if [ ! -f $TEMPLATE ]; then
echo "$TEMPLATE not exists"
exit 1
fi


TEMPLATE=$1
TARGET=$2
SIZE=$3
# internal 
TEMP_DISKIMG=
loopdev=
# config
keep_TEMP=n
logfile=
#/tmp/ResizeImg.log


trap cleanup_signal QUIT
trap cleanup_signal INT
trap cleanup_exit   EXIT


if [ -n "$logfile" ]
then
exec >>$logfile 2>&1
fi


PER_SECTOR=512
PER_KB=1024


template_disksize=`qemu-img info $TEMPLATE | grep "^virtual size" | awk '{print $4}' | grep -o "[0-9]\+"`
template_disksize_gb=$[template_disksize / PER_KB / PER_KB / PER_KB]


if [ "$SIZE" -lt "$template_disksize_gb" ] 
then
echo "target size no bigger than minimum size[$template_disksize_gb G], do nothing"
exit 1
fi
if [ "$SIZE" -eq "$template_disksize_gb" ]
then
cp $TEMPLATE $TARGET
exit 0
fi




#before getting partition table , it's essential to convert *.img or *.qcow2 to *.raw .
TEMP_DISKIMG=$(mktemp --tmpdir ResizeImg-XXXXXX.raw)      #创建格式转换后的镜像名称,名称随机且保证唯一
echo "temp disk file is $TEMP_DISKIMG"
qemu-img convert -O raw $TEMPLATE $TEMP_DISKIMG


add=$[SIZE - template_disksize_gb]
echo begin to resize +${add}G
qemu-img resize $TEMP_DISKIMG +${add}G


lastPartition=$(parted $TEMP_DISKIMG unit s print | tail -n 2 | awk '{print $1}')
startSector=$(parted $TEMP_DISKIMG unit s print | tail -n 2 | awk '{print $2}')
startSector=${startSector%*s}
endSector=$(parted $TEMP_DISKIMG unit s print  | tail -n 2 | head -n1 | awk '{print $3}')
endSector=${endSector%*s}
newEndSector=$[endSector + add * PER_KB * PER_KB * PER_KB / PER_SECTOR]


echo "Action: add ${add}G bytes to last partition $lastPartition"
echo "      Old: partition ${lastPartition} sectors [${startSector}s, ${endSector}s)"
echo "      New: partition ${lastPartition} sectors [${startSector}s, ${newEndSector}s)"
echo "start to delete second partition.."
parted $TEMP_DISKIMG unit s rm $lastPartition
echo "start to resize partition"
parted $TEMP_DISKIMG unit s mkpart primary ${startSector}s ${newEndSector}s


echo "Resize filesystems on parition $lastPartition"
loopdev=`losetup -f`
echo "map raw disk image $TEMP+${startSector}s to loop device $loopdev"
losetup $loopdev -o $[startSector * PER_SECTOR]  $TEMP_DISKIMG
echo "check file system consistency on $loopdev"
set +e  # disable exit on error, since fsck will return error if file system corrected
e2fsck -y -f $loopdev 
if [ $? -ge 4 ]; then
exit $?
fi
set -e  # re-enable exit on error
echo "resize file system on $loopdev"
resize2fs -d 2 $loopdev
echo "re-check file system consistency on $loopdev"
set +e  # disable exit on error
e2fsck -y -f $loopdev
if [ $? -ge 4 ]; then
exit $?
fi
set -e  # re-enable exit on error
echo "sync cache"
sync


echo convert $TEMP_DISKIMG to $TARGET
qemu-img convert -O qcow2 $TEMP_DISKIMG $TARGET




0 0
原创粉丝点击