0

Here's the situation: We're using ansible to make a bunch of changes to newly deployed VMs in GCP. One of those changes is to update the hostname.

GCP has a requirement that the first character in a hostname must be a letter. So, lets say our hostnames in GCP are PC1000-blah-blah. With Ansible, I want to dynamically pull that hostname (PC1000-blah-blah) and change it do 1000-blah-blah, dropping the "PC".

Now, I can do this on a VM by VM basis with the ansible.windows.win_hostname plugin: https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_hostname_module.html

But I haven't been able to figure out how to run my playbook against a group of VMs, where it's smart enough to see the current hostname (with PC) and drop the PC on each.

Any help is appreciated!

  • Your strategy will fail. Even if Ansible changes the hostname to **1000-blah-blah**, you will break DNS, and cause DHCP errors. VM hostnames must conform to RFC 1035. This regex defines allowed hostnames: **[a-z]([-a-z0-9]*[a-z0-9])?**. – John Hanley Aug 18 '21 at 19:44

1 Answers1

0

You can use ansible-module-gce-facts to gather information about an instance. In Ansible playbook, on can use hosts: 127.0.0.1 and connection:local to run eg. gcloud in a local shell.

And setting the hostname can also be done with metadata. For Windows VM there are further possibilities to automate an instance (if setting the metadata hostname should not suffice):

windows-startup-script-url, windows-startup-script-cmd, windows-startup-script-bat, windows-startup-script-ps1, sysprep-specialize-script-url, sysprep-specialize-script-cmd, sysprep-specialize-script-bat, and sysprep-specialize-script-ps1.

Here's an example sysprep-specialize-script-ps1: instance_setup.ps1... in particular function Change-InstanceName should not only be in the sys-prep script, but should run as windows-startup-script-ps1, so that the installation will always reflect the current host-name from the metadata:

function Change-InstanceName {
  <#
    .SYNOPSIS
      Changes the machine name for GCE Instance
    .DESCRIPTION
      If metadata server is reachable get the instance name for the machine and
      rename.
  #>

  Write-Log 'Getting hostname from metadata server.'

  if ((Get-CimInstance Win32_BIOS).Manufacturer -cne 'Google') {
    if (-not (Test-Connection -Count 1 metadata.google.internal -ErrorAction SilentlyContinue)) {
      Write-Log 'Not running in a Google Compute Engine VM.' -error
      return
    }
  }

  $count = 1
  do {
    $hostname_parts = (Get-Metadata -property 'hostname') -split '\.'
    if ($hostname_parts.Length -le 1) {
      Write-Log "Waiting for metadata server, attempt $count."
      Start-Sleep -Seconds 1
    }
    if ($count++ -ge 60) {
      Write-Log 'There is likely a problem with the network.' -error
      return
    }
  }
  while ($hostname_parts.Length -le 1)

  $new_hostname = $hostname_parts[0]
  # Change computer name to match GCE hostname.
  # This will take effect after reboot.
  try {
    (Get-WmiObject Win32_ComputerSystem).Rename($new_hostname)
    Write-Log "Renamed from $global:hostname to $new_hostname."
    $global:hostname = $new_hostname
  }
  catch {
    Write-Log 'Unable to change hostname.'
    Write-LogError
  }
}

So you probably won't change the host-name with ansible ...but still can edit the meta-data, in order to change the hostname and to provide a windows sys-prep or startup script - and then let these instances apply the meta-data by themselves with eg. Powershell (then reboot to apply the new host-name).

One could just run (Get-WmiObject Win32_ComputerSystem).Rename($new_hostname) on each instance and/or remove the leading PC while doing so and then reboot - but it is nevertheless recommend, to let a script pick up and apply the meta-data (which is self-managed). Well, it might make sense to only reboot when the host-name actually has changed (the example above is rather a sys-prep script, which therefore assumes a reboot/shutdown after it ran).

This would at least give you the current hostname, according to meta-data (while set):

gcloud compute instances describe instance-1 --zone europe-west3-c --format="value(metadata.items.hostname)"
Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • Hi Martin, thanks for the detailed response. I attempted to rename using a .ps1 script on startup: `Rename-Computer -ComputerName $env:COMPUTERNAME -NewName ($env:COMPUTERNAME -replace "pc","") -LocalCredential local\admin` But the "Rename-Computer" command doesn't allow a password, so the script fails as unauthorized during startup. Maybe there's another way to so this at startup so it drops the 'PC'? – Nathan Bergsma Aug 19 '21 at 04:47