Go to ...

RSS Feed

Hyper-V Online Gallery: Create a VHD repository


Windows 10 version 1709 holds a hidden gem for us virtualization freaks: Quick Create Online Gallery. By default, it gives Microsoft an opportunity to suggest its premade virtual machines to users. But the term “hidden gem” means that although the feature has been available for almost a year now in Windows Insider builds, its documentation remains nearly non-existent. Rafael Rivera‘s (@WithinRafael)  article at Thurrot.com dated July 1st 2017 is still the best documentation available anywhere.

After reading Rafael’s article, I was sold on this concept, as my tweet a week later shows:

In this post I show how to set up a Hyper-V Quick Create Online Gallery, to be used for your own virtualization needs or to deploy virtual machines to your users. Because Quick Create can only create Generation 2 virtual machines, the guest OS must be Windows 8.1 or later, Windows Server 2012R2 or later, or some supported Linux distribution (distro).

You can add any existing VHD to such a gallery (remove checkpoints first!) or create a new VM and add its VHD. Windows 10 and Hyper-V are pretty good at adapting to new hardware, but if your intention is to use the Online Gallery to deploy virtual machines to your users, I recommend the following: create a new Generation 2 VM with a dynamically expanding VHD, install Windows on it, restart into Audit Mode when the OOBE starts, customize it as you like, and then generalize it using Sysprep. When all that is done, copy the resulting VHD or VHDX file onto a network or cloud share and add it to the gallery.

Each VM / VHD included in the Online Gallery needs its own configuration file in JSON format (JavaScript Object Notation, extension .json). You can use this sample script and edit it to fit your needs:

{
    "images": [
        {
            "name": "Windows 10 Enterprise LTSB FIN",
            "version": "2016",
            "locale": "FIN",
            "publisher": "Win10.guru",
            "lastUpdated": "2017-12-26",
            "description": [
                "\n",
		"Following software has been pre-installed:\n",
		"- Office 2016 Pro Plus\n",
		"- Adobe Reader"
            ],
            "config": {
                "secureBoot": true
            },
            "requirements": {
                "diskSpace": 0
            },
            "disk": {
                "uri":"https://server/share/VHDX_file.vhdx",
                "hash":"sha256:1234567890",
                "size":FILE SIZE in BYTES,
                "archiveRelativePath": ""
            },
            "logo": {
                "uri":"https://server/share/LOGO.jpg",
                "hash":"sha256:FILE HASH",
                "size":FILE SIZE in BYTES,
                "archiveRelativePath": ""
            },
            "symbol": {
                "uri":"https://server/share/SYMBOL.jpg",
                "hash":"sha256:FILE HASH",
                "size":FILE SIZE in BYTES,
                "archiveRelativePath": "" 
	    },	
            "thumbnail": {
                "uri":"https://server/share/THUMBNAIL.jpg",
                "hash":"sha256:FILE HASH",
                "size":FILE SIZE in BYTES,
                "archiveRelativePath": "" 
            },
	    "details": [
            {
   	        "name": "Space required",
	        "value": "256 GB"
	    }
         ]
      }
   ]
}

You can also download Rafael’s sample script with explanatory remarks from GitHub.

OK, let’s break this script into parts, block by block.

1.) Images 

{
    "images": [
        {
            "name": "Windows 10 Enterprise LTSB EN-GB",
            "version": "2016",
            "locale": "EN-GB",
            "publisher": "Win10.guru",
            "lastUpdated": "2017-12-26",
            "description": [
                "\n",
		"Following software has been pre-installed:\n",
		"- Office 2016 Pro Plus\n",
		"- Adobe Reader"
            ],

At the beginning of this script we provide a name, version, locale, publisher, last updated and description fields. This is all just information shown to an end user: any of all of this text can be freely modified. I start this description with an empty line (“\n”,) to separate the first line (Following software…) from name and publisher.

2.) Config 

            "config": {
                "secureBoot": true
            },

Enables (true) or disables (false) Secure Boot on the VM that this script creates.

3.) Requirements

            "requirements": {
                "diskSpace": 0
            },

Specifies the minimum free space in bytes on the target partition where the VM will be installed. Here, it is set to 0 which means no minimum  space requirements are imposed. Please note: having now tested the Online Gallery feature quite extensively, I have never gotten this to work. However, I am sure this will be fixed at some point. For now, it’s best to leave this section untouched.

4.) Disk

            "disk": {
                "uri":"https://server/share/VHDX_file.vhdx",
                "hash":"sha256:1234567890",
                "size":FILE SIZE in BYTES,
                "archiveRelativePath": ""
            },

This section includes VHD file information. A URI could be a URL, such as a path to a server share or a File URI. Here are some examples for URI specifications:

