Automating Lab Builds with XenServer PowerShell – Part 3 Unlimited VM Creation

Part 1 – Understanding the Requirements
Part 2 – Creating a Custom ISO
>>Part 3 – Unlimited VM Creation
Part 4 – Roles, Features, and Other Components

Introduction

Once you have all the necessary files and have created a custom ISO to complete an unattended installation of Windows, the next step will be to automate the creation of VMs. Doing this manually can take some time via XenCenter, especially if you are creating a large number of VMs. With the VM Build portion of AXL, you can build all 10 VMs, all with the same configuration, from a single screen. You have options to make VMs either from system sysprepped templates, blank templates, or default templates.

NOTE: If you plan on creating VMs in a pool with more than one XenServer host, there are a few considerations before moving forward which includes the following:

  • Rename each host’s local storage repository to something more identifiable than the default name ‘Local Storage’
  • When connecting to the XenServer host to create the VMs, you will need to connect to the pool master

Creating VMs From Sysprepped Templates

Upon first launch of the VM creation form, you’ll notice everything is disabled except for a few areas. This is because a connection to a XenServer host is required for any of the information fields to be populated.

If the XenServer PowerShell module is not found in any subdirectories, you will get a prompt to input the location of the XenServer PowerShell Module, as seen in Figure 1. The PowerShell Module can also be downloaded from GitHub Here .

Figure 1 – Module Location

The process for creating a sysprepped machine using AXL is quite refined compared to the other processes, especially compared to using default templates. Starting at the top and working down, the Select Storage Location drop-down will be where you select what storage repository the VM(s) will get created on which can be either local or network storage.

This information is pulled directly from the host/pool and does not include ISO repositories. In the Input VM Names text box, you can input each VM you want to create and click Add. Multiple machines can be added by separating each name either by a comma or semi-colon, but choose only one or the other type of delimiter, not both.

Selecting the names and clicking Remove can also remove any names if you decide to do so.

Onto the most important part, the Select a Template option. By default, only non-default templates will be populated in the drop down. After selecting which template to use, that’s all that is needed to create VMs from sysprepped templates. After all the information is input, select the validate button to ensure that the configuration is correct and, if it is, click Create to start building the VMs.

There is one caveat to using a sysprepped template though, and it kind of defeats the whole purpose of AXL. That is, you still have to go through the initial configuration of every VM created, whereas with a custom ISO, you don’t have to.

Creating VMs from a Blank Template

You may be asking what I mean by a blank template, and that simply means a template that has no operating system installed. Only the virtual hardware is configured such as the disk, CPU, RAM, and network. The benefit of using a blank template is that it will save you a little bit of time when running through the configuration.

Figure 2 – Sysprepped Buildout Example

Making VMs from a blank template is very similar to that of making them from sysprepped templates. There is one exception though, you have to actually select the ISO repository where the ISO is located, and which ISO you want to be installed. For the ISO repository, you may notice it is disabled in Figure 2, that is because I only had one ISO repository created for my pool.

However, if you had multiples created, the drop down would be enabled, and you could then choose the appropriate repository. To select an ISO, you first need to specify that you would actually like to insert one by selecting the Insert ISO checkbox. You can then select which ISO you want to be inserted into the created VMs and click validate to check your configuration. So long as everything checks out, you can create the configured VMs.

Figure 3 – Blank Buildout Example

NOTE: You can create multiple types of VMs, for instance Windows 10 and Server 2016, but you will need to do create them separately. After you click create, you will receive a prompt asking if you would like to create more VMs; which is when you would click yes if you wanted to make VMs with different operating systems. Doing this will clear the form completely.

Creating VMs From Default Templates

Non-default templates are great, blank and sysprepped, but you also have the option to create VMs via default templates. There is a little more configuration involved with default templates because you have to specify how much RAM, CPU, and disk you want to provide it as well as what network it should be on.

After you have filled out all required information from the blank template example, the only thing needed is for the Default Templates checkbox to be checked. This will populate the drop down with all default templates and will provide some additional drop downs to configure the resources you will allocate to the VMs.

Each drop down will have information pulled from the host to accurately configure the VMs, so you cannot over commit resources that are not there. RAM and Disk Size will be throttled back depending on how many VMs you have listed in the list box above to create.

