Windows Server 2019 and Azure Stack – My Curiosity Got To Me

I have been reading some post in various social tools about Window Server 2019 and when it will be available on Azure Stack.  I have the same questions as well and hoping that Windows Server 2019 will soon be available in the Azure Stack Marketplace.  However, I was curious to see if a custom image could be made and imported into Azure Stack.  Officially Windows Server 2019 isn’t on the support Operating System list for Azure Stack at this time.  You can find the list on Microsoft Docs website “Supported Guest Operating System for Azure Stack.” 

I wanted to try this for two reasons. The first, I am curious and wanted to see if it would work, the second, I have never created a custom image for Azure Stack so this would be my first. 

First we need to create our image that we will import.  A lot of the research I did led me to deploying an image on Hyper-V then running Sysprep to get the image ready, etc.  I decided to go with creating the VHD using the Convert-WindowsImage.ps1 PowerShell script that you can download from various locations.  I already had a copy from the files I downloaded from Matt McSpirit’s ASDK Configuration tool.  You can download the file from his github location here.  Just a note, this again is for my curiosity and creating the VHD using the convert-windowsimage.ps1 might not be supported in production environments.  

I downloaded everything into a single directory called ImageCreation.  My Convert-WindowsImage.ps1 file and the ISO I grabbed from my volume license site.  I renamed the ISO to help me manage my script to Server2019.iso.

The following is the script I used to create my VHD using the convert-windowsimage.ps1.

