Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add script_text to linux_option customization #1621

Merged
merged 2 commits into from
Apr 6, 2022

Conversation

tenthirtyam
Copy link
Collaborator

@tenthirtyam tenthirtyam commented Mar 10, 2022

Description

Adds support for a customization script (script_text) to be run on a Linux guest operating system during guest customization using linux_options.

See VMware KB 74880 for VMware Tools prerequisites on the template.

Ensure that VMware Tools version 10.1.0 or later is installed.

In the VMware Tools configuration, the enable-custom-scripts option is disabled by default for security and will need to be enabled to run the script.

  • To check the value of this option, launch below command in guest operating system:
    vmware-toolbox-cmd config get deployPkg enable-custom-scripts

  • To enable this option, launch below command in guest operating system:
    vmware-toolbox-cmd config set deployPkg enable-custom-scripts true

Also, a helpful option could allow a user to use an in-guest script to customize the workload versus a provisioner.

Acceptance Tests

main.tf

provider "vsphere" {
  vsphere_server       = var.vsphere_server
  user                 = var.vsphere_username
  password             = var.vsphere_password
  allow_unverified_ssl = var.vsphere_insecure
}

data "vsphere_datacenter" "datacenter" {
  name = var.vsphere_datacenter
}

data "vsphere_network" "network" {
  name          = var.vsphere_network
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

data "vsphere_compute_cluster" "cluster" {
  name          = var.vsphere_cluster
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

data "vsphere_resource_pool" "pool" {
  name          = format("%s%s", data.vsphere_compute_cluster.cluster.name, "/Resources")
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

data "vsphere_datastore" "datastore" {
  name          = var.vsphere_datastore
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

data "vsphere_virtual_machine" "template" {
  name          = var.vsphere_template
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

resource "vsphere_virtual_machine" "vm" {
  name                    = var.vm_name
  folder                  = var.vsphere_folder
  num_cpus                = var.vm_cpus
  memory                  = var.vm_memory
  firmware                = var.vm_firmware
  efi_secure_boot_enabled = var.vm_efi_secure_boot_enabled
  guest_id                = data.vsphere_virtual_machine.template.guest_id
  datastore_id            = data.vsphere_datastore.datastore.id
  resource_pool_id        = data.vsphere_resource_pool.pool.id
  network_interface {
    network_id = data.vsphere_network.network.id
  }
  disk {
    label            = "disk0"
    size             = data.vsphere_virtual_machine.template.disks.0.size
    eagerly_scrub    = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
    thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
  }
  clone {
    template_uuid = data.vsphere_virtual_machine.template.id
    customize {
      linux_options {
        host_name   = var.vm_hostname
        domain      = var.vm_domain
        script_text = var.vm_script_text
      }
      network_interface {
        ipv4_address = var.vm_ipv4_address
        ipv4_netmask = var.vm_ipv4_netmask
      }

      ipv4_gateway    = var.vm_ipv4_gateway
      dns_suffix_list = var.vm_dns_suffix_list
      dns_server_list = var.vm_dns_server_list
    }
  }
  lifecycle {
    ignore_changes = [
      clone[0].template_uuid,
    ]
  }
}

terraform.tfvars

Note the use of Heredoc style for string literal in script_text.

# Credentials

vsphere_server   = "M01-vc01.rainpole.io"
vsphere_username = "[email protected]"
vsphere_password = "VMware1!"
vsphere_insecure = true

# vSphere Settings

vsphere_datacenter = "m01-dc01"
vsphere_cluster    = "m01-cl01"
vsphere_datastore  = "local-ssd-01"
vsphere_folder     = "workloads"
vsphere_network    = "M - 172.16.11.0"
vsphere_template   = "linux-centos-stream-8-v22.03"

# Virtual Machines Settings

vm_name                    = "centos-test"
vm_cpus                    = 2
vm_memory                  = 4096
vm_firmware                = "efi"
vm_efi_secure_boot_enabled = true
vm_hostname                = "centos-test"
vm_domain                  = "rainpole.io"
vm_script_text             = <<EOT
#!/bin/sh
if [ x$1=x"precustomization" ];
then
  mkdir -p /i-am/precustomization
fi
if [ x$1=x"postcustomization" ];
then
  mkdir -p /i-am/postcustomization
fi
EOT
vm_ipv4_address            = "172.16.11.111"
vm_ipv4_netmask            = "24"
vm_ipv4_gateway            = "172.16.11.1"
vm_dns_suffix_list         = ["rainpole.io"]
vm_dns_server_list         = ["172.16.11.11", "172.16.11.12"]

Plan:

terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # vsphere_virtual_machine.vm will be created
  + resource "vsphere_virtual_machine" "vm" {
      + annotation                              = (known after apply)
      + boot_retry_delay                        = 10000
      + change_version                          = (known after apply)
      + cpu_limit                               = -1
      + cpu_share_count                         = (known after apply)
      + cpu_share_level                         = "normal"
      + datastore_id                            = "datastore-11"
      + default_ip_address                      = (known after apply)
      + efi_secure_boot_enabled                 = true
      + ept_rvi_mode                            = "automatic"
      + firmware                                = "efi"
      + folder                                  = "workloads"
      + force_power_off                         = true
      + guest_id                                = "centos8_64Guest"
      + guest_ip_addresses                      = (known after apply)
      + hardware_version                        = (known after apply)
      + host_system_id                          = (known after apply)
      + hv_mode                                 = "hvAuto"
      + id                                      = (known after apply)
      + ide_controller_count                    = 2
      + imported                                = (known after apply)
      + latency_sensitivity                     = "normal"
      + memory                                  = 4096
      + memory_limit                            = -1
      + memory_share_count                      = (known after apply)
      + memory_share_level                      = "normal"
      + migrate_wait_timeout                    = 30
      + moid                                    = (known after apply)
      + name                                    = "centos-test"
      + num_cores_per_socket                    = 1
      + num_cpus                                = 2
      + power_state                             = (known after apply)
      + poweron_timeout                         = 300
      + reboot_required                         = (known after apply)
      + resource_pool_id                        = "resgroup-6046"
      + run_tools_scripts_after_power_on        = true
      + run_tools_scripts_after_resume          = true
      + run_tools_scripts_before_guest_shutdown = true
      + run_tools_scripts_before_guest_standby  = true
      + sata_controller_count                   = 0
      + scsi_bus_sharing                        = "noSharing"
      + scsi_controller_count                   = 1
      + scsi_type                               = "pvscsi"
      + shutdown_wait_timeout                   = 3
      + storage_policy_id                       = (known after apply)
      + swap_placement_policy                   = "inherit"
      + tools_upgrade_policy                    = "manual"
      + uuid                                    = (known after apply)
      + vapp_transport                          = (known after apply)
      + vmware_tools_status                     = (known after apply)
      + vmx_path                                = (known after apply)
      + wait_for_guest_ip_timeout               = 0
      + wait_for_guest_net_routable             = true
      + wait_for_guest_net_timeout              = 5

      + clone {
          + template_uuid = "42023ec5-63c7-8821-2ec9-a07c734718ba"
          + timeout       = 30

          + customize {
              + dns_server_list = [
                  + "172.16.11.11",
                  + "172.16.11.12",
                ]
              + dns_suffix_list = [
                  + "rainpole.io",
                ]
              + ipv4_gateway    = "172.16.11.1"
              + timeout         = 10

              + linux_options {
                  + domain       = "rainpole.io"
                  + host_name    = "centos-test"
                  + hw_clock_utc = true
                  + script_text  = <<-EOT
                        #!/bin/sh
                        if [ x$1=x"precustomization" ];
                        then
                          mkdir -p /i-am/precustomization
                        fi
                        if [ x$1=x"postcustomization" ];
                        then
                          mkdir -p /i-am/postcustomization
                        fi
                    EOT
                }

              + network_interface {
                  + ipv4_address = "172.16.11.111"
                  + ipv4_netmask = 24
                }
            }
        }

      + disk {
          + attach            = false
          + controller_type   = "scsi"
          + datastore_id      = "<computed>"
          + device_address    = (known after apply)
          + disk_mode         = "persistent"
          + disk_sharing      = "sharingNone"
          + eagerly_scrub     = false
          + io_limit          = -1
          + io_reservation    = 0
          + io_share_count    = 0
          + io_share_level    = "normal"
          + keep_on_remove    = false
          + key               = 0
          + label             = "disk0"
          + path              = (known after apply)
          + size              = 40
          + storage_policy_id = (known after apply)
          + thin_provisioned  = false
          + unit_number       = 0
          + uuid              = (known after apply)
          + write_through     = false
        }

      + network_interface {
          + adapter_type          = "vmxnet3"
          + bandwidth_limit       = -1
          + bandwidth_reservation = 0
          + bandwidth_share_count = (known after apply)
          + bandwidth_share_level = "normal"
          + device_address        = (known after apply)
          + key                   = (known after apply)
          + mac_address           = (known after apply)
          + network_id            = "network-1001"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.

Apply:

terraform apply -auto-approve

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # vsphere_virtual_machine.vm will be created
  + resource "vsphere_virtual_machine" "vm" {
      + annotation                              = (known after apply)
      + boot_retry_delay                        = 10000
      + change_version                          = (known after apply)
      + cpu_limit                               = -1
      + cpu_share_count                         = (known after apply)
      + cpu_share_level                         = "normal"
      + datastore_id                            = "datastore-11"
      + default_ip_address                      = (known after apply)
      + efi_secure_boot_enabled                 = true
      + ept_rvi_mode                            = "automatic"
      + firmware                                = "efi"
      + folder                                  = "workloads"
      + force_power_off                         = true
      + guest_id                                = "centos8_64Guest"
      + guest_ip_addresses                      = (known after apply)
      + hardware_version                        = (known after apply)
      + host_system_id                          = (known after apply)
      + hv_mode                                 = "hvAuto"
      + id                                      = (known after apply)
      + ide_controller_count                    = 2
      + imported                                = (known after apply)
      + latency_sensitivity                     = "normal"
      + memory                                  = 4096
      + memory_limit                            = -1
      + memory_share_count                      = (known after apply)
      + memory_share_level                      = "normal"
      + migrate_wait_timeout                    = 30
      + moid                                    = (known after apply)
      + name                                    = "centos-test"
      + num_cores_per_socket                    = 1
      + num_cpus                                = 2
      + power_state                             = (known after apply)
      + poweron_timeout                         = 300
      + reboot_required                         = (known after apply)
      + resource_pool_id                        = "resgroup-6046"
      + run_tools_scripts_after_power_on        = true
      + run_tools_scripts_after_resume          = true
      + run_tools_scripts_before_guest_shutdown = true
      + run_tools_scripts_before_guest_standby  = true
      + sata_controller_count                   = 0
      + scsi_bus_sharing                        = "noSharing"
      + scsi_controller_count                   = 1
      + scsi_type                               = "pvscsi"
      + shutdown_wait_timeout                   = 3
      + storage_policy_id                       = (known after apply)
      + swap_placement_policy                   = "inherit"
      + tools_upgrade_policy                    = "manual"
      + uuid                                    = (known after apply)
      + vapp_transport                          = (known after apply)
      + vmware_tools_status                     = (known after apply)
      + vmx_path                                = (known after apply)
      + wait_for_guest_ip_timeout               = 0
      + wait_for_guest_net_routable             = true
      + wait_for_guest_net_timeout              = 5

      + clone {
          + template_uuid = "42023ec5-63c7-8821-2ec9-a07c734718ba"
          + timeout       = 30

          + customize {
              + dns_server_list = [
                  + "172.16.11.11",
                  + "172.16.11.12",
                ]
              + dns_suffix_list = [
                  + "rainpole.io",
                ]
              + ipv4_gateway    = "172.16.11.1"
              + timeout         = 10

              + linux_options {
                  + domain       = "rainpole.io"
                  + host_name    = "centos-test"
                  + hw_clock_utc = true
                  + script_text  = <<-EOT
                        #!/bin/sh
                        if [ x$1=x"precustomization" ];
                        then
                          mkdir -p /i-am/precustomization
                        fi
                        if [ x$1=x"postcustomization" ];
                        then
                          mkdir -p /i-am/postcustomization
                        fi
                    EOT
                }

              + network_interface {
                  + ipv4_address = "172.16.11.111"
                  + ipv4_netmask = 24
                }
            }
        }

      + disk {
          + attach            = false
          + controller_type   = "scsi"
          + datastore_id      = "<computed>"
          + device_address    = (known after apply)
          + disk_mode         = "persistent"
          + disk_sharing      = "sharingNone"
          + eagerly_scrub     = false
          + io_limit          = -1
          + io_reservation    = 0
          + io_share_count    = 0
          + io_share_level    = "normal"
          + keep_on_remove    = false
          + key               = 0
          + label             = "disk0"
          + path              = (known after apply)
          + size              = 40
          + storage_policy_id = (known after apply)
          + thin_provisioned  = false
          + unit_number       = 0
          + uuid              = (known after apply)
          + write_through     = false
        }

      + network_interface {
          + adapter_type          = "vmxnet3"
          + bandwidth_limit       = -1
          + bandwidth_reservation = 0
          + bandwidth_share_count = (known after apply)
          + bandwidth_share_level = "normal"
          + device_address        = (known after apply)
          + key                   = (known after apply)
          + mac_address           = (known after apply)
          + network_id            = "network-1001"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.
vsphere_virtual_machine.vm: Creating...
vsphere_virtual_machine.vm: Still creating... [10s elapsed]
vsphere_virtual_machine.vm: Still creating... [20s elapsed]
vsphere_virtual_machine.vm: Still creating... [30s elapsed]
vsphere_virtual_machine.vm: Still creating... [40s elapsed]
vsphere_virtual_machine.vm: Still creating... [50s elapsed]
vsphere_virtual_machine.vm: Still creating... [1m0s elapsed]
vsphere_virtual_machine.vm: Still creating... [1m10s elapsed]
vsphere_virtual_machine.vm: Creation complete after 1m20s [id=42023c31-6a0a-6054-941a-cd923ddff811]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Results in Guest OS:

image

Release Note

resource/virtual_machine: Added support for guest customization script for Linux guest operating systems. (GH-1621)

References

Closes #1557 (A script can be used to change the root password.)

Adds support for s customization script to be run on a Linux guest operating system during guest customization. See VMware KB 74880 for VMware Tools prerequisites. #1557

Signed-off-by: Ryan Johnson <[email protected]>
@tenthirtyam tenthirtyam added enhancement Type: Enhancement needs-review Status: Pull Request Needs Review area/guest Area: Guest Operating System labels Mar 10, 2022
@tenthirtyam tenthirtyam added this to the v2.2.0 milestone Mar 10, 2022
@github-actions github-actions bot added documentation Type: Documentation provider Type: Provider size/xs Relative Sizing: Extra-Small labels Mar 10, 2022
@tenthirtyam tenthirtyam self-assigned this Mar 10, 2022
@hashicorp-cla
Copy link

hashicorp-cla commented Mar 12, 2022

CLA assistant check
All committers have signed the CLA.

Sets `sensitive: true` for the new `script_text` option in `linux_options`.
@tenthirtyam tenthirtyam requested a review from appilon April 6, 2022 16:45
@appilon appilon merged commit d802053 into main Apr 6, 2022
@appilon appilon deleted the feat/linux-options-script branch April 6, 2022 17:46
@github-actions
Copy link

github-actions bot commented May 7, 2022

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 7, 2022
@tenthirtyam tenthirtyam removed the needs-review Status: Pull Request Needs Review label Jun 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area/guest Area: Guest Operating System documentation Type: Documentation enhancement Type: Enhancement provider Type: Provider size/xs Relative Sizing: Extra-Small
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for setting root password in Linux customization
3 participants