├── LICENSE ├── README.md ├── clone.sh └── deleteclone.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Peter Den Hartog 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | esxi-linked-clone 2 | ================= 3 | 4 | A utility script to create linked clones of a base virtual machine. 5 | 6 | To run this script, you must first have created (and presumably installed an OS on) a base virtual machine. A single snapshot of the machine must be taken from within the vSphere client prior to running the script. 7 | 8 | After creating and snapshotting the base machine, it must be left alone. 9 | 10 | SSH into your ESXi host and copy clone.sh to your datastore. Run clone.sh with the first argument being the folder name of your base image and the second argument being the name of the folder you want the clone output to. 11 | 12 | For example: 13 | 14 | ```ShellSession 15 | /vmfs/volumes/521bbe8d-709fe0eb-baca-0015c5e15f7c # ls 16 | 32bit Server Clone 1 Server Clone 1 Ubuntu Server Base (Don't Touch) 17 | 32bit Server Clone 2 Server Clone 2 clone.sh 18 | Fast Controller Server Clone 3 19 | Peter Test Adserver Ubuntu 32bit Server Base (Don't Touch) 20 | /vmfs/volumes/521bbe8d-709fe0eb-baca-0015c5e15f7c # ./clone.sh Ubuntu\ Server\ Base\ \(Don\'t\ Touch\)/ Server\ Clone\ 4 21 | /vmfs/volumes/521bbe8d-709fe0eb-baca-0015c5e15f7c # ls 22 | 32bit Server Clone 1 Server Clone 1 Ubuntu 32bit Server Base (Don't Touch) 23 | 32bit Server Clone 2 Server Clone 2 Ubuntu Server Base (Don't Touch) 24 | Fast Controller Server Clone 3 clone.sh 25 | Peter Test Adserver Server Clone 4 26 | ``` -------------------------------------------------------------------------------- /clone.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | readonly NUMARGS=$# 4 | readonly INFOLDER=$1 5 | readonly OUTFOLDER=$2 6 | 7 | usage() { 8 | echo "USAGE: ./clone.sh base_image_folder out_folder" 9 | } 10 | makeandcopy() { 11 | mkdir "$OUTFOLDER" 12 | cp "$INFOLDER"/*-"$VMFILE"* "$OUTFOLDER"/ 13 | cp "$INFOLDER"/*.vmx "$OUTFOLDER"/ 14 | } 15 | main() { 16 | if [ $NUMARGS -le 1 ] 17 | then 18 | usage 19 | exit 1 20 | fi 21 | 22 | if echo "$INFOLDER" | grep "[[:space:]]" 23 | then 24 | echo '$INFOLDER cannot contain spaces!' 25 | exit 1 26 | fi 27 | 28 | if echo "$INFOLDER" | grep "/" 29 | then 30 | echo '$INFOLDER cannot contain slashes!' 31 | exit 1 32 | fi 33 | 34 | VMFILE=`grep -E "(scsi|sata)0\:0\.fileName" "$INFOLDER"/*.vmx | grep -o "[0-9]\{6,6\}"` 35 | if [ -z "$VMFILE" ] 36 | then 37 | echo "No $VMFILE found!" 38 | exit 1 39 | fi 40 | 41 | makeandcopy 42 | 43 | #reference snapshot 44 | SNAPSHOT=`grep -o "[^\"]*.vmsn" "$INFOLDER"/*.vmx || (cd "$INFOLDER" && ls -r *.vmsn) | tail -1` 45 | if [ -n "$SNAPSHOT" ] 46 | then 47 | sed -i -e '/checkpoint.vmState =/s/= .*/= "..\/'$INFOLDER'\/'$SNAPSHOT'"/' $OUTFOLDER/*.vmx 48 | sed -i -e 's/checkpoint.vmState.readOnly = "FALSE"/checkpoint.vmState.readOnly = "TRUE"/' $OUTFOLDER/*.vmx 49 | fi 50 | 51 | local fullbasepath=$(readlink -f "$INFOLDER")/ 52 | cd "$OUTFOLDER"/ 53 | sed -i '/sched.swap.derivedName/d' ./*.vmx #delete swap file line, will be auto recreated 54 | sed -i -e '/displayName =/ s/= .*/= "'$OUTFOLDER'"/' ./*.vmx #Change display name config value 55 | local escapedpath=$(echo "$fullbasepath" | sed -e 's/[\/&]/\\&/g') 56 | sed -i -e '/parentFileNameHint=/ s/="/="'"$escapedpath"'/' ./*-"$VMFILE".vmdk #change parent disk path 57 | 58 | # Forces generation of new MAC + DHCP, I think. 59 | sed -i '/ethernet0.generatedAddress/d' ./*.vmx 60 | sed -i '/ethernet0.addressType/d' ./*.vmx 61 | 62 | # Forces creation of a fresh UUID for the VM. Obviates the need for the line 63 | # commented out below: 64 | #echo 'answer.msg.uuid.altered="I copied it" ' >>./*.vmx 65 | sed -i '/uuid.location/d' ./*.vmx 66 | sed -i '/uuid.bios/d' ./*.vmx 67 | 68 | # Things that ghetto-esxi-linked-clones.sh did that we might want. I can only guess at their use/value. 69 | #sed -i '/scsi0:0.fileName/d' ${STORAGE_PATH}/$FINAL_VM_NAME/$FINAL_VM_NAME.vmx 70 | #echo "scsi0:0.fileName = \"${STORAGE_PATH}/${GOLDEN_VM_NAME}/${VMDK_PATH}\"" >> ${STORAGE_PATH}/$FINAL_VM_NAME/$FINAL_VM_NAME.vmx 71 | #sed -i 's/nvram = "'${GOLDEN_VM_NAME}.nvram'"/nvram = "'${FINAL_VM_NAME}.nvram'"/' ${STORAGE_PATH}/$FINAL_VM_NAME/$FINAL_VM_NAME.vmx 72 | #sed -i 's/extendedConfigFile = "'${GOLDEN_VM_NAME}.vmxf'"/extendedConfigFile = "'${FINAL_VM_NAME}.vmxf'"/' ${STORAGE_PATH}/$FINAL_VM_NAME/$FINAL_VM_NAME.vmx 73 | 74 | # delete machine id 75 | sed -i '/machine.id/d' *.vmx 76 | 77 | # add machine id 78 | sed -i -e "\$amachine.id=$OUTFOLDER" *.vmx 79 | 80 | # Register the machine so that it appears in vSphere. 81 | FULL_PATH=`pwd`/*.vmx 82 | VMID=`vim-cmd solo/registervm $FULL_PATH` 83 | 84 | # Power on the machine. 85 | vim-cmd vmsvc/power.on $VMID 86 | } 87 | 88 | main 89 | -------------------------------------------------------------------------------- /deleteclone.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | # Deletes a cloned VM created by clone.sh. 4 | if [ $# -le 0 ] 5 | then 6 | echo "USAGE: ./deleteclone.sh vm_name" 7 | exit 1 8 | fi 9 | readonly VMNAME=$1 10 | 11 | if echo "$VMNAME" | grep "/" 12 | then 13 | echo '$VMNAME cannot contain slashes!' 14 | exit 1 15 | fi 16 | 17 | VMID=$(vim-cmd vmsvc/getallvms | awk "/^[0-9]+ +$VMNAME /{print \$1}") 18 | if [ -n "$VMID" ] 19 | then 20 | vim-cmd vmsvc/power.off $VMID 21 | vim-cmd vmsvc/unregister $VMID 22 | fi 23 | rm -rf $VMNAME 24 | --------------------------------------------------------------------------------