Citrix XenApp/Desktop LTSR 7.15 Azure catalog creation issues

I came across this problem whilst trying to build a lab scenario with an older version of LTSR 7.15 and wasn’t able to find any similar issues documented elsewhere. Essentially Citrix Studio would not allow me to browse for .vhd files when creating a new catalog from an unmanaged disk located in an Azure storage account.

Here’s the troubleshooting process and solution at the end (spoiler – it’s TLS 1.1, 1.2!)

Trying to create a catalog following successful creation of a hosting connection:

Machine creation wizard error

You might find for instance when examining other storage accounts that you are even able to view the name of any named containers e.g. ‘logs’ located within the storage account object, but no obvious difference is possible.

You might try even using PowerShell to examine the hypervisor connection, and by following along will eventually reach a dead end in the communication with Azure:

Add-PSsnapin Ci*
cd XDHyp:\
cd HostingUnits

Determine the name of your hosting connection, and change directory into it

cd .\YourHostingUnitName\

Determine the name of your resource, and change directory into it

cd .\image.folder\

Determine the name of your Azure resource group, and change directory into it

cd .\YourResourceGroupName.resourcegroup\

Determine the name of your storage account, and change directory into it

cd .\YourStorageAccountName.storageaccount\

At this point if you attempt to use dir or get-childitem you will receive an error saying:

An exception occurred. The associated message was Error: Could not receive inventory contents from path

In summary you don’t receive very much information from Citrix Studio which might provide further assistance at troubleshooting the issue. Citrix Host Service will generate an Event ID 1007 message including the text:

Citrix.MachineCreationAPI.MachineCreationException: Error: Could not retrieve inventory contents from path /UK South.region/image.folder/YourResourceGroup.resourcegroup/YourStorageAccount.storageaccount ---> Microsoft.WindowsAzure.Storage.StorageException: The remote server returned an error: (400) Bad Request. ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.
   at System.Net.HttpWebRequest.GetResponse()

The solution took quite some comparison between different working environments until I happened on the cause and eventual solution. That is, that the storage accounts affected were configured by default to use TLS 1.2 as a minimum rather than TLS 1.0. Clearly this isn’t ideal but even relatively recent LTSR 7.15 CU5 (and presumably earlier) does not seem to support TLS 1.2 for this type of API communication with Azure.

Simply locate the storage account and modify the following switch under the Configuration page:

Finally (after waiting 30 seconds or so for the storage account change to take affect you’ll be able to open the storage account and view the unmanaged disk VHD blob.

Correctly working master image wizard selection

Switching to TLS 1.1 support does not improve the situation, it will begin failing again – even though the browser in Windows Server 2016 (with recent updates) supports TLS 1.1 and 1.2. So it appears that the code somewhere is out of date in LTSR 7.15 (either Citrix Studio or PowerShell perhaps).

I’ll update this post if I manage to resolve it using another method, but in my experience after testing this problem goes away with LTSR 1912.

Using MSDeploy to migrate between IIS6 and IIS7/8.5

A recent server replacement task I worked on recently involved migrating content between an IIS6 instance running on Windows Server 2003 R2 and IIS8.5 on Windows Server 2012 R2.

One of the sticking points that arose was that the source and destination switches included the potential options of -source: and -dest: with the webserver60 or webserver switches, according to whether IIS6 or above was being targeted respectively.

However when attempting a cross-version migration it is not possible to sync the content directly when using mismatched webserver and webserver60 switches. Instead, it’s more appropriate to target the IIS metabase index for the web site using –source:metakey=lm/w3svc/1

Here’s a step by step example of the choices which you would use:

Obtain and install the MSDeploy tool on both source and destination servers, including the remote service.

To check the dependencies on the original IIS6 server
msdeploy -verb:getDependencies -source:webServer60

To check the installed modules on the target IIS8.5 server
msdeploy -verb:getDependencies -source:webServer

To check the dependencies on the original IIS6 metabase
msdeploy -verb:getDependencies -source:metakey=lm/w3svc/1

To check the installed modules on the target IIS8.5 metabase
msdeploy -verb:getDependencies -source:metakey=lm/w3svc/1

Once you have determined which options were previously installed on the source IIS instance and manually aligned the settings on the target server you can proceed with the initial synchronisation of the web server content. One way of doing this between servers connected by a slow connection is using a ZIP archive (termed package mode), which should ideally contain credentials encrypted using a password:

To export the files from the source IIS6 server metabase to an encrypted ZIP file, including Application Pools
msdeploy.exe -verb:Sync -source:metakey=lm/w3svc/1 -dest:package=C:\Output\MS_WebDeploy_WebDeploy\,encryptPassword=xxx -enableLink:AppPoolExtension

Copy the package file (.zip) to the target server in order to import it.

NB. The IncludeACLs=true option does not do anything when transferring data using the package option (ZIP archive), but doesn’t generate any error

I found that it was necessary to switch the .NET priority order of the migration tool in “C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe.config” in order to use the earlier .NET version when importing data on the target server.

To import to IIS metabase on target server using the encrypted package
msdeploy -verb:sync -source:package=c:\Output\MS_WebDeploy_WebDeploy\,encryptPassword=xxx -enableLink:AppPoolExtension -dest:metakey=lm/w3svc/1

Once you have completed the initial import of the source data on the target server it is often useful to resynchronise the data at a later point, e.g. after applying small changes at the source. This option can also be used directly without using the package based approach outlined previously if you are copying content between servers with a high-speed connection.

To import to IIS metabase on target server by pulling from the source machine, including ACLs

msdeploy -verb:sync -source:metakey=lm/w3svc/1,computername=servername,includeAcls=True -enableLink:AppPoolExtension -dest:metakey=lm/w3svc/1,includeAcls=True

These are fairly simple examples but they should be sufficient to migrate simple HTML or Classic ASP pages between the source and destination servers. You can find links to useful documentation below: