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