VHD file stored on Azure Blob Storage:
https://STORAGE_ACCOUNT.blob.core.windows.net/RESOURCE_GROUP/FOLDER/FILENAME.vhdx

Local PC:
file://DRIVE:/FOLDER/FILENAME.vhdx

Notice that you should only use file URI if you are doing gallery only for yourself.

NAS or PC on local network:
http://192.168.2.106:8080/FOLDER/FILENAME.vhdx

Notice the port number in the URL shown: port 8080 should work if you have not changed other port assignments.

Use the Get-FileHash cmdlet in PowerShell to calculate the SHA256 hash for your file (required):
Get-FileHash -Path PATH\FILENAME -Algorithm SHA256

(Click screenshot to enlarge.)

Get the VHDX file size in bytes from its file properties.

I’ve had no success in using zipped VHDX files, but in theory you could use a ZIP archive of your VHDX in the URI field, then add a VHDX file’s relative path in archiveRelativePath. Let’s see if the “Virtualization Goddess” @VirtualScooley can come up with an answer:

5.) Logo

            "logo": {
                "uri":"https://server/share/LOGO.jpg",
                "hash":"sha256:FILE HASH",
                "size":FILE SIZE in BYTES,
                "archiveRelativePath": ""
            },

A logo is a 100×30 pixel image shown in Quick Create. Use PowerShell > Get-FileHash as in 4.) Disk above to get a hash value, get file size in bytes from its file properties window.

6.) Symbol

            "symbol": {
                "uri":"https://server/share/SYMBOL.jpg",
                "hash":"sha256:FILE HASH",
                "size":FILE SIZE in BYTES,
                "archiveRelativePath": ""
            },

Symbol is a 35×35 pixel logo image shown in Quick Create.

7.) Thumbnail

            "thumbnail": {
                "uri":"https://server/share/THUMBNAIL.jpg",
                "hash":"sha256:FILE HASH",
                "size":FILE SIZE in BYTES,
                "archiveRelativePath": ""
            },

A thumbnail is an image shown in Quick Create. A thumbnail image can be relatively big. I usually use a 16:9 screenshot from the desktop for the OS in question, then resize it to 800×450 pixels.

Notice that logo, symbol and thumbnail blocks are optional. If you want to use just a thumbnail, cut out the logo and symbol blocks.

8.) Details

	    "details": [
            {
   	        "name": "Space required",
	        "value": "256 GB"
	    }

Additional information shown to user. In this example I am telling that to set up VM user needs 256 GB free storage space (a dynamically expanding 127 GB VHDX, another 127 GB for it to expand to full size when used plus an additional 2 GB just to be sure).

Create an individual configuration JSON file for each VHD included in your gallery, In this example I wanted to create a gallery containing W10 Enterprise x64 LTSB 2016 virtual hard disk images in Finnish, Swedish, UK & US English.

To make Hyper-V to read my custom gallery instead of default one, I need to ad a Multi String Value (REG_MULTI_SZ) GalleryLocations in registry to key HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization. I prefer doing this on elevated Command Prompt with following command:

REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization" /v GalleryLocations /t REG_MULTI_SZ /d G:\Hyper-V_Scripts\LTSB_FIN.json\0G:\Hyper-V_Scripts\LTSB_SWE.json\0G:\Hyper-V_Scripts\LTSB_EN-GB.json\0G:\Hyper-V_Scripts\LTSB_EN-US.json /f

Notice that the preceding command occupies only one command line. The /v and /t switches provide the name and type of the new or modified value, the switch /d then lists all required JSON files separated by \0, and finally /f forces possibly extant older values to be overwritten without prompting the user to provide permission to proceed.

Of course you can do this in the Registry Editor as well, Creating Multi String Value GalleryLocations and adding JSON files:

(Click screenshot to enlarge.)

All done! When the registry has been updated, users will see this when selecting Quick Create in Hyper-V Manager:

1.) Details appear in block 1. Images
2.) Logo set in block 5. Logo
3.) Symbol set in block 6. Symbol
4.) Thumbnail set in block 7. Thumbnail
5.) Additional details told in block 8. Details 

That’s it!  A user can now select any of the gallery’s virtual hard disks and set up a new VM with a pre-installed OS.

Questions and comments welcome,

Kari

Author: Kari Finn

A Windows Insider MVP, Kari started in computing in the mid 80’s writing code for VAX / VMS systems. Since then, he’s worked in a variety of IT positions. He specializes in Windows image capture, customization, repair and deployment as well as Hyper-V virtualization. Kari is a proud Team Member at number #1 Windows site TenForums.com.

Leave a Reply