Results 1 to 10 of 13
For anyone that likes/needs to use VMWare Server a lot...
To me, the only advantage in using VMWare Workstation is the option to create "linked clones" via the WKS GUI. ...
- 04-17-2008 #1Linux Guru
- Join Date
- Nov 2007
- Posts
- 1,695
Script - Linked Clones on VMWare Server
For anyone that likes/needs to use VMWare Server a lot...
To me, the only advantage in using VMWare Workstation is the option to create "linked clones" via the WKS GUI. But VMWare Server *can* do this as well - it's just not available in the Console. (A linked clone is a cloned virtual machines that uses a "base" VM disk for reference. If you have a 5GB Windows VM, making 5 "full" clones would require 25GB. Initially, 5 linked clones would require only a few MB of extra disk space. As things change, the linked clone VM HDD's will grow, but typically takes up much less space than if they were full clones.)
You can read further about linked clones on VMWare's website. While the manual steps to create a linked clone are easy to find, I needed something to automate this process for a number of users.
It continues to be improved with new features, and if there is interest, I will post any changes as well.
To use, copy/paste the code below into a file named something like vmclone.sh, copy it to /usr/bin, and chmod to make it executable.
Any feedback/suggestions/improvements are welcome.
Code:#!/bin/bash # VMClone.sh # Small shell script to create *linked clones* on VMWare Server. # Author: HROAdmin26 # Last Edited: 2008-04-16 # Revision: 1.5 VER="1.5_2008-04-16" # README: # Copy this script to some place in your PATH statement # and make it executable - /usr/bin is a good place. # On the command line, CD into the directory of your base VM. # Run vmclone.sh with no switches for the HELP info. # Run script as ROOT. # DO NOT use if your guest VMDK's are split into 2GB chunks. # If any of your names have spaces in them, use quotes. # Script is run on command line and expects 4 (or more) parameters: # $1 = BASE_VM_NAME # $2 = BASE_VM_VMX_FILE # $3 = BASE_VMDK_FILE # $4 = CLONE_VM_NAME/MULTI_BASE_NAME # Example: vmclone "BOBO" "BOBO.vmx" "BOBO.vmdk" TIMMAY # $5 = Extra functionality. These are *NOT combinable.* Current options: # 1) If "start" is specified, the cloned VM is registered and started after cloning. # 2) If "multi" is specified, it must be followed by a number between 2 and 10 for the number of clones to create. The MULTI_BASE_NAME is appended with -1, -2, etc to name the multiple clones. # Examples: # 1) vmclone "BOBO" "BOBO.vmx" "BOBO.vmdk" TIMMAY start # 2) vmclone "BOBO" "BOBO.vmx" "BOBO.vmdk" NODES multi 7 if [ $# -lt 4 ] then echo "*****" echo "Usage: vmclone.sh \"BASE_VM_NAME\" \"BASE_VMX_FILE\" \"BASE_VMDK_FILE\" \"CLONE_VM_NAME\"" echo " " echo "Example: vmclone.sh \"BIG SERVER\" \"SLES_9.vmx\" \"BigTuna.vmdk\" \"BIGGER_SERVER\"" echo " " echo "==> WARNING! Do not use this script if the .VMDK files are split into 2GB chunks." echo "==> Usage Steps:" echo "==> ** This new version of vmclone will create the snapshot for you if it does not already exist." echo "==> 1) Change directory INTO the folder of your BASE VM and then run vmclone." echo "==> More usage options can be found in the script itself - \"more vmclone.sh\"." echo "==> VMClone Version: $VER" echo "*****" exit fi # Check for ROOT permissions. if [ $EUID -ne "0" ] then echo " " echo "Effective permissions not ROOT." echo "Please run this script as ROOT user." echo " " exit fi # Set some initial variables... REN_CMD="`which vmware-vdiskmanager`" SNAP_CMD="`which vmrun`" VM_CMD="`which vmware-cmd`" B_PATH="`pwd`" B_NAME=$1 B_VMX=$2 B_VMDK=$3 C_NAME=$4 # Check if OPTION is specified... if [ -n "$5" ] then OPTION=$5 fi # Figure out the snapshot file name. B_SNAP=`echo "$B_VMDK" | sed 's/.vmdk/-000001.vmdk/'` # Define some useful functions... # Check if snapshot is already done - if not, create the snapshot. check_for_snap () { if [ ! -e "$B_SNAP" ] then $VM_CMD -s register "$B_PATH"/"$B_VMX" 2>/dev/null >/dev/null $SNAP_CMD snapshot "$B_PATH"/"$B_VMX" 2>/dev/null >/dev/null fi } # Assumes CWD is $B_NAME - after clone creation, returns to $B_NAME. make_clone () { mkdir ../"$C_NAME" cp "$B_VMX" "$C_NAME.vmx" rm -f *.vmsn rm -f *.vmsd mv "$C_NAME.vmx" ../"$C_NAME" mv "$B_SNAP" ../"$C_NAME" # Replace the snapshot disk in B_VMX so that another snap can be taken. cat "$B_VMX" | sed 's/'"$B_SNAP"'/'"$B_VMDK"'/g' > "$B_VMX.new" mv "$B_VMX.new" "$B_VMX" cd ../"$C_NAME" # Now that we're in the clone's dir, set $C_PATH. C_PATH="`pwd`" $REN_CMD -q -n "$B_SNAP" "$C_NAME.vmdk" ln -s ../"$B_NAME"/"$B_VMDK" "$B_VMDK" # Edit the clone's VMX to reflect the new VMDK name and console display name. cat "$C_NAME.vmx" | sed 's/'"$B_SNAP"'/'"$C_NAME"'.vmdk/g' > "$C_NAME.new" mv "$C_NAME.new" "$C_NAME.vmx" cat "$C_NAME.vmx" | sed 's/'"$B_NAME"'/'"$C_NAME"'/g' > "$C_NAME.new" mv "$C_NAME.new" "$C_NAME.vmx" chmod 754 * # Register the clone with VM Server $VM_CMD -s register "$C_PATH"/"$C_NAME.vmx" 2>/dev/null >/dev/null cd ../"$B_NAME" } # MAIN # If OPTION is "multi", then we need to create multiple clones, using C_NAME as a base name. if [ "$OPTION" = "multi" ] then # If $6 is a valid number of clones between 2 and 10, set REPS. if [ -n "$6" ] && [ $6 -ge 2 ] && [ $6 -le 10 ] then REPS=$6 else echo " " echo "Sorry, MULTI was specified, but the number of VM's to create was not between 2 and 10." echo "Please try again." echo " " exit fi #Save the base name before calling make_clone() multiple times. M_BASE="$C_NAME" for ((i=1; i <= REPS; i++)) do C_NAME="$M_BASE-$i" check_for_snap make_clone done else # No MULTI - single clone to create. check_for_snap make_clone # If $OPTION "start" was specified, start the clone VM. if [ -n "$OPTION" ] && [ "$OPTION" = "start" ] then $SNAP_CMD start "$C_PATH"/"$C_NAME.vmx" 2>/dev/null >/dev/null fi fi echo " " echo "Linked clone created successfully..." echo "Within a few seconds, you should see the clone VM listed in the VMWare Console." echo " " echo " " exit
- 08-19-2008 #2Just Joined!
- Join Date
- Aug 2008
- Posts
- 11
I'm having a problem. When the script executes it seems everything is fine, but when I go to start the linked clone from the console I get an error message the disk isn't there. This is no VMWare 1.0.6 and ubuntu 8.04 Server.
- 08-19-2008 #3Linux Guru
- Join Date
- Nov 2007
- Posts
- 1,695
Here is the latest and greatest - it includes an option to create clusters. The script does *not* do a lot of error checking, so if your VM is not set up correctly, the results may vary.
Note that the VMDK file cannot be split into 2GB chunks.
There is also more README info as well - such as the DISPLAY NAME in VMWare should match the FOLDER NAME in the filesystem.Code:#!/bin/bash # VMClone.sh # Small shell script to create *linked clones* on VMWare Server. # Author: HROAdmin26 # Last Edited: 2008-04-22 # Revision: 1.7 VER="1.7_2008-04-22" # README: # Copy this script to some place in your PATH statement # and make it executable - /usr/bin is a good place. # On the command line, CD into the directory of your base VM. # Run vmclone.sh with no switches for the HELP info. # Run script as ROOT. # DO NOT use if your guest VMDK's are split into 2GB chunks. # If any of your names have spaces in them, use quotes. # Script is run on command line and expects 4 (or more) parameters: # $1 = BASE_VM_NAME # $2 = BASE_VM_VMX_FILE # $3 = BASE_VMDK_FILE # $4 = CLONE_VM_NAME/MULTI_BASE_NAME/CLUSTER_NAME # Example: vmclone "BOBO" "BOBO.vmx" "BOBO.vmdk" TIMMAY # $5 = Extra functionality. These are *NOT combinable.* Current options: # 1) If "start" is specified, the cloned VM is registered and started after cloning. # 2) If "multi" is specified, it must be followed by a number between 2 and 10 for the number of clones to create. The MULTI_BASE_NAME is appended with -1, -2, etc to name the multiple clones. # 3) If "cluster" is specified, it must be followed by a number between 2 and 5 for the number of nodes. # Examples: # 1) vmclone.sh "BOBO" "BOBO.vmx" "BOBO.vmdk" TIMMAY start # 2) vmclone.sh "BOBO" "BOBO.vmx" "BOBO.vmdk" CLONAL multi 7 # 3) vmclone.sh "BONGO" "BONGO.vmx" "BIG_DISK.vmdk" NODAL cluster 3 # CAVEATS! PLEASE READ AND UNDERSTAND! # > Some users have reported issues if the base VM has more than 1 disk - your mileage may vary. < # > Your DISPLAY_NAME for the Base VM in the VMWare Console must match the folder name of the Base VM. < # > When using the 'cluster' switch, the shared disks are added on an LSILOGIC adapter. < # > When using the 'cluster' switch, a folder named CLUSTER_NAME is created - the nodes and shared disks are created inside this folder. < if [ $# -lt 4 ] then echo "*****" echo "Usage: vmclone.sh \"BASE_VM_NAME\" \"BASE_VMX_FILE\" \"BASE_VMDK_FILE\" \"CLONE_VM_NAME\"" echo " " echo "Example: vmclone.sh \"BIG SERVER\" \"SLES_9.vmx\" \"BigTuna.vmdk\" \"BIGGER_SERVER\"" echo " " echo "==> WARNING! Do not use this script if the .VMDK files are split into 2GB chunks." echo "==> Usage Steps:" echo "==> ** This new version of vmclone will create the snapshot for you if it does not already exist." echo "==> Step 1) Change directory INTO the folder of your BASE VM and then run vmclone." echo "==> More usage options can be found in the script itself - \"more vmclone.sh\"." echo " " echo "==> Some more usage examples:" echo "==> vmclone.sh \"BOBO\" \"BOBO.vmx\" \"BOBO.vmdk\" TIMMAY start" echo "==> vmclone.sh \"BOBO\" \"BOBO.vmx\" \"BOBO.vmdk\" NODES multi 4" echo "==> vmclone.sh \"BOBO\" \"BOBO.vmx\" \"BOBO.vmdk\" WIN_CLUSTER cluster 3" echo " " echo "==> VMClone Version: $VER" echo "*****" exit fi # Check for ROOT permissions. if [ $EUID -ne "0" ] then echo " " echo "Effective permissions not ROOT." echo "Please run this script as ROOT user." echo " " exit fi # Set some initial variables... B_NAME=$1 B_VMX=$2 B_VMDK=$3 C_NAME=$4 REN_CMD="`which vmware-vdiskmanager`" SNAP_CMD="`which vmrun`" VM_CMD="`which vmware-cmd`" B_PATH="`pwd`" # Check if OPTION is specified... if [ -n "$5" ] then OPTION=$5 fi # Figure out the snapshot file name. B_SNAP=`echo "$B_VMDK" | sed 's/.vmdk/-000001.vmdk/'` ################# # FUNCTION LIST # ################# # Define some useful functions... # Check if snapshot is already done - if not, create the snapshot. check_for_snap () { if [ ! -e "$B_SNAP" ] then $VM_CMD -s register "$B_PATH"/"$B_VMX" 2>/dev/null >/dev/null $SNAP_CMD snapshot "$B_PATH"/"$B_VMX" 2>/dev/null >/dev/null fi } # Assumes CWD is $B_NAME - after clone creation, returns to $B_NAME. make_clone () { if [ "$OPTION" = "cluster" ] then mkdir -p ../"$CL_BASE"/"$C_NAME" else mkdir ../"$C_NAME" fi cp "$B_VMX" "$C_NAME.vmx" rm -f *.vmsn rm -f *.vmsd if [ "$OPTION" = "cluster" ] then mv "$C_NAME.vmx" ../"$CL_BASE"/"$C_NAME" mv "$B_SNAP" ../"$CL_BASE"/"$C_NAME" else mv "$C_NAME.vmx" ../"$C_NAME" mv "$B_SNAP" ../"$C_NAME" fi # Replace the snapshot disk in B_VMX so that another snap can be taken. cat "$B_VMX" | sed 's/'"$B_SNAP"'/'"$B_VMDK"'/g' > "$B_VMX.new" mv "$B_VMX.new" "$B_VMX" if [ "$OPTION" = "cluster" ] then cd ../"$CL_BASE"/"$C_NAME" else cd ../"$C_NAME" fi # Now that we're in the clone's dir, set $C_PATH. C_PATH="`pwd`" $REN_CMD -q -n "$B_SNAP" "$C_NAME.vmdk" 2>/dev/null >/dev/null if [ "$OPTION" = "cluster" ] then ln -s ../../"$B_NAME"/"$B_VMDK" "$B_VMDK" else ln -s ../"$B_NAME"/"$B_VMDK" "$B_VMDK" fi # Edit the clone's VMX to reflect the new VMDK name and console display name. cat "$C_NAME.vmx" | sed 's/'"$B_SNAP"'/'"$C_NAME"'.vmdk/g' > "$C_NAME.new" mv "$C_NAME.new" "$C_NAME.vmx" cat "$C_NAME.vmx" | sed 's/'"$B_NAME"'/'"$C_NAME"'/g' > "$C_NAME.new" mv "$C_NAME.new" "$C_NAME.vmx" chmod 754 * # Register the clone with VM Server *if not* a cluster node. if [ "$OPTION" != "cluster" ] then $VM_CMD -s register "$C_PATH"/"$C_NAME.vmx" 2>/dev/null >/dev/null fi # CD back into the BASE VM dir. if [ "$OPTION" = "cluster" ] then cd ../../"$B_NAME" else cd ../"$B_NAME" fi } # Creates shared disks, adds shared disks to node VMX files, and adds 2 NIC's to node VMX files. add_cluster_resources () { # Create the shared disks. mkdir ../"$CL_BASE"/SHARED cd ../"$CL_BASE"/SHARED for ((i=1; i <= $NUM_SH_DISKS; i++)) do SH_DISK_NAME="$CL_BASE-D$i.vmdk" $REN_CMD -c -s "$SZ_SH_DISKS"Mb -a lsilogic -t 2 $SH_DISK_NAME 2>/dev/null >/dev/null done # Add the shared disks into the NODES' VMX files. for ((i=1; i <= REPS; i++)) do N_FILE="../$CL_BASE-N$i/$CL_BASE-N$i.vmx" echo "disk.locking = \"FALSE\"" >> $N_FILE echo "diskLib.dataCacheMaxSize = \"0\"" >> $N_FILE echo "scsi3.sharedBus = virtual" >> $N_FILE echo "scsi3.present = \"TRUE\"" >> $N_FILE echo "scsi3.virtualDev = \"lsilogic\"" >> $N_FILE for ((z=1; z <= $NUM_SH_DISKS; z++)) do if [ $z -lt 7 ] then echo "scsi3:$z.present = \"TRUE\"" >> $N_FILE echo "scsi3:$z.fileName = \"../SHARED/$CL_BASE-D$z.vmdk\"" >> $N_FILE echo "scsi3:$z.writeThrough = \"TRUE\"" >> $N_FILE echo "scsi3:$z.mode = \"independent-persistent\"" >> $N_FILE else # Must skip ID 7 when setting SCSI ID. let y=$z+1 echo "scsi3:$y.present = \"TRUE\"" >> $N_FILE echo "scsi3:$y.fileName = \"../SHARED/$CL_BASE-D$z.vmdk\"" >> $N_FILE echo "scsi3:$y.writeThrough = \"TRUE\"" >> $N_FILE echo "scsi3:$y.mode = \"independent-persistent\"" >> $N_FILE fi done done # Check if more than 1 NIC preset - if not, add 2 NIC's on HOSTONLY network. # Since they are clones, we can just check the first node's VMX. cd ../"$CL_BASE-N1" if grep -q "Ethernet1.present" "$CL_BASE-N1.vmx" then echo " " echo "Cluster Nodes appear to already have more than one NIC - not adding any NIC's." cd .. else echo " " echo "Cluster Nodes have 1 NIC - adding 2 more NIC's to the HOSTONLY network..." # Grab the name of the NIC device in use. NIC_LINE="`grep Ethernet0.virtualDev \"$CL_BASE-N1.vmx\"`" NIC1="`echo "$NIC_LINE" | sed 's/'Ethernet0'/'Ethernet1'/g'`" NIC2="`echo "$NIC_LINE" | sed 's/'Ethernet0'/'Ethernet2'/g'`" cd .. for ((i=1; i <= REPS; i++)) do N_FILE="$CL_BASE-N$i"/"$CL_BASE-N$i.vmx" echo "Ethernet1.present = \"TRUE\"" >> $N_FILE echo "Ethernet1.connectionType = \"hostonly\"" >> $N_FILE echo "$NIC1" >> $N_FILE echo "Ethernet2.present = \"TRUE\"" >> $N_FILE echo "Ethernet2.connectionType = \"hostonly\"" >> $N_FILE echo "$NIC2" >> $N_FILE done fi cd "$B_PATH" } register_cluster_nodes () { # Do this last because we want to add the shared disks and NIC's before updating VM Server. for ((i=1; i <= REPS; i++)) do cd ../"$CL_BASE"/"$CL_BASE-N$i" L_PATH="`pwd`" $VM_CMD -s register "$L_PATH"/"$CL_BASE-N$i.vmx" 2>/dev/null >/dev/null cd "$B_PATH" done } ######## # MAIN # ######## # If OPTION is "multi", then we need to create multiple clones, using C_NAME as a base name. if [ "$OPTION" = "multi" ] then # If $6 is a valid number of clones between 2 and 10, set REPS. if [ -n "$6" ] && [ $6 -ge 2 ] && [ $6 -le 10 ] then REPS=$6 else echo " " echo "Sorry, MULTI was specified, but the number of VM's to create was not between 2 and 10." echo "Please try again." echo " " exit fi #Save the base name before calling make_clone() multiple times. M_BASE="$C_NAME" for ((i=1; i <= REPS; i++)) do C_NAME="$M_BASE-$i" check_for_snap make_clone done #Check for "cluster" option. elif [ "$OPTION" = "cluster" ] then # If $6 is a valid number of cluster nodes between 2 and 5, set REPS. if [ -n "$6" ] && [ $6 -ge 2 ] && [ $6 -le 5 ] then REPS=$6 else echo " " echo "Sorry, CLUSTER was specified, but the number of NODES to create was not between 2 and 5." echo "Please try again." echo " " exit fi #Prompt for the size of the shared disks - in MB. #And prompt for how many. Valid = 1 to 14 (beyond that is another SCSI bus.) #Warn user that this requires full disk space. echo " " echo "Cluster was specified - if this is not correct, use CONTROL-C to exit." echo "Creating shared disks...NOTE that the shared disks require full disk space." echo "IE - (4) disks @ 500MB = 2GB used disk space." echo " " echo -n "How many shared disks to create? (Valid = 1 to 14):" read NUM_SH_DISKS echo -n "And what size for the shared disks - in MB? (Valid = 100 to 2048):" read SZ_SH_DISKS if [ $NUM_SH_DISKS -lt 1 ] || [ $NUM_SH_DISKS -gt 14 ] then echo "The number of disks is invalid - exiting..." echo " " exit 5 fi if [ $SZ_SH_DISKS -lt 100 ] || [ $SZ_SH_DISKS -gt 2048 ] then echo "The size of the shared disks is invalid - exiting..." echo " " exit 5 fi #Save the cluster name before calling make_clone() multiple times. CL_BASE="$C_NAME" for ((i=1; i <= REPS; i++)) do C_NAME="$CL_BASE-N$i" check_for_snap make_clone done # Testing... echo " " echo "Adding $NUM_SH_DISKS shared disks at $SZ_SH_DISKS MB each..." add_cluster_resources register_cluster_nodes else # No OPTION - single clone to create. check_for_snap make_clone # If $OPTION "start" was specified, start the clone VM. if [ -n "$OPTION" ] && [ "$OPTION" = "start" ] then $SNAP_CMD start "$C_PATH"/"$C_NAME.vmx" 2>/dev/null >/dev/null fi fi echo " " echo "Linked clone(s) created successfully..." echo "Within a few seconds, you should see the clone VM listed in the VM Console." echo " " echo " " exit
- 08-19-2008 #4Just Joined!
- Join Date
- Aug 2008
- Posts
- 11
Thanks for the quick reply.
I saw the caveat about the 2GB chunks and it's not set up that way. I'll try this one. THanks.
- 08-19-2008 #5Just Joined!
- Join Date
- Aug 2008
- Posts
- 11
- 08-19-2008 #6Linux Guru
- Join Date
- Nov 2007
- Posts
- 1,695
o.O
No. I and ~30 other people use this script almost daily. I sent you a PM.
- 08-20-2008 #7Just Joined!
- Join Date
- Aug 2008
- Posts
- 11
I sent a PM, did you get it?
- 08-20-2008 #8Linux Guru
- Join Date
- Nov 2007
- Posts
- 1,695
Problem solved - Bentman was using a "fully allocated" or "thick" virtual disk where the entire disk space is allocated. VMWare creates a second file (-flat.vmdk) when this option is used. While this kind of defeats the purpose of linked clones and using as little disk space as possible, I updated the script to deal with this scenario:
Code:#!/bin/bash # VMClone.sh # Small shell script to create *linked clones* on VMWare Server. # Author: HROAdmin26 # Last Edited: 2008-08-20 # Revision: 1.8 VER="1.8_2008-08-20" # README: # Copy this script to some place in your PATH statement # and make it executable - /usr/bin is a good place. # On the command line, CD into the directory of your base VM. # Run vmclone.sh with no switches for the HELP info. # Run script as ROOT. # DO NOT use if your guest VMDK's are split into 2GB chunks. # If any of your names have spaces in them, use quotes. # Script is run on command line and expects 4 (or more) parameters: # $1 = BASE_VM_NAME # $2 = BASE_VM_VMX_FILE # $3 = BASE_VMDK_FILE # $4 = CLONE_VM_NAME/MULTI_BASE_NAME/CLUSTER_NAME # Example: vmclone "BOBO" "BOBO.vmx" "BOBO.vmdk" TIMMAY # $5 = Extra functionality. These are *NOT combinable.* Current options: # 1) If "start" is specified, the cloned VM is registered and started after cloning. # 2) If "multi" is specified, it must be followed by a number between 2 and 10 for the number of clones to create. The MULTI_BASE_NAME is appended with -1, -2, etc to name the multiple clones. # 3) If "cluster" is specified, it must be followed by a number between 2 and 5 for the number of nodes. # Examples: # 1) vmclone.sh "BOBO" "BOBO.vmx" "BOBO.vmdk" TIMMAY start # 2) vmclone.sh "BOBO" "BOBO.vmx" "BOBO.vmdk" CLONAL multi 7 # 3) vmclone.sh "BONGO" "BONGO.vmx" "BIG_DISK.vmdk" NODAL cluster 3 # CAVEATS! PLEASE READ AND UNDERSTAND! # > Some users have reported issues if the base VM has more than 1 disk - your mileage may vary. < # > Your DISPLAY_NAME for the Base VM in the VMWare Console must match the folder name of the Base VM. < # > When using the 'cluster' switch, the shared disks are added on an LSILOGIC adapter. < # > When using the 'cluster' switch, a folder named CLUSTER_NAME is created - the nodes and shared disks are created inside this folder. < if [ $# -lt 4 ] then echo "*****" echo "Usage: vmclone.sh \"BASE_VM_NAME\" \"BASE_VMX_FILE\" \"BASE_VMDK_FILE\" \"CLONE_VM_NAME\"" echo " " echo "Example: vmclone.sh \"BIG SERVER\" \"SLES_9.vmx\" \"BigTuna.vmdk\" \"BIGGER_SERVER\"" echo " " echo "==> WARNING! Do not use this script if the .VMDK files are split into 2GB chunks." echo "==> Usage Steps:" echo "==> ** This new version of vmclone will create the snapshot for you if it does not already exist." echo "==> Step 1) Change directory INTO the folder of your BASE VM and then run vmclone." echo "==> More usage options can be found in the script itself - \"more vmclone.sh\"." echo " " echo "==> Some more usage examples:" echo "==> vmclone.sh \"BOBO\" \"BOBO.vmx\" \"BOBO.vmdk\" TIMMAY start" echo "==> vmclone.sh \"BOBO\" \"BOBO.vmx\" \"BOBO.vmdk\" NODES multi 4" echo "==> vmclone.sh \"BOBO\" \"BOBO.vmx\" \"BOBO.vmdk\" WIN_CLUSTER cluster 3" echo " " echo "==> VMClone Version: $VER" echo "*****" exit fi # Check for ROOT permissions. if [ $EUID -ne "0" ] then echo " " echo "Effective permissions not ROOT." echo "Please run this script as ROOT user." echo " " exit fi # Set some initial variables... B_NAME=$1 B_VMX=$2 B_VMDK=$3 C_NAME=$4 REN_CMD="`which vmware-vdiskmanager`" SNAP_CMD="`which vmrun`" VM_CMD="`which vmware-cmd`" B_PATH="`pwd`" # Check if OPTION is specified... if [ -n "$5" ] then OPTION=$5 fi # Figure out the snapshot file name. B_SNAP=`echo "$B_VMDK" | sed 's/.vmdk/-000001.vmdk/'` # If virtual disk is "thick", there will be a -flat.vmdk we need to create an ln -s for. B_FLAT=`echo "$B_VMDK" | sed 's/.vmdk/-flat.vmdk/'` ################# # FUNCTION LIST # ################# # Define some useful functions... # Check if snapshot is already done - if not, create the snapshot. check_for_snap () { if [ ! -e "$B_SNAP" ] then $VM_CMD -s register "$B_PATH"/"$B_VMX" 2>/dev/null >/dev/null $SNAP_CMD snapshot "$B_PATH"/"$B_VMX" 2>/dev/null >/dev/null fi } # Assumes CWD is $B_NAME - after clone creation, returns to $B_NAME. make_clone () { if [ "$OPTION" = "cluster" ] then mkdir -p ../"$CL_BASE"/"$C_NAME" else mkdir ../"$C_NAME" fi cp "$B_VMX" "$C_NAME.vmx" rm -f *.vmsn rm -f *.vmsd if [ "$OPTION" = "cluster" ] then mv "$C_NAME.vmx" ../"$CL_BASE"/"$C_NAME" mv "$B_SNAP" ../"$CL_BASE"/"$C_NAME" else mv "$C_NAME.vmx" ../"$C_NAME" mv "$B_SNAP" ../"$C_NAME" fi # Replace the snapshot disk in B_VMX so that another snap can be taken. cat "$B_VMX" | sed 's/'"$B_SNAP"'/'"$B_VMDK"'/g' > "$B_VMX.new" mv "$B_VMX.new" "$B_VMX" if [ "$OPTION" = "cluster" ] then cd ../"$CL_BASE"/"$C_NAME" else cd ../"$C_NAME" fi # Now that we're in the clone's dir, set $C_PATH. C_PATH="`pwd`" $REN_CMD -q -n "$B_SNAP" "$C_NAME.vmdk" 2>/dev/null >/dev/null if [ "$OPTION" = "cluster" ] then ln -s ../../"$B_NAME"/"$B_VMDK" "$B_VMDK" # IF B_FLAT exists, need to create link to it also: if [ -e ../../"$B_NAME"/"$B_FLAT" ] then ln -s ../../"$B_NAME"/"$B_FLAT" "$B_FLAT" fi else ln -s ../"$B_NAME"/"$B_VMDK" "$B_VMDK" # IF B_FLAT exists, need to create link to it also: if [ -e ../"$B_NAME"/"$B_FLAT" ] then ln -s ../"$B_NAME"/"$B_FLAT" "$B_FLAT" fi fi # Edit the clone's VMX to reflect the new VMDK name and console display name. cat "$C_NAME.vmx" | sed 's/'"$B_SNAP"'/'"$C_NAME"'.vmdk/g' > "$C_NAME.new" mv "$C_NAME.new" "$C_NAME.vmx" cat "$C_NAME.vmx" | sed 's/'"$B_NAME"'/'"$C_NAME"'/g' > "$C_NAME.new" mv "$C_NAME.new" "$C_NAME.vmx" chmod 754 * # Register the clone with VM Server *if not* a cluster node. if [ "$OPTION" != "cluster" ] then $VM_CMD -s register "$C_PATH"/"$C_NAME.vmx" 2>/dev/null >/dev/null fi # CD back into the BASE VM dir. if [ "$OPTION" = "cluster" ] then cd ../../"$B_NAME" else cd ../"$B_NAME" fi } # Creates shared disks, adds shared disks to node VMX files, and adds 2 NIC's to node VMX files. add_cluster_resources () { # Create the shared disks. mkdir ../"$CL_BASE"/SHARED cd ../"$CL_BASE"/SHARED for ((i=1; i <= $NUM_SH_DISKS; i++)) do SH_DISK_NAME="$CL_BASE-D$i.vmdk" $REN_CMD -c -s "$SZ_SH_DISKS"Mb -a lsilogic -t 2 $SH_DISK_NAME 2>/dev/null >/dev/null done # Add the shared disks into the NODES' VMX files. for ((i=1; i <= REPS; i++)) do N_FILE="../$CL_BASE-N$i/$CL_BASE-N$i.vmx" echo "disk.locking = \"FALSE\"" >> $N_FILE echo "diskLib.dataCacheMaxSize = \"0\"" >> $N_FILE echo "scsi3.sharedBus = virtual" >> $N_FILE echo "scsi3.present = \"TRUE\"" >> $N_FILE echo "scsi3.virtualDev = \"lsilogic\"" >> $N_FILE for ((z=1; z <= $NUM_SH_DISKS; z++)) do if [ $z -lt 7 ] then echo "scsi3:$z.present = \"TRUE\"" >> $N_FILE echo "scsi3:$z.fileName = \"../SHARED/$CL_BASE-D$z.vmdk\"" >> $N_FILE echo "scsi3:$z.writeThrough = \"TRUE\"" >> $N_FILE echo "scsi3:$z.mode = \"independent-persistent\"" >> $N_FILE else # Must skip ID 7 when setting SCSI ID. let y=$z+1 echo "scsi3:$y.present = \"TRUE\"" >> $N_FILE echo "scsi3:$y.fileName = \"../SHARED/$CL_BASE-D$z.vmdk\"" >> $N_FILE echo "scsi3:$y.writeThrough = \"TRUE\"" >> $N_FILE echo "scsi3:$y.mode = \"independent-persistent\"" >> $N_FILE fi done done # Check if more than 1 NIC preset - if not, add 2 NIC's on HOSTONLY network. # Since they are clones, we can just check the first node's VMX. cd ../"$CL_BASE-N1" if grep -q "Ethernet1.present" "$CL_BASE-N1.vmx" then echo " " echo "Cluster Nodes appear to already have more than one NIC - not adding any NIC's." cd .. else echo " " echo "Cluster Nodes have 1 NIC - adding 2 more NIC's to the HOSTONLY network..." # Grab the name of the NIC device in use. NIC_LINE="`grep Ethernet0.virtualDev \"$CL_BASE-N1.vmx\"`" NIC1="`echo "$NIC_LINE" | sed 's/'Ethernet0'/'Ethernet1'/g'`" NIC2="`echo "$NIC_LINE" | sed 's/'Ethernet0'/'Ethernet2'/g'`" cd .. for ((i=1; i <= REPS; i++)) do N_FILE="$CL_BASE-N$i"/"$CL_BASE-N$i.vmx" echo "Ethernet1.present = \"TRUE\"" >> $N_FILE echo "Ethernet1.connectionType = \"hostonly\"" >> $N_FILE echo "$NIC1" >> $N_FILE echo "Ethernet2.present = \"TRUE\"" >> $N_FILE echo "Ethernet2.connectionType = \"hostonly\"" >> $N_FILE echo "$NIC2" >> $N_FILE done fi cd "$B_PATH" } register_cluster_nodes () { # Do this last because we want to add the shared disks and NIC's before updating VM Server. for ((i=1; i <= REPS; i++)) do cd ../"$CL_BASE"/"$CL_BASE-N$i" L_PATH="`pwd`" $VM_CMD -s register "$L_PATH"/"$CL_BASE-N$i.vmx" 2>/dev/null >/dev/null cd "$B_PATH" done } ######## # MAIN # ######## # If OPTION is "multi", then we need to create multiple clones, using C_NAME as a base name. if [ "$OPTION" = "multi" ] then # If $6 is a valid number of clones between 2 and 10, set REPS. if [ -n "$6" ] && [ $6 -ge 2 ] && [ $6 -le 10 ] then REPS=$6 else echo " " echo "Sorry, MULTI was specified, but the number of VM's to create was not between 2 and 10." echo "Please try again." echo " " exit fi #Save the base name before calling make_clone() multiple times. M_BASE="$C_NAME" for ((i=1; i <= REPS; i++)) do C_NAME="$M_BASE-$i" check_for_snap make_clone done #Check for "cluster" option. elif [ "$OPTION" = "cluster" ] then # If $6 is a valid number of cluster nodes between 2 and 5, set REPS. if [ -n "$6" ] && [ $6 -ge 2 ] && [ $6 -le 5 ] then REPS=$6 else echo " " echo "Sorry, CLUSTER was specified, but the number of NODES to create was not between 2 and 5." echo "Please try again." echo " " exit fi #Prompt for the size of the shared disks - in MB. #And prompt for how many. Valid = 1 to 14 (beyond that is another SCSI bus.) #Warn user that this requires full disk space. echo " " echo "Cluster was specified - if this is not correct, use CONTROL-C to exit." echo "Creating shared disks...NOTE that the shared disks require full disk space." echo "IE - (4) disks @ 500MB = 2GB used disk space." echo " " echo -n "How many shared disks to create? (Valid = 1 to 14):" read NUM_SH_DISKS echo -n "And what size for the shared disks - in MB? (Valid = 100 to 2048):" read SZ_SH_DISKS if [ $NUM_SH_DISKS -lt 1 ] || [ $NUM_SH_DISKS -gt 14 ] then echo "The number of disks is invalid - exiting..." echo " " exit 5 fi if [ $SZ_SH_DISKS -lt 100 ] || [ $SZ_SH_DISKS -gt 2048 ] then echo "The size of the shared disks is invalid - exiting..." echo " " exit 5 fi #Save the cluster name before calling make_clone() multiple times. CL_BASE="$C_NAME" for ((i=1; i <= REPS; i++)) do C_NAME="$CL_BASE-N$i" check_for_snap make_clone done # Testing... echo " " echo "Adding $NUM_SH_DISKS shared disks at $SZ_SH_DISKS MB each..." add_cluster_resources register_cluster_nodes else # No OPTION - single clone to create. check_for_snap make_clone # If $OPTION "start" was specified, start the clone VM. if [ -n "$OPTION" ] && [ "$OPTION" = "start" ] then $SNAP_CMD start "$C_PATH"/"$C_NAME.vmx" 2>/dev/null >/dev/null fi fi echo " " echo "Linked clone(s) created successfully..." echo "Within a few seconds, you should see the clone VM listed in the VM Console." echo " " echo " " exit
- 09-03-2008 #9Just Joined!
- Join Date
- Aug 2008
- Posts
- 11
I was wondering. I have a directory of /var/vm that holds my vm's. I'd like to store all of my images in /var/vm/images. When I run the script to create the linked clone in the /var/vm directory. This help's me keep the directory clean.
I'm certainly no bash script master, any help would be appreciated.
- 09-25-2008 #10Just Joined!
- Join Date
- Sep 2008
- Posts
- 9
Can I use this script on vmware workstation on Linux? If we have hundred of master images on a SAN, each time we update the master image the linked clones will die. I am trying to find a way to easily create new linked clones for each workstation...


Reply With Quote