Say for instance you listed 5 VMs in the list box and you have 32 GB of RAM on your host, taking 2 GB out for the host, you would have a maximum of 6 GB for each VM.

Figure 4 – Default Buildout Example

How it All Works

Knowing how to use the form is important, but so is knowing what is actually happening in the background. The code snippet below is the function that actually creates the VMs. Depending on what was chosen in the form, VMs will be created from either a blank, sysprepped, or default template.

Because of limitations with cloning VMs via the XenServer PowerShell module, the function will determine if the template chosen is on the same SR where the VMs were specified to be created; this would only affect you if you are using pools.

In the event the VMs being created and the template are on a different SRs, a temporary template will be copied to the SR where the VMs are to be created, then they are cloned from there on forward, if creating more than one VM. The temporary template, if created, will get removed after all VMs have been created.

Function BuildVMs {
 
# Specify DropDown variables 
$VMNames = $NewVMHostnameListBox.Items
$SourceTemplateName = $DropDownTemplates.SelectedItem
$StorageRepositoryName = $DropDownStorage.SelectedItem
$SelectedNetwork = $DropDownNetwork.SelectedItem
 
    foreach($VMName in $VMNames){
 
    # Specify general properties 
    $GetSRProperties = Get-XenSR -Name $StorageRepositoryName
    $GetNetworkProperties = Get-XenNetwork $SelectedNetwork
    $TemplateSRLocation = (Get-XenVM -Name $SourceTemplateName | Select -ExpandProperty VBDs | Get-XenVBD | Select -ExpandProperty VDI | Get-XenVDI | Select -ExpandProperty SR | Get-XenSR).name_label
    $ObjSourceTemplate = Get-XenVM -Name $SourceTemplateName
 
        if($DefaultTemplateCheckbox.CheckState -eq "Checked") { 
 
        # Specify required VM properties
        $VMRAM = ($DropDownRAMAmmount.SelectedItem*1GB)
        $DiskSize = ($DropDownDiskSize.SelectedItem*1GB)
        $VMCPU = $DropDownCPUCount.SelectedItem
        
        # Create new VM from all specified properties
        New-XenVM -NameLabel $VMName -MemoryTarget $VMRAM -MemoryStaticMax $VMRAM -MemoryDynamicMax $VMRAM -MemoryDynamicMin $VMRAM -MemoryStaticMin $VMRAM -VCPUsMax $VMCPU -VCPUsAtStartup $VMCPU -HVMBootPolicy "BIOS order" -HVMBootParams @{ order = "dc" } -HVMShadowMultiplier 1 -UserVersion 1 -ActionsAfterReboot restart -ActionsAfterCrash restart -ReferenceLabel $ObjSourceTemplate.reference_label -HardwarePlatformVersion 2 -Platform @{ "cores-per-socket" = "$VMCPU"; hpet = "true"; pae = "true"; vga = "std"; nx = "true"; viridian_time_ref_count = "true"; apic = "true"; viridian_reference_tsc = "true"; viridian = "true"; acpi = "1" } -OtherConfig @{ base_template_name = $ObjSourceTemplate.reference_label }
        
        $GetVMProperties = Get-XenVM -Name $VMname
        
        WaitScript 1
 
        # Create a new Virtual Disk with the same name as the new VM
        New-XenVDI -NameLabel $VMName -VirtualSize $DiskSize -SR $GetSRProperties -Type user
 
        WaitScript 4
 
        # Specify VDI and Network locations
        $NewVDI = Get-XenVDI -Name $VMName
        $VIFDevice = (Get-XenVMProperty -VM $GetVMProperties -XenProperty AllowedVIFDevices)[0]
 
            if($GetVMProperties -and $NewVDI){
                
                # Create CD drive for the new VM
                New-XenVBD -VM $GetVMProperties -VDI $null -Type CD -mode RO -Userdevice 3 -Bootable $False -Unpluggable $True -Empty $True
                
                # Attach previously created hard drive into the new VM
                New-XenVBD -VM $GetVMProperties -VDI $NewVDI -Type Disk -mode RW -Userdevice 0 -Bootable $True -Unpluggable $True
 
                # Create network interface for the new VM
                New-XenVIF -VM $GetVMProperties -Network $GetNetworkProperties -Device $VIFDevice 
 
                # Mount previously created hard disk
                Get-XenVM -Name $VMName | Select -ExpandProperty VBDs | Get-XenVBD | where {$_.type -eq "Disk"} | Select -ExpandProperty VDI | Set-XenVDI -NameLabel $VMName  
 
            }
            
        }
 
        if($DefaultTemplateCheckbox.CheckState -eq "Unchecked") {
 
            if($TemplateSRLocation -match $GetSRProperties.name_label) {
 
            # Create a clone of the template
            Invoke-XenVM -NewName $VMName -VM $ObjSourceTemplate -XenAction Clone
 
            # Provision the copy into a VM
            Invoke-XenVM -XenAction Provision -Name $VMName
 
            WaitScript 1
 
            # Rename the attached disk to the name of the VM
            Get-XenVM -Name $VMName | Select -ExpandProperty VBDs | Get-XenVBD | where {$_.type -eq "Disk"} | Select -ExpandProperty VDI | Set-XenVDI -NameLabel $VMName
 
            }
 
            else {
            
            # Copy the chosen template to the SR where the VMs are being created
            Invoke-XenVM -NewName "$SourceTemplateName - TEMP" -VM $ObjSourceTemplate  -SR $GetSRProperties -XenAction Copy
 
            # Specify old and new template names
            $SourceTemplateName = "$SourceTemplateName - TEMP"
            $ObjSourceTemplate = Get-XenVM -Name $SourceTemplateName
            
            # Clone the template that was just coppied to create the first VM
            Invoke-XenVM -NewName $VMName -VM $ObjSourceTemplate -XenAction Clone
            
            # Provision the copy into a VM
            Invoke-XenVM -XenAction Provision -Name $VMName
 
            WaitScript 1
 
            # Rename the attached disk to the name of the VM
            Get-XenVM -Name $VMName | Select -ExpandProperty VBDs | Get-XenVBD | where {$_.type -eq "Disk"} | Select -ExpandProperty VDI | Set-XenVDI -NameLabel $VMName
 
            # Rename the temporary templates attached disk name
            $ObjSourceTemplate | Select -ExpandProperty VBDs | Get-XenVBD | where {$_.type -eq "Disk"} | Select -ExpandProperty VDI | Set-XenVDI -NameLabel $SourceTemplateName
 
            }
        
        }
 
        if($BlankTemplateCheckbox.CheckState -eq 'Checked' -and $DropDownISOs.SelectedItem) {
 
        $SelectedBootISO = $DropDownISOs.Text
        
        # Get the VM, select the CD drive for the VM and attach the ISO
        Get-XenVM -Name $VMName | Select -ExpandProperty VBDs | Get-XenVBD | where {$_.type -eq "CD"} | Invoke-XenVBD -XenAction Insert -VDI (Get-XenVDI -Name $SelectedBootISO).opaque_ref
 
        }
 
    # Start the created VM to begin installing the attached ISO
    $VM = Get-XenVM -Name $VMName
    Invoke-XenVM -VM $VM -XenAction Start -Async
 
    $Global:AllCreatedServers += $VMName
 
    }
 
    #If a temporary template was created, remove it and the associated disk
    if($SourceTemplateName -match "- TEMP") {
    
    WaitScript 1
    
    $ObjSourceTemplate | Select -ExpandProperty VBDs | Get-XenVBD | where {$_.type -eq "Disk"} | Select -ExpandProperty VDI | Remove-XenVDI
 
    WaitScript 1
 
    Remove-XenVM -Name $SourceTemplateName
 
    }
 
}

 

 

Figure 5 – VM Creation Process

Figure 5 shows a visual representation of the VM creation process after filling out the form and clicking create.

Conclusion

There is really no limit to creating VMs other than available hardware. With the VM build form, you can rapidly create unlimited number of VMs in just a few minutes. This pairs especially well, and was designed for, the custom ISO created in part 2.

Now that you know all the ways VMs can be created with templates, it’s just a matter of doing it. The blank templates provide the most flexibility as you can do less configuration than default templates while receiving the same results. The blank and default templates used in tandem with the custom ISO provide a seamless way to created VMs.

In Part 4 of this blog post I will be outlining “Roles, Features, and Other Components”.

And don’t forget to check out Part 2 where the ISO creation process will be discussed in further detail.

Zach Thurmond
IT Consultant
Critical Design Associates

LinkedIn Profile