Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions Config.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ function Get-AvailableConfigOptions {
@{"Name" = "virtual_disk_format"; "DefaultValue" = "VHDX";
"Description" = "Select between VHD, VHDX, QCOW2, VMDK or RAW formats."},
@{"Name" = "image_type"; "DefaultValue" = "HYPER-V";
"Description" = "This parameter allows to choose between MAAS, KVM, VMware and Hyper-V specific images.
"Description" = "This parameter allows to choose between MAAS, KVM, Nutanix, VMware and Hyper-V specific images.
For HYPER-V, cloudbase-init will be installed and the generated image should be in vhd or vhdx format.
For MAAS, in addition to cloudbase-init, the curtin tools are installed
and the generated image should be in raw.tgz format.
For KVM, in addition to cloudbase-init, the VirtIO drivers are installed
and the generated image should be in qcow2 format."},
and the generated image should be in qcow2 format.
For Nutanix, in addition to cloudbase-init, the Nutanix VirtIO drivers
are installed and the generated image should be in qcow2 format."},
@{"Name" = "disk_layout"; "DefaultValue" = "BIOS";
"Description" = "This parameter can be set to either BIOS or UEFI."},
@{"Name" = "product_key";
Expand Down Expand Up @@ -108,10 +110,12 @@ function Get-AvailableConfigOptions {
@{"Name" = "shrink_image_to_minimum_size"; "DefaultValue" = $true; "AsBoolean" = $true
"Description" = "Whether to shrink the image partition and disk after the image generation is complete."},
@{"Name" = "virtio_iso_path"; "GroupName" = "drivers";
"Description" = "The path to the ISO file containing the VirtIO drivers."},
"Description" = "The path to the ISO file containing the VirtIO drivers.
For Nutanix images, virtio_iso_path must point to the Nutanix VirtIO drivers ISO."},
@{"Name" = "virtio_base_path"; "GroupName" = "drivers";
"Description" = "The location where the VirtIO drivers are found.
For example, the location of a mounted VirtIO ISO. VirtIO versions supported >=0.1.6.x"},
For example, the location of a mounted VirtIO ISO. VirtIO versions supported >=0.1.6.x
For Nutanix images, virtio_base_path must point to the Nutanix VirtIO drivers."},
@{"Name" = "install_qemu_ga"; "GroupName" = "custom";"DefaultValue" = "False";
"Description" = "Installs QEMU guest agent services from the Fedora VirtIO website.
Defaults to 'False' (no installation will be performed).
Expand Down
96 changes: 72 additions & 24 deletions WinImageBuilder.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,29 @@ $VirtIODriverMappings = @{
"2k25" = @(26100, $MAX_BUILD_NUMBER, $true);
}

# Nutanix VirtIO driver folders can be labeled with or without "(Legacy)" depending on version
$nutanixVirtioFolderMappings = @{
"2k8" = @("Windows Server 2008 (Legacy)", "Windows Server 2008");
"2k8r2" = @("Windows Server 2008 R2 (Legacy)", "Windows Server 2008 R2");
"w7" = @("Windows 7 (Legacy)", "Windows 7");
"2k12" = @("Windows Server 2012 (Legacy)", "Windows Server 2012");
"w8" = @("Windows 8 (Legacy)", "Windows 8");
"2k12r2" = @("Windows Server 2012 R2 (Legacy)", "Windows Server 2012 R2");
"w8.1" = @("Windows 8.1 (Legacy)", "Windows 8.1");
"2k16" = @("Windows Server 2016");
"w10" = @("Windows 10");
"w11" = @("Windows 11");
"2k19" = @("Windows Server 2019");
"2k22" = @("Windows Server 2022");
"2k25" = @("Windows Server 2025");
}

$nutanixVirtioArchMappings = @{
"amd64" = "x64"
"i386" = "x86"
"x86" = "x86"
}

$AvailableCompressionFormats = @("tar","gz","zip")

. "$scriptPath\Interop.ps1"
Expand Down Expand Up @@ -760,6 +783,8 @@ function Get-VirtIODrivers {
[parameter(Mandatory=$true)]
[bool]$IsServer,
[parameter(Mandatory=$true)]
[bool]$IsNutanixTarget,
[parameter(Mandatory=$true)]
[string]$BasePath,
[parameter(Mandatory=$true)]
[string]$Architecture,
Expand All @@ -768,31 +793,47 @@ function Get-VirtIODrivers {
)

Write-Log "Getting Virtual IO Drivers: $BasePath..."
$driverPaths = @()
foreach ($driver in $VirtioDrivers) {
foreach ($osVersion in $VirtIODriverMappings.Keys) {
$map = $VirtIODriverMappings[$osVersion]
$osVersion = $null
foreach ($entry in $VirtIODriverMappings.Keys) {
$map = $VirtIODriverMappings[$entry]
$minBuildNumber = $map[0]
$maxBuildNumber = $map[1]
$isServerVersion = $map[2]
if (!(($BuildNumber -ge $minBuildNumber -and $BuildNumber -le $maxBuildNumber) `
-and ($isServerVersion -eq $isServer))) {
continue
}
$driverPath = "{0}\{1}\{2}\{3}" -f @($basePath,
$driver,
$osVersion,
$architecture)
if (Test-Path $driverPath) {
$driverPaths += $driverPath
if (($BuildNumber -ge $minBuildNumber -and $BuildNumber -le $maxBuildNumber) `
-and ($isServerVersion -eq $isServer)) {
$osVersion = $entry
break
}
}

$driverPaths = @()
if ($osVersion) {
if (!$IsNutanixTarget){
foreach ($driver in $VirtioDrivers) {
$driverPath = "{0}\{1}\{2}\{3}" -f @($basePath,
$driver,
$osVersion,
$architecture)
if (Test-Path $driverPath) {
$driverPaths += $driverPath
}
}
} else {
foreach ($folder in $nutanixVirtioFolderMappings[$osVersion]) {
$driverPath = "{0}\{1}\{2}" -f @($basePath,
$folder,
$nutanixVirtioArchMappings[$Architecture])
if (Test-Path $driverPath) {
$driverPaths += $driverPath
break
}
}
}
}
if (!$driverPaths -and $RecursionDepth -lt 1) {
# Note(avladu): Fallback to 2012r2/w8.1 if no drivers are found
$driverPaths = Get-VirtIODrivers -BuildNumber 9600 -IsServer $IsServer `
-BasePath $BasePath -Architecture $Architecture -RecursionDepth 1
-IsNutanixTarget $IsNutanixTarget -BasePath $BasePath -Architecture $Architecture -RecursionDepth 1
}
Write-Log "Finished to get IO Drivers."
return $driverPaths
Expand All @@ -805,6 +846,8 @@ function Add-VirtIODrivers {
[parameter(Mandatory=$true)]
[object]$image,
[parameter(Mandatory=$true)]
[bool]$isNutanixTarget,
[parameter(Mandatory=$true)]
[string]$driversBasePath
)

Expand Down Expand Up @@ -832,8 +875,8 @@ function Add-VirtIODrivers {
# For VirtIO ISO with drivers version higher than 1.8.x
$buildNumber = [int]$image.ImageVersion.Build
$virtioDriversPaths = Get-VirtIODrivers -BuildNumber $buildNumber `
-IsServer ([bool](Is-ServerInstallationType $image)) -BasePath $driversBasePath `
-Architecture $image.ImageArchitecture
-IsServer ([bool](Is-ServerInstallationType $image)) -IsNutanixTarget $isNutanixTarget `
-BasePath $driversBasePath -Architecture $image.ImageArchitecture
foreach ($virtioDriversPath in $virtioDriversPaths) {
if (Test-Path $virtioDriversPath) {
Add-DriversToImage $vhdDriveLetter $virtioDriversPath
Expand All @@ -857,6 +900,9 @@ function Add-VirtIODriversFromISO {
.PARAMETER Image
The exact flavor of Windows installed on that image, so that the supported VirtIO drivers
can be installed.
.PARAMETER IsNutanixTarget
Indicates whether the image is being built for Nutanix. When true, Nutanix VirtIO ISO
folder mappings are used.
.PARAMETER ISOPath
The full path of the VirtIO ISO file containing the drivers.
#>
Expand All @@ -866,6 +912,8 @@ function Add-VirtIODriversFromISO {
[parameter(Mandatory=$true)]
[object]$image,
[parameter(Mandatory=$true)]
[bool]$isNutanixTarget,
[parameter(Mandatory=$true)]
[string]$isoPath
)
Write-Log "Adding Virtual IO Drivers from ISO: $isoPath..."
Expand Down Expand Up @@ -893,7 +941,7 @@ function Add-VirtIODriversFromISO {
$driversBasePath += ":"
Write-Log "Adding drivers from $driversBasePath"
Add-VirtIODrivers -vhdDriveLetter $vhdDriveLetter -image $image `
-driversBasePath $driversBasePath
-isNutanixTarget $isNutanixTarget -driversBasePath $driversBasePath
} else {
throw "The $isoPath is not a valid iso path."
}
Expand Down Expand Up @@ -1587,7 +1635,7 @@ function New-WindowsOnlineImage {
Remove-Item -Force $virtualDiskPath
}

if ($windowsImageConfig.image_type -eq "KVM") {
if ($windowsImageConfig.image_type -in @("KVM", "Nutanix")) {
$imagePath = $barePath + ".qcow2"
Write-Log "Converting VHD to Qcow2"
Convert-VirtualDisk -vhdPath $virtualDiskPath -outPath $imagePath -format "qcow2" `
Expand Down Expand Up @@ -1730,11 +1778,11 @@ function New-WindowsCloudImage {
}
if ($windowsImageConfig.virtio_iso_path) {
Add-VirtIODriversFromISO -vhdDriveLetter $winImagePath -image $image `
-isoPath $windowsImageConfig.virtio_iso_path
-isNutanixTarget $($windowsImageConfig.image_type -eq "Nutanix") -isoPath $windowsImageConfig.virtio_iso_path
}
if ($windowsImageConfig.virtio_base_path) {
Add-VirtIODrivers -vhdDriveLetter $winImagePath -image $image `
-driversBasePath $windowsImageConfig.virtio_base_path
-isNutanixTarget $($windowsImageConfig.image_type -eq "Nutanix") -driversBasePath $windowsImageConfig.virtio_base_path
}
if ($windowsImageConfig.extra_features) {
Enable-FeaturesInImage $winImagePath $windowsImageConfig.extra_features.split(",")
Expand Down Expand Up @@ -1867,7 +1915,7 @@ function New-WindowsFromGoldenImage {
$imageInfo = Get-ImageInformation $driveLetterGold -ImageName $windowsImageConfig.image_name
if ($windowsImageConfig.virtio_iso_path) {
Add-VirtIODriversFromISO -vhdDriveLetter $driveLetterGold -image $imageInfo `
-isoPath $windowsImageConfig.virtio_iso_path
-isNutanixTarget $($windowsImageConfig.image_type -eq "Nutanix") -isoPath $windowsImageConfig.virtio_iso_path
}

if ($windowsImageConfig.drivers_path -and (Test-Path $windowsImageConfig.drivers_path)) {
Expand Down Expand Up @@ -1940,7 +1988,7 @@ function New-WindowsFromGoldenImage {
$imagePath = $imagePathRaw
}

if ($windowsImageConfig.image_type -eq "KVM") {
if ($windowsImageConfig.image_type -in @("KVM", "Nutanix")) {
$imagePathQcow2 = $barePath + ".qcow2"
Write-Log "Converting VHD to QCow2"
Convert-VirtualDisk -vhdPath $imagePath -outPath $imagePathQcow2 `
Expand Down Expand Up @@ -2047,7 +2095,7 @@ function Test-OfflineWindowsImage {
$diskFormat = 'vpc'
}
}
if ($windowsImageConfig.image_type -eq "KVM") {
if ($windowsImageConfig.image_type -in @("KVM", "Nutanix")) {
$fileExtension = 'qcow2'
$diskFormat = 'qcow2'
}
Expand Down