Reduce Your Virtual Machine Build Time Using Hashicorp Packer: [Part 4 - Windows Server 2022 - HCL Template]

automation packer Jan 06, 2024
hashicorp packer part 4

Introduction:


You know how annoying it is to install an OS manually.  Having to click through the initial setup, remember which drivers to install, and then apply your basic configuration to every new machine is cumbersome.  

Fortunately, both Windows and Linux operating systems support automated installations.  With Windows, you can use an autounattend.xml file, sometimes referred to as an answer file, to provide answers to those initial prompts and apply an initial configuration.  For Linux, you can use a Kickstart file to automate the installation. The Automated Sandbox Framework takes advantage of these features. 

In this post, we'll add the autounattend.xml and PackerShutdown.bat files to the project.  These will aid in creating the golden image.  We'll end up with our source block defined in the Win2022.pkr.hcl HCL template.

Let's get started.

Step 1: Windows Server 2022 Answer File


You can find a copy of the autounattend.xml file I use here.   

  1. Download the autounattend.zip file and extract it.
  2. Move the autounattend.xml file to C:\AutomatedSandboxFramework\Win2022\scripts.
  3. Open it using VS Code and review what it does. 

I won't cover everything configured using this file, but you can open it using VS Code to review the settings.  WinRM is configured so that Packer can connect to the initial virtual machine.

Step 2: Create PackerShutdown.bat


Next, we need to create the PackerShutdown.bat file.  

  1. Open the VS Code and the AutomatedSandboxFramework folder.
  2. Expand Win2022 and scripts.  
  3. Under scripts, create a new file named PackerShutdown.bat.  Copy the following statements into this file and save it.  I'll explain what these do next.  

:: Block WinRM on first boot

netsh advfirewall firewall set rule name="Windows Remote Management (HTTPS-In)" new action=block
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new action=block

:: Sysprep and shutdown
C:/windows/system32/sysprep/sysprep.exe /generalize /oobe /unattend:C:/Windows/Panther/autounattend.xml /quiet /shutdown

 

The first two lines will create firewall rules to block WinRM, over HTTP and HTTPS, upon first boot.  I use Vagrant to manage my environment and if Vagrant connects to the virtual machine prior to it being fully ready, I'll get errors.  If you'd like to read more, check out this post over at Matthew Hodgkins blog.

Next, we sysprep the image and shutdown.

Step 3: Build the source block


You're now ready to complete the source block in the Win2022.pkr.hcl template.

  1. Open Win2022.pkr.hcl in VS Code.  Your build source block should look like this (where we left it after part 3 in this series).
    1.  
  2. Between the {} brackets, add the following code.
    1. boot_command = ["<spacebar>"]
      boot_wait = "${var.boot_wait}"
      communicator = "winrm"
      disk_size = "${var.disk_size}"
      disk_type_id = "0"
      floppy_files = ["scripts/autounattend.xml","scripts/PackerShutdown.bat"]
      guest_os_type = "windows2019srvnext-64"
      headless = false
      iso_checksum = "${var.iso_checksum}"
      iso_url = "${var.iso_url}"
      shutdown_command = "A:/PackerShutdown.bat" #; shutdown /s /t 5 /f /d p:4:1 /c \"Packer Shutdown\""
      shutdown_timeout = "30m"
      skip_compaction = false
      vm_name = "${var.vm_name}"
      vmx_data = {
      firmware = "efi"
      memsize = "${var.memsize}"
      numvcpus = "${var.numvcpus}"
      "scsi0.virtualDev" = "lsisas1068"
      "virtualHW.version" = "21"
      }
      winrm_insecure = true
      winrm_password = "${var.winrm_password}"
      winrm_timeout = "4h"
      winrm_use_ssl = true
      winrm_username = "${var.winrm_username}"
  3. Save the file.

Let's break down what each line is doing here.

  • boot_command = ["<spacebar>"] - Packer sends this boot command when the initial virtual machine is starting.  In this case, when prompted to "Press any key to continue," instead of you having to hit a key, Packer simulates pressing the spacebar (pretty cool).  For more commands, check out the official documentation for Hashicorp Packer.
  • boot_wait = "${var.boot_wait}" - We've instructed Packer to use a variable for this value.  We'll define this variable in the variables.pkr.hcl file a bit later in this series.  This will be the time Packer waits after booting the initial virtual machine before typing the boot command.
  • communicator = "winrm" - Since we're building a Windows golden image, we'll instruct Packer to use WinRM to communicate with the initial virtual machine.  This will be SSH when building a Linux image.
  • disk_size = "${var.disk_size}" - This parameter specifies the size of the disk in the virtual machine. It uses a variable defined in the variables.pkr.hcl file. This variable will determine the allocated disk space for the virtual machine.

  •  disk_type_id = "0" - This setting defines the type of disk. In this case, it's set to "0," indicating this disk is growable and contained in a single file.

  •  floppy_files = ["scripts//autounattend.xml","scripts/PackerShutdown.bat"] - These files are included in the floppy disk image used during the installation. Packer will create a virtual floppy disk and copy the autounattend.xml and PackerShutdown.bat files to it.  The Windows installation will use the autounattend.xml file to answer any questions we'd otherwise be prompted for.

  •  guest_os_type = "windows2019srvnext-64" - This parameter specifies the type of guest operating system. Here, it's set for a 64-bit Windows Server 2022 OS (vnext being the next version after Windows Server 2019).

  •  headless = false - This setting determines whether the virtual machine will run in a headless mode. When set to "false", it means that the VM will have a graphical user interface.

  •  iso_checksum = "${var.iso_checksum}" - This parameter represents the checksum of the ISO file used for the installation. It utilizes a variable to ensure the integrity of the ISO file.

  •  iso_url = "${var.iso_url}" - This setting defines the URL or path to the ISO file used for the installation. It references a variable to locate the specific ISO file.

  •  shutdown_command = "A:/PackerShutdown.bat" - This command specifies the path to a script (PackerShutdown.bat) that will be executed to shut down the virtual machine.

  •  shutdown_timeout = "30m" - This parameter defines the maximum time Packer will wait for the machine to shut down gracefully before timing out (here, set to 30 minutes).

  •  skip_compaction = false - When set to 'false", this instructs Packer not to skip disk compaction, which usually optimizes disk space usage after provisioning.

  •  vm_name = "${var.vm_name}" - This parameter specifies the name of the virtual machine. It references a variable that contains the desired name for the VM.

  •  vmx_data - This section includes additional configuration settings for the VMX file (VMware configuration file). It specifies parameters like firmware, memory size, number of virtual CPUs, SCSI controller type, and virtual hardware version.

  •  winrm_insecure = true - This setting enables or disables insecure WinRM connections. When set to "true", it allows unencrypted WinRM connections.

  •  winrm_password, winrm_timeout, winrm_use_ssl, winrm_username: These parameters configure WinRM (Windows Remote Management) settings, specifying the password, timeout duration, SSL usage, and username for remote management on the Windows system. They use variables for secure and customizable configurations.

Conclusion:


We're not finished with the template yet, but we're getting close.  In Part 5, we'll create six scripts to configure the image.  These will include downloading and installing the latest updates. 

In Part 6, we'll complete the HCL template and create the Windows Server 2022 image.  In the meantime, review the autounattend.xml file and understand what it does. It's a good time to review the official documentation on Packer as well. 

Thanks for stopping by.