github.com/vmware/govmomi@v0.51.0/scripts/vcsa/create-esxi-vm.sh (about) 1 #!/bin/bash -e 2 3 # © Broadcom. All Rights Reserved. 4 # The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 5 # SPDX-License-Identifier: Apache-2.0 6 # 7 # Create a VM and boot stateless ESXi via cdrom/iso 8 9 set -o pipefail 10 11 usage() { 12 cat <<'EOF' 13 Usage: $0 [-d DISK_GB] [-m MEM_GB] [-i ESX_ISO] [-s] ESX_URL VM_NAME 14 15 GOVC_* environment variables also apply, see https://github.com/vmware/govmomi/tree/main/govc#usage 16 If GOVC_USERNAME is set, it is used to create an account on the ESX vm. Default is to use the existing root account. 17 If GOVC_PASSWORD is set, the account password will be set to this value. Default is to use the given ESX_URL password. 18 EOF 19 } 20 21 disk=48 22 mem=16 23 # 6.7 U3 24 iso=VMware-VMvisor-6.7.0-14320388.x86_64.iso 25 26 while getopts d:hi:m:s flag 27 do 28 case $flag in 29 d) 30 disk=$OPTARG 31 ;; 32 h) 33 usage 34 exit 35 ;; 36 i) 37 iso=$OPTARG 38 ;; 39 m) 40 mem=$OPTARG 41 ;; 42 s) 43 standalone=true 44 ;; 45 *) 46 usage 1>&2 47 exit 1 48 ;; 49 esac 50 done 51 52 shift $((OPTIND-1)) 53 54 if [ $# -ne 2 ] ; then 55 usage 56 exit 1 57 fi 58 59 if [[ "$iso" == *"-Installer-"* ]] ; then 60 echo "Invalid iso name (need stateless, not installer): $iso" 1>&2 61 exit 1 62 fi 63 64 export GOVC_INSECURE=1 65 export GOVC_URL=$1 66 network=${GOVC_NETWORK:-"VM Network"} 67 username=$GOVC_USERNAME 68 password=$GOVC_PASSWORD 69 unset GOVC_USERNAME GOVC_PASSWORD 70 71 guest=${GUEST:-"vmkernel65Guest"} 72 73 if [ -z "$password" ] ; then 74 # extract password from $GOVC_URL 75 password=$(govc env GOVC_PASSWORD) 76 fi 77 78 shift 79 80 name=$1 81 shift 82 83 echo -n "Checking govc version..." 84 govc version -require 0.15.0 85 86 if [ "$(govc env -x GOVC_URL_HOST)" = "." ] ; then 87 if [ "$(uname -s)" = "Darwin" ]; then 88 PATH="/Applications/VMware Fusion.app/Contents/Library:$PATH" 89 fi 90 91 dir="${name}.vmwarevm" 92 vmx="$dir/${name}.vmx" 93 94 if [ -d "$dir" ] ; then 95 if vmrun list | grep -q "$vmx" ; then 96 vmrun stop "$vmx" hard 97 fi 98 rm -rf "$dir" 99 fi 100 101 mkdir "$dir" 102 vmware-vdiskmanager -c -s "${disk}GB" -a lsilogic -t 1 "$dir/${name}.vmdk" 2>/dev/null 103 104 cat > "$vmx" <<EOF 105 config.version = "8" 106 virtualHW.version = "11" 107 numvcpus = "2" 108 memsize = "$((mem*1024))" 109 displayName = "$name" 110 guestOS = "vmkernel6" 111 vhv.enable = "TRUE" 112 scsi0.present = "TRUE" 113 scsi0.virtualDev = "lsilogic" 114 scsi0:0.present = "TRUE" 115 scsi0:0.fileName = "${name}.vmdk" 116 ide1:0.present = "TRUE" 117 ide1:0.fileName = "$(realpath "$iso")" 118 ide1:0.deviceType = "cdrom-image" 119 ethernet0.present = "TRUE" 120 ethernet0.connectionType = "nat" 121 ethernet0.virtualDev = "e1000" 122 ethernet0.wakeOnPcktRcv = "FALSE" 123 ethernet0.linkStatePropagation.enable = "TRUE" 124 vmci0.present = "TRUE" 125 hpet0.present = "TRUE" 126 tools.syncTime = "TRUE" 127 pciBridge0.present = "TRUE" 128 pciBridge4.present = "TRUE" 129 pciBridge4.virtualDev = "pcieRootPort" 130 pciBridge4.functions = "8" 131 pciBridge5.present = "TRUE" 132 pciBridge5.virtualDev = "pcieRootPort" 133 pciBridge5.functions = "8" 134 pciBridge6.present = "TRUE" 135 pciBridge6.virtualDev = "pcieRootPort" 136 pciBridge6.functions = "8" 137 pciBridge7.present = "TRUE" 138 pciBridge7.virtualDev = "pcieRootPort" 139 pciBridge7.functions = "8" 140 EOF 141 142 vmrun start "$vmx" nogui 143 vm_ip=$(vmrun getGuestIPAddress "$vmx" -wait) 144 else 145 export GOVC_DATASTORE=${GOVC_DATASTORE:-$(basename "$(govc ls datastore)")} 146 if [ "$(govc about -json | jq -r .About.ProductLineId)" == "embeddedEsx" ] ; then 147 policy=$(govc host.portgroup.info -json | jq -r ".Portgroup[] | select(.Spec.Name == \"$network\") | .Spec.Policy.Security") 148 if [ -n "$policy" ] && [ "$(jq -r <<<"$policy" .AllowPromiscuous)" != "true" ] ; then 149 echo "Enabling promiscuous mode for $network on $(govc env -x GOVC_URL_HOST)..." 150 govc host.portgroup.change -allow-promiscuous "$network" 151 fi 152 fi 153 154 boot=$(basename "$iso") 155 if ! govc datastore.ls "$boot" > /dev/null 2>&1 ; then 156 govc datastore.upload "$iso" "$boot" 157 fi 158 159 echo "Creating vm ${name}..." 160 govc vm.create -on=false -net "$network" -m $((mem*1024)) -c 2 -g "$guest" -net.adapter=vmxnet3 -disk.controller pvscsi "$name" 161 162 echo "Adding a second nic for ${name}..." 163 govc vm.network.add -net "$network" -net.adapter=vmxnet3 -vm "$name" 164 165 echo "Enabling nested hv for ${name}..." 166 govc vm.change -vm "$name" -nested-hv-enabled 167 168 echo "Enabling Mac Learning dvFilter for ${name}..." 169 seq 0 1 | xargs -I% govc vm.change -vm "$name" \ 170 -e ethernet%.filter4.name=dvfilter-maclearn \ 171 -e ethernet%.filter4.onFailure=failOpen 172 173 echo "Adding cdrom device to ${name}..." 174 id=$(govc device.cdrom.add -vm "$name") 175 176 echo "Inserting $boot into $name cdrom device..." 177 govc device.cdrom.insert -vm "$name" -device "$id" "$boot" 178 179 if [ -n "$standalone" ] ; then 180 echo "Creating $name disk for use by ESXi..." 181 govc vm.disk.create -vm "$name" -name "$name"/disk1 -size "${disk}G" 182 fi 183 184 echo "Powering on $name VM..." 185 govc vm.power -on "$name" 186 187 echo "Waiting for $name ESXi IP..." 188 vm_ip=$(govc vm.ip "$name") 189 190 ! govc events -n 100 "vm/$name" | grep -E 'warning|error' 191 fi 192 193 esx_url="root:@${vm_ip}" 194 echo "Waiting for $name hostd (via GOVC_URL=$esx_url)..." 195 while true; do 196 if govc about -u "$esx_url" 2>/dev/null; then 197 break 198 fi 199 200 printf "." 201 sleep 1 202 done 203 204 if [ -z "$standalone" ] ; then 205 # Create disk for vSAN after boot so they are unclaimed 206 echo "Creating $name disks for use by vSAN..." 207 govc vm.disk.create -vm "$name" -name "$name"/vsan-cache -size "$((disk/2))G" 208 govc vm.disk.create -vm "$name" -name "$name"/vsan-store -size "${disk}G" 209 fi 210 211 # Set target to the ESXi VM 212 GOVC_URL="$esx_url" 213 214 if [ -z "$standalone" ] ; then 215 echo "Rescanning ${name} HBA for new devices..." 216 disk=($(govc host.storage.info -rescan | grep /vmfs/devices/disks | awk '{print $1}' | sort)) 217 218 echo "Marking ${name} disk ${disk[0]} as SSD..." 219 govc host.storage.mark -ssd "${disk[0]}" 220 221 echo "Marking ${name} disk ${disk[1]} as HDD..." 222 govc host.storage.mark -ssd=false "${disk[1]}" 223 fi 224 225 echo "Configuring NTP for ${name}..." 226 govc host.date.change -server 0.pool.ntp.org 227 228 for id in TSM TSM-SSH ntpd ; do 229 printf "Enabling service %s for ${name}...\n" $id 230 govc host.service enable $id 231 govc host.service start $id 232 done 233 234 if [ -z "$username" ] ; then 235 username=root 236 action="update" 237 else 238 action="create" 239 fi 240 241 echo "Disabling VSAN device monitoring for ${name}..." 242 govc host.esxcli system settings advanced set -o /LSOM/VSANDeviceMonitoring -i 0 243 244 # A setting of 1 means that vSwp files are created thin, with 0% Object Space Reservation 245 govc host.esxcli system settings advanced set -o /VSAN/SwapThickProvisionDisabled -i 1 246 govc host.esxcli system settings advanced set -o /VSAN/FakeSCSIReservations -i 1 247 248 echo "ESX host account $action for user $username on ${name}..." 249 govc host.account.$action -id $username -password "$password" 250 251 echo "Granting Admin permissions for user $username on ${name}..." 252 govc permissions.set -principal $username -role Admin 253 254 echo "Enabling guest ARP inspection to get vm IPs without vmtools on ${name}..." 255 govc host.esxcli system settings advanced set -o /Net/GuestIPHack -i 1 256 257 echo "Opening firewall for serial port traffic for ${name}..." 258 govc host.esxcli network firewall ruleset set -r remoteSerialPort -e true 259 260 echo "Setting hostname for ${name}..." 261 govc host.esxcli system hostname set -H "$name" 262 263 echo "Enabling MOB for ${name}..." 264 govc host.option.set Config.HostAgent.plugins.solo.enableMob true 265 266 if which sshpass >/dev/null && [ -e ~/.ssh/id_rsa.pub ] ; then 267 echo "Adding ssh authorized key to ${name}..." 268 sshpass -p "$password" scp \ 269 -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=error \ 270 ~/.ssh/id_rsa.pub "root@$vm_ip:/etc/ssh/keys-root/authorized_keys" 271 fi 272 273 echo "Done: GOVC_URL=${username}:${password}@${vm_ip}"