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}"