.\Convert-WindowsImage.ps1 `
-SourcePath "C:\Temp\ImageCreation\Server2019.ISO" `
-SizeBytes 40GB `
-Edition "Windows Server 2019 SERVERDATACENTER" `
-VHDPath "C:\Temp\ImageCreation\Server2019.vhd" `
-VHDFormat VHD `-VHDType Fixed `
-VHDPartitionStyle MBR `
-Feature "NetFx3" `
-Passthru -Verbose

Next we need to get the newly created VHD to our Azure Stack.  Again there are a lot of good examples on how to do this from various blogs.  First we will connect to our Azure Stack with PowerShell as an Operator.  If you are not familiar with these steps you can review them on the following Microsoft Documentation, “Connect to Azure Stack with PowerShell as an Operator.” 

We need to create the Resource Group, Storage Account, and the Container in order to have a place to upload our VHD and our Marketplace Package we will create later.

I borrowed most these scripts from Matt McSpirit’s ASDK Configuration tool.  Did some editing to fit my needs but why re-invite the wheel?  Here is a copy of the script I ran to create my resource groups, storage accounts, etc.

$azsLocation = "dfw"
$azsImagesRGName = "azurestack-images"
$azsImagesStorageAccountName = "azsimagesstor"
$azsImagesContainerName = "azsimagescontainer"
$csvImagePath = "C:\Temp\ImageCreation"

# Test/Create RG
if (-not (Get-AzureRmResourceGroup -Name $azsImagesRGName -Location $azsLocation -ErrorAction SilentlyContinue)) { New-AzureRmResourceGroup -Name $azsImagesRGName -Location $azsLocation -Force -Confirm:$false -ErrorAction Stop }
# Test/Create Storage
$azsStorageAccount = Get-AzureRmStorageAccount -Name $azsImagesStorageAccountName -ResourceGroupName $azsImagesRGName -ErrorAction SilentlyContinue
if (-not ($azsStorageAccount)) { $azsStorageAccount = New-AzureRmStorageAccount -Name $azsImagesStorageAccountName -Location $azsLocation -ResourceGroupName $azsImagesRGName -Type Standard_LRS -ErrorAction Stop }
Set-AzureRmCurrentStorageAccount -StorageAccountName $azsImagesStorageAccountName -ResourceGroupName $azsImagesRGName | Out-Null
# Test/Create Container
$azsContainer = Get-AzureStorageContainer -Name $azsImagesContainerName -ErrorAction SilentlyContinue
if (-not ($azsContainer)) { $azsContainer = New-AzureStorageContainer -Name $azsImagesContainerName -Permission Blob -Context $azsStorageAccount.Context -ErrorAction Stop }

We now have our storage account, container, and resource group created. I ran the next script just to check  if the VHD exist and also it creates a variable we will use when we go to upload the VHD.


# Verify VHD exsist.
$image = "Server2019"
$csvImagePath = "C:\Temp\ImageCreation"
$blobName = "$($image).vhd"

Write-Host "There is no suitable $blobName image within your Storage Account. We'll need to upload a new one."
$validDownloadPathVHD = [System.IO.File]::Exists("$csvImagePath\$blobName")
Write-Host "Checking for a local copy first..."
# If there's no local VHD, create one.
if ($validDownloadPathVHD -eq $true) {
Write-Host "Located suitable VHD in this folder. No need to download again..."
$serverVHD = Get-ChildItem -Path "$csvImagePath\$blobName"
Write-Host "VHD located at $serverVHD"
}

The next script I will run will upload the VHD to the storage account we created earlier.

# Upload to Storage Account
Write-Host "Beginning upload of VHD to Azure Stack Storage Account"
$imageURI = '{0}{1}/{2}' -f $azsStorageAccount.PrimaryEndpoints.Blob, $azsImagesContainerName, $serverVHD.Name
Add-AzureRmVhd -Destination $imageURI -ResourceGroupName $azsImagesRGName -LocalFilePath $serverVHD.FullName -OverWrite -Verbose -ErrorAction Stop

Now that the VHD has been successfully uploaded to our Storage Account we will need to import it to the Platform Image Repository (PIR).  Here is the script that I ran to accomplish this.

# Upload into the PIR

$sku = "2019-Datacenter"
$edition = 'Windows Server 2019 SERVERDATACENTER'
$vhdVersion = "1.0.0"
$publisher = "MicrosoftWindowsServer"
$offer = "WindowsServer"
$osVersion = "Windows"

# Add the Platform Image
Add-AzsPlatformImage -Publisher $publisher -Offer $offer -Sku $sku -Version $vhdVersion -OsType $osVersion -OsUri "$imageURI" -Force -Confirm: $false -Verbose -ErrorAction Stop

Now that the image has been uploaded into the PIR you should be able to deploy Azure Stack VM’s using ARM Templates and using Azure Stack Powershell.  However, it will not show up in the MarketPlace at this time.  So, now we move on the creating a MarketPlace package and publishing that item into our Azure Stack Marketplace.

I didn’t document these next steps as well as I should.  To be honest I have never published a custom image to Azure Stack or Azure until today.  So that being said I wasn’t aware of the complexity that it took to do these steps.  I wrote this blog as I went along doing this the first time.  There are a lot of good resources once again on how to do this.  I will list some of the ones I referred to as I went along.  Also, I once again used Matt McSpirit’s work that helped me get my package created.

I did follow the Microsoft Documentation but I also referred back to 

Deploy a custom item in the Market Place by Florent Appointaire. 

Create and publish a Marketplace item at Microsoft Docs

So at a high level I took the ARM Template from Matt’s ASDK Configurator located at Github.  You can find it  in the Deployment\Packages\WindowsServer directory.  All I did was change any reference to Windows Server 2016 to Windows Server 2019. Also, I made sure that within the createuidefinition.json file that it was pointing to the correct imageReference.  This is where we will use the previous uploaded VHD.

I ran the following command to create my package file.

.\AzureGalleryPackager.exe package -m "C:\Temp\ImageCreation\Azure Stack Marketplace Item Generator\Microsoft.WindowsServer2019Datacenter-ARM.1.0.0\manifest.j
son" -o "C:\Temp\ImageCreation\Azure Stack Marketplace Item Generator"

I then just uploaded the *.azpkg file to my existing storage account that I used to upload my VHD file.

The next step is to run the Add-AzsGalleryItem cmdlet to get it into the Marketplace.

Add-AzsGalleryItem -GalleryItemUri `
https://azsimagestor.blob.dfw.azurestack.nttdacloud.com/azsimagecontainer/Microsoft.WindowsServer2019Datacenter-ARM.1.0.0.azpkg –Verbose

Within a few minutes I now had a Windows Server 2019 Marketplace item.  Because I didn’t really customize the names and the links I wouldn’t have used this in a production stamp.  Just want to make sure you are all aware.  This was for my curiosity and shouldn’t be used in production.

Now, the question.  Will it work?  Did I actually do this correctly the first time?  Let us deploy a Windows Server 2019 VM on Azure Stack and see! 

After a few minutes I now have a fully functional Windows Server 2019 VM running on my Azure Stack.  Success and now one more thing that I was curious about could be marked off as done.

Now there is some cleanup that needs to be done.  I will remove the storage account I created as well as the resource group created as well.  

Final Thoughts

Wow!  This was a little more work than I had expected.  To be honest I thought it would be a few lines of PowerShell and possibly a few clicks here and there.  I do want to make sure that everyone reading this blog understands this isn’t supported at this time.  This was my curiosity getting the better of me.  I know that I need to do another blog on how to create a proper custom image for Azure Stack now.  Now off to play with Windows Server 2019 and test out some of the new functionality.  I might even create a Server Core version and upload it to my Azure Stack.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s