terraform-provider-vcd icon indicating copy to clipboard operation
terraform-provider-vcd copied to clipboard

Guest customization load order is not configurable to postcustomization

Open georgesvachulay opened this issue 7 years ago • 3 comments

Hi there,

I want to run a guest customization script for a vcd_vm_app resource on launch. I wanted to make the script run post tools customization (e.g setting host name and IP address).

There seems to be support for this from VMware, although documentation is sparse on it: https://pubs.vmware.com/vcd-51/index.jsp#com.vmware.vcloud.users.doc_51/GUID-724EB7B5-5C97-4A2F-897F-B27F1D4226C7.html https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1026614

In a nutshell, there needs to be a wrapper around the script you are executing, defining which tasks are pre and post. I would want to execute my actions post (possible using this method).

However it seems, that the VCD provider picks up my actions by default as pre. This makes it impossible to use the network and the host name as they have not been set at that point yet. Here's some logs to show the behaviour:

DEBUG: Exit Code: 0
DEBUG: Command: 'hostname -f 2>/dev/null'
DEBUG: Result: localhost

DEBUG: Exit Code: 0
DEBUG: opening file /etc/sysconfig/network.
DEBUG: Match found   : Line = HOSTNAME=localhost.localdomain

DEBUG: Actual String : localhost.localdomain
INFO: OLD HOST NAME = localhost.localdomain
INFO: Handling pre-customization ...
INFO: RunCustomScript invoked in '/tmp/.vmware-imgcust-d52grc3/' for 'precustomization'
DEBUG: Command: '/bin/cat /tmp/.vmware-imgcust-d52grc3//script4204918823332955454.bat | /usr/bin/tr -d '^M' > /tmp/.vmware-imgcust-d52grc3//script4204918823332955454.bat.tmp'
DEBUG: Result:
DEBUG: Exit Code: 0
DEBUG: Command: '/bin/mv -f /tmp/.vmware-imgcust-d52grc3//script4204918823332955454.bat.tmp /tmp/.vmware-imgcust-d52grc3//script4204918823332955454.bat'
DEBUG: Result:
DEBUG: Exit Code: 0
DEBUG: Command: '/bin/chmod u+x /tmp/.vmware-imgcust-d52grc3//script4204918823332955454.bat'
DEBUG: Result:
DEBUG: Exit Code: 0
INFO: Executing pre-customization script...
INFO: precustomization
DEBUG: Command: '/bin/sh /tmp/.vmware-imgcust-d52grc3//script4204918823332955454.bat "precustomization"'

You can see in the above snippet, that it defaults to 'precustomization' even though that's not specified anywhere in my script.

The configuration is like this:

resource "vcd_vapp_vm" "repo" {
  depends_on    = ["vcd_vapp_vm.jump"]
  provider      = "vcd.xap"
  vapp_name     = "${vcd_vapp.xap_core.name}"
  name          = "repo01"
  catalog_name  = "${var.catalog_lin}"
  template_name = "${var.template_lin}"
  memory        = 4096
  cpus          = 4
  network_name  = "${vcd_network.mgmt_net.name}"
  ip            = "${cidrhost(var.mgmt_network_ip_pool, 22)}"
  initscript    = "service network restart; cp -r /tmp/vm* /root/"
}

I have tested the script and it works if executed locally on post as root. I've also seen from the VMware logs that it does attempt to do actions defined in it, it just can't succeed due to no network.

I'm aware of the connection + remote-exec method, however I want to use clean API calls for this provisioning and according to documentation and manual test with the UI, this should be possible.

Can you please advise on how the initscript interacts with the API and if it's possible to override the precustomization argument to postcustomization ?

Cheers

georgesvachulay avatar Aug 21 '17 11:08 georgesvachulay

Have you tried wrapping your script with the IF statements as suggested in second link you posted?

#!/bin/sh
if [ x$1 == x"precustomization" ]; then
echo Do Precustomization tasks
elif [ x$1 == x"postcustomization" ]; then
echo Do Postcustomization tasks
fi 

bobbydeveaux avatar Aug 23 '17 07:08 bobbydeveaux

Yep that works, but there's one additional thing that might be needed in documentation to make it work: when I tried with raw input for initscript, it was not resolving linebreaks correctly and ultimately the script didn't run on the machines. I recommend adding this to the docs about initscript:

data "template_file" "myinitscript" {
  template            = "${file("${path.cwd}/mymagicinitscript.tpl")}"
  vars {
    x           = "${var.from_varstf}"
    y           = "${var.from_varstf}"
  }
}

resource "vcd_vapp_vm" "myvm" {
  initscript    = "${data.template_file.myinitscript.rendered}"
}

add a .tpl file in the same folder as the .tf file with this resource with the contents of the shell script:

#!/bin/bash
if [ x$1 == x"precustomization" ]; then
  echo "Started doing pre-customization steps..."
  echo "Finished doing pre-customization steps."
elif [ x$1 == x"postcustomization" ]; then
  echo "Started doing post-customization steps..."
  echo "Finished doing post-customization steps."
fi

if you can avoid it, don't add empty newlines in this .tpl file as it tends to break the script interpolation. Hope this is useful!

If you succeeded, you can find your script on the created VM under /root/.customization/custom* (don't exactly remember the filename). I also recommend adding logging to your script as the tools logging for these scripts is pretty bad. If you store credentials in your file, make sure you rm the file in the end as it will stay on the disk if you don't!

georgesvachulay avatar Aug 24 '17 09:08 georgesvachulay

Awesome - thanks for that. Shall tag this issue as a documentation update. Cheers! :)

bobbydeveaux avatar Aug 24 '17 09:08 bobbydeveaux