Wednesday, November 25, 2009

[Level 3] Script for create VirtualBox VM quickly.

This script is for quickly create VirtualBox VM,
it base on ZFS snapshot/clone technique.
The description for the script is as the following:

The step as below:
1. create a ZFS filesystem first.
Ex. # zfs create -p rpool/vbox/sourceOS
2. create a VirtualBox VM for source and put the vdi on the above ZFS filesystem.
3. use the script:
Usage:
  $0 create New_Machine_Name Source_Machine_Name interface begin_index end_index
Ex.
  ./createVBoxClientByClone.sh create NewVM SourceVM yukonx0 3 5
the above command will create 3 VMs (NewVM_3, NewVM_4, NewVM_5):
The actions of create are,
. snapshot origin ZFS
. clone from origin ZFS snapshot to new ZFS
. re-new vdi uuid on new ZFS
. create new vm
. modify new vm
. modify new vm nic
4. If you want to delete VMs, use the command as below:
Usage:
  $0 delete New_Machine_Name Source_Machine_Name interface begin_index end_index
Ex.
  ./createVBoxClientByClone.sh delete NewVM SourceVM yukonx0 3 5
Above comand will delete 3 VMs (NewVM_3, NewVM_4, NewVM_5),
The actions of delete are:
. modify new vm (detach disk)
. unregister new vm
. destroy snapshot and new build-ed ZFS

The script as blow:

#!/usr/bin/bash
showUsage() {
  cat <<EOF
Usage:
  $0 create New_Machine_Name Source_Machine_Name interface begin_index end_index
Ex.
  $0 create OS111b_MySQL OS111b_origin yukonx0 1 10
  $0 delete OS111b_MySQL OS111b_origin yukonx0 1 10
VMMachine:
`showVMS | sed -e 's/^/  /'`
EOF
}

## Usage:
##   setUUID vdi_file
## Ex.
##   setUUID /Karajon/VBoxes/Guest/guest.vdi
setUUID() {
  sVDI=$1
  VBoxManage -q internalcommands setvdiuuid $sVDI
}

## Usage:
##   createVM vm_name os_type.
## Ex.
##   createVM S10u8_MySQL Solaris_64
## PS.
##   OS Type: Solaris Solaris_64 OpenSolaris OpenSolaris_64
createVM() {
  sVMName=$1
  sOSType=$2
  /opt/VirtualBox/VBoxManage -q createvm \
    --name $sVMName \
    --ostype $sOSType \
    --register
}

## Usage:
##   modifyVMNIC vm_name source_vm interface
## Ex.
##   modifyVMNIC S10u8_MySQL S10u8_Source yukonx0
modifyVMNIC() {
  sTVMName=$1
  sSVMName=$2
  sIF="$3 - Ethernet"
  sAttachedTo=bridged
  sAdapterType=82540EM
  while read n
  do
    /opt/VirtualBox/VBoxManage -q modifyvm $sTVMName \
      --nic$n $sAttachedTo \
      --nictype$n $sAdapterType \
      --cableconnected$n on \
      --bridgeadapter$n "$sIF"
  done <
<EOF
  `VBoxManage -q showvminfo $sSVMName | grep "^NIC [1-4]:" | cut -d: -f1 | awk '{print($2)}'`
EOF
}

## Usage:
##   modifyVM vm_name hda seq_no
## Ex.
##   modifyVM S10u8_MySQL /Karajon/VBox/$sVMName/$sVDI $nSeq
modifyVM() {
  sVMName=$1
  declare -i nMemory=768
  sHDA=$2
  sDVD_ISO=/Karajon/ISOs/osol-1002-125-ai-x86.iso
  declare -i nVRDPport=3390+$3

  /opt/VirtualBox/VBoxManage -q modifyvm $sVMName \
    --memory $nMemory \
    --hda $sHDA \
    --boot1 disk --boot2 dvd \
    --dvd $sDVD_ISO \
    --audio solaudio --audiocontroller ac97 \
    --vrdp on --vrdpport $nVRDPport
}

## Usage:
##   startVM vm_name
## Ex.
##   startVM S10_U8
startVM() {
  sVMName=$1
  /opt/VirtualBox/VBoxManage -q startvm $sVMName
}

showVMS() {
  VBoxManage -q list vms
}

## Usage:
##   getVMOSType vm_name
## Ex.
##   getVMOSType OS111b_MySQL
getVMOSType() {
  sVMName=$1
  sOSType=""
  sGuestOS=`VBoxManage -q showvminfo $sVMName | grep "^Guest OS:" | cut -d: -f2`
  sOS=`echo $sGuestOS | awk '{print($1)}'`
  declare -i nVer=`echo $sGuestOS | cut -d\( -f2 | cut -d' ' -f1`
  sOSType="$sOS"_"$nVer"
  echo "$sOSType"
}

## Usage:
##   getVMHDA vm_name
## Ex.
##   getVMHDA OS111b_MySQL
getVMHDA() {
  sVMName=$1
  sHDA=`VBoxManage -q showvminfo $sVMName | grep "^Primary master:" | cut -d: -f2 | awk '{print($1)}'`
  echo $sHDA
}

## Usage:
##   getZFS vdi_file
## Ex.
##   getZFS /Karajon/VBoxes/OS111b_MySQL/abc.vdi
getZFS() {
  sVDIFile=$1
  sVDIFolder=`dirname $sVDIFile`
  sZFS=`zfs list | grep $sVDIFolder$ | awk '{print($1)}'`
  echo $sZFS
}

## Usage:
##   cloneFS source_zfs target_name
## Ex.
##   sCloneFS=`cloneZFS Karajon/VBoxes/OS111b_origin S10u8_MySQL_1`
## PS. use this function to get clone ZFS name
cloneZFS() {
  sSZFS=$1
  sSnapshotName=$2
  sTZFS=`echo $sSZFS | sed -e 's|/[^/]*$||'`/$sSnapshotName
  pfexec zfs snapshot $sSZFS@$sSnapshotName || exit 2
  pfexec zfs clone $sSZFS@$sSnapshotName $sTZFS || exit 2
  echo $sTZFS
}

########################################################### main

[ $# -lt 6 ] && echo "Error without enough parameters, exit program..." && showUsage && exit 1
sAct=$1
sNMN=$2
sSMN=$3
sIF=$4
declare -i nStartMachine=$5
declare -i nEndMachine=$6

sOSType=`getVMOSType $sSMN`
sSHDA=`getVMHDA $sSMN`
sSZFS=`getZFS $sSHDA`
sCloneFS=""
sTHDA=""
sTZFS=""

case $sAct in
create)
  # set -vx
  declare -i nCount=$nStartMachine;
  while true
  do
    [ $nCount -gt $nEndMachine ] && break
    createVM "$sNMN"_"$nCount" $sOSType
    sCloneFS=`cloneZFS $sSZFS "$sSMN"_"$nCount"`
    sTHDA=`zfs get -H mountpoint $sCloneFS | awk '{print($3)}'`/`basename $sSHDA`
    setUUID $sTHDA
    modifyVM "$sNMN"_"$nCount" $sTHDA $nCount
    modifyVMNIC "$sNMN"_"$nCount" $sSMN $sIF
    nCount=nCount+1
    sleep 1
  done
  # set +vx
  ;;
delete)
  # set -vx
  declare -i nCount=$nStartMachine;
  while true
  do
    [ $nCount -gt $nEndMachine ] && break
    VBoxManage -q modifyvm "$sNMN"_"$nCount" --hda none || exit 3
    VBoxManage -q unregistervm "$sNMN"_"$nCount" --delete || exit 3
    zfs list -t snapshot | grep $sSMN@"$sSMN"_"$nCount" | while read f x
    do
      pfexec zfs destroy -R $f
    done
    nCount=nCount+1
  done
  # set +vx
  ;;
*)
  echo "Error with wrong action($sAct), exit program..."
  showUsage
  exit 1
esac







Wish this helps.

regards,
Stanley Huang