/devops-terraform-esxi-boilerplate

POC for managing free esxi instance with opensource terraform provider via ssh workaround

Primary LanguageHCL

#First steps

  1. Get VMware OVF Tool for Linux 64-bit installed in path
  2. Get esxi plugin for terraform installed from https://github.com/josenk/terraform-provider-esxi
  3. Configure main.tf
  4. Any ovf template or vm to be cloned from should be witn UNPLAGGED cdroms and with as less devices as possible

than, as usually

terraform init terraform plan terraform apply terraform destroy

Example: preparing ubuntu server image for cloning.

  1. Install operation system
  2. Install cloud-init (optional)
  3. For development operations (not recommended) - you can deactivate automatic cron for updates
#!/bin/bash

systemctl stop apt-daily.service
systemctl kill --kill-who=all apt-daily.service

# wait until `apt-get updated` has been killed
while ! (systemctl list-units --all apt-daily.service | fgrep -q dead)
do
  sleep 1;
done

systemctl mask apt-daily.service apt-daily-upgrade.service
  1. Install open-vm-tools
  2. Reset cloud-init before suspending state
sudo cloud-init clean
  1. Shutdown and unplug CD and unnecessary devices

Deploying VM

resource "esxi_guest" "vmtest" {
  # guest_name - Required - The Guest name.
  guest_name         = "vmtest"
  # guestos  # Optional - Default will be taken from cloned source
  notes              = "ProjectX"  # Optional - The Guest notes (annotation).
  disk_store         = var.disk_store # Required - esxi Disk Store where guest vm will be created
  boot_disk_type     = "thin" # Optional - Guest boot disk type. Default 'thin'. Available thin, zeroedthick, eagerzeroedthick
  boot_disk_size     = "30" # Optional - Specify boot disk size or grow cloned vm to this size.
  memsize            = "4096" # Optional - Memory size in MB. (ie, 1024 == 1GB). See esxi documentation for limits. - Default 512 or default taken from cloned source
  numvcpus           = "1" # Optional - Number of virtual cpus. See esxi documentation for limits. - Default 1 or default taken from cloned source.
  virthwver          = "8" #  Optional - esxi guest virtual HW version. See esxi documentation for compatible values. - Default 8 or taken from cloned source.
  power              = "on" # Optional - on, off.
  guest_startup_timeout = "45"

  network_interfaces {
     virtual_network = var.virtual_network
  }

//  guestinfo = {
////    "coreos.config.data.encoding" = "base64"
////    "coreos.config.data" = base64encode(data.ignition_config.coreos.rendered)
//    "userdata.encoding" = "gzip+base64"
//    "userdata"          = base64gzip(data.template_file.userdata_default.rendered)
//  }

  #
  #  Specify an existing guest to clone, an ovf source, or neither to build a bare-metal guest vm.
  #
  clone_from_vm      = var.vm_clone_from #  Source vm to clone. Mutually exclusive with ovf_source option.
  #ovf_source        = var.vm_ovf_local_path # ovf files to use as a source. Mutually exclusive with clone_from_vm option.

  #Array of upto 10 network interfaces.
  #virtual_network - Required for each Guest NIC - This is the esxi virtual network name configured on esxi host.
  #mac_address - Optional - If not set, mac_address will be generated by esxi.
  #nic_type - Optional - See esxi documentation for compatibility list. - Default "e1000" or taken from cloned source.

  # Other optionals

  # resource_pool_name - Optional - Any existing or terraform managed resource pool name. - Default "/"
  # virtual_disks - Optional - Array of additional storage to be added to the guest.
  #     virtual_disk_id - Required - virtual_disk.id from esxi_virtual_disk resource.
  #     slot - Required - SCSI_Ctrl:SCSI_id. Range '0:1' to '3:15'. SCSI_id 7 is not allowed.
  # guest_startup_timeout - Optional - The amount of guest uptime, in seconds, to wait for an available IP address on this virtual machine.
  # guest_shutdown_timeout - Optional - The amount of time, in seconds, to wait for a graceful shutdown before doing a forced power off.

  # guestinfo - Optional - The Guestinfo root
  # metadata - Optional - A JSON string containing the cloud-init metadata.
  # metadata.encoding - Optional - The encoding type for guestinfo.metadata. (base64 or gzip+base64)
  # userdata - Optional - A YAML document containing the cloud-init user data.
  # userdata.encoding - Optional - The encoding type for guestinfo.userdata. (base64 or gzip+base64)
  # vendordata - Optional - A YAML document containing the cloud-init vendor data.
  # vendordata.encoding - Optional - The encoding type for guestinfo.vendordata (base64 or gzip+base64)

  # /Other optionals

  # OUTPUTS
  # ip_address - Computed - The IP address reported by VMware tools.
}

Exporting VM as ovf

Caveats

There are a few issues that you can potentially run into that are well-known, but I think are still worth mentioning here.

Special characters in URIs, including passwords (string starting with vi://) must be escaped. Use % followed by the character HEX code.

For example use "vi://root:P%40ssword@192.168.2.2", instead of "vi://root:P@ssword@192.168.2.2" or you can get confusing errors similar to this:

Error: Could not lookup host: root

Disconnect ISO images from VMs before migrating them or you will get the following error:

Error: A general system error occurred: vim.fault.FileNotFound

ovftool -dm=thin "vi://esxi/templateU18S" .
Enter login information for source vi://192.168.2.2/
Username: root
Password: ***********
Opening VI source: vi://root@192.168.2.2:443/templateU18S
Opening OVF target: .
Writing OVF package: ./templateU18S/templateU18S.ovf
Transfer Completed
Completed successfully

Creating VM using ovftool

From ovf template (stored locally)

ovftool --acceptAllEulas --noSSLVerify --noImageFiles --X:useMacNaming=false -dm=thin --name='vmtest2' --overwrite -ds='ESXI'  --network='VM Network' '/home/slavko/personal/ESXI/templateU18S/templateU18S.ovf' 'vi://USER:PASSWORD@esxi/'

From existing machine on a esxi host (stored remotely)

Generally this is subset of the command from moving VM between ESXi hosts, but applied to the same host.

ovftool --acceptAllEulas --noSSLVerify --X:useMacNaming=false -dm=thin --name='vmtest' --overwrite -ds='ESXI'  'vi://USER:PASSWORD@esxi/templateU18S' 'vi://USER:PASSWORD%21@esxi/'

ESXI notes

Some commands you can execute on a esxi box itself are listed and will be added below

VMWare version

vmware --version
VMware ESXi 6.7.0 build-8169922

List disk stores

esxcli storage filesystem list | grep '/vmfs/volumes/.*[VMFS|
NFS]' | awk '{print $2}'

ESXI

List vms

vim-cmd vmsvc/getallvms 2>/dev/null | sort -n | grep "[0-9] *" | awk '{print $1 " " $2}'

2 LOCALU18
6 debian8
7 debian9
8 LBM
11 awx-U1604LTS
15 templateU18S
28 vmtest