Thursday, December 10, 2009

[Level 3] Script for clone VirtualBox 3.1.0 .

Before, I wrote a script to clone VirtualBox with ZFS technology.
After new VirtualBox release, because of the architecture and command changed,
the previous script will occur error while running.
Therefore, I modify the script for version 3.1.0 later of VirtualBox.

#!/usr/bin/bash
showUsage() {
  cat <<EOF
Usage:
  $0 [c]reate/[d]elete New_Machine_Name Source_Machine_Name interface begin_index end_index
Ex.
  $0 [c]reate OS128a_MySQL OS128a yge0 1 10
  $0 [d]elete OS128a_MySQL OS128a yge0 1 10
  $0 [d]elete OS128a_MySQL OS128a yge0
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 -v disabled | grep "^NIC [1-4]:" | cut -d: -f1 | awk '{print($2)}'`
EOF
}

## Usage:
##   cloneStorageController target_vm source_vm
## Ex.
##   cloneStorageController S10u8_MySQL S10u8_Source
cloneStorageController() {
  sTVMName=$1
  sSVMName=$2
  declare -a aSC
  declare -i nCount=0
 
  VBoxManage -q showvminfo $sSVMName | grep -i "^Storage Controller .*:" | while read x
  do
    aSC[$nCount]="`echo $x | cut -d: -f2 | sed -e 's/^[ ]*//'`"
    nCount=$nCount+1
    if [ $nCount -eq 5 ]
    then
      sCT=`echo ${aSC[0]} | awk '{print($1)}' | tr [A-Z] [a-z]`
      VBoxManage -q storagectl $sTVMName \
        --name "${aSC[0]}" \
        --add $sCT \
        --controller ${aSC[1]}
      nCount=0
    fi
  done
}

## 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 \
    --audio solaudio --audiocontroller ac97 \
    --vrdp on --vrdpport $nVRDPport
    ## --dvd $sDVD_ISO \
}

## 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() {
  sHDAFilter='IDE Controller (0, 0):'
  sVMName=$1
  sHDA=`VBoxManage -q showvminfo $sVMName | grep "^$sHDAFilter" | 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 -H | grep $sVDIFolder$ | awk '{print($1)}'`
  echo $sZFS
}

## Usage:
##   cloneFS source_zfs target_name index
## 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
}

## Ex.
##   checkVersion v1 v2
##   v1>v2,  return 1
##   v1==v2, return 0
##   v1
checkVersion() {
  sVar1=$1
  sVar2=$2
  nF1=0
  nF2=0
  sReturn=0
  declare -i nCount=1
  while true
  do
    n1=`echo $sVar1 | cut -d. -f$nCount` && [ -z $n1 ] && n1=0 && nF1=1
    n2=`echo $sVar2 | cut -d. -f$nCount` && [ -z $n2 ] && n2=0 && nF2=1
    if [ $nF1 -eq 1 ] && [ $nF2 -eq 1 ]
    then
      sReturn=0
    else
      if [ $n1 -gt $n2 ]
      then
        nF1=1
        nF2=1
        sReturn=1
      elif [ $n2 -gt $n1 ]
      then
        nF1=1
        nF2=1
        sReturn=255
      else
        sReturn=0
      fi
    fi
    [ $nF1 -eq 1 ] && [ $nF2 -eq 1 ] && break
    nCount=$nCount+1
  done
  return $sReturn
}

checkVBoxVer() {
  sVBoxMinVer=$1
  sCurrVer=`VBoxManage -v | cut -dr -f1`
  nReturn=0
  checkVersion $sCurrVer $sVBoxMinVer
  nResult=$?
  if [ $nResult -ne 255 ]
  then
    nReturn=0
  else
    nReturn=1
  fi
  echo $nReturn
  return $nReturn
}

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

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

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

##sDVD_ISO=/Karajon/ISOs/osol-1002-125-ai-x86.iso

if [ `checkVBoxVer $sVBoxMinVer` -ne 0 ]
then
  cat <<EOF
Current version of VirtualBox is `VBoxManage -v`.
And to run this script,
the version of VirtualBox must great than $sVBoxMinVer.
EOF
  exit 255
fi

case $sAct in
c|create)
  # set -vx
  declare -i nCount=$nStartMachine;
  while true
  do
    [ $nCount -gt $nEndMachine ] && break
    createVM "$sNMN"_"$nCount" $sOSType
    sCloneFS=`cloneZFS $sSZFS "$sSMN"_"$nCount"`
    sTHDADir=`zfs get -H mountpoint $sCloneFS | awk '{print($3)}'`
    sTHDA=$sTHDADir/`basename $sSHDA`
    setUUID $sTHDA

    ## rename vdi filename
    mv $sTHDA $sTHDADir/`basename $sSHDA | cut -d. -f1`_$nCount.`basename $sSHDA | cut -d. -f2-`
    sTHDA=$sTHDADir/`basename $sSHDA | cut -d. -f1`_$nCount.`basename $sSHDA | cut -d. -f2-`

    cloneStorageController "$sNMN"_"$nCount" $sSMN
    modifyVM "$sNMN"_"$nCount" $sTHDA $nCount
    modifyVMNIC "$sNMN"_"$nCount" $sSMN $sIF
    nCount=nCount+1
    sleep 1
  done
  # set +vx
  ;;
d|delete)
  # set -vx
  declare -i nCount=$nStartMachine;
  while true
  do
    [ $nCount -gt $nEndMachine ] && break
    sHDA=`getVMHDA "$sNMN"_"$nCount"`
    echo "deleting $sNMN"_"$nCount" ...
    VBoxManage -q modifyvm "$sNMN"_"$nCount" --hda none || exit 3
    VBoxManage -q unregistervm "$sNMN"_"$nCount" --delete || exit 3
    #VBoxManage -q list hdds ## list hdds info
    VBoxManage -q closemedium disk $sHDA # remove disk medium
    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