Project automate CVAD - Part two

Project automate CVAD - Part two

In this part, I will delve into the automation of Citrix Provisioning Services (PVS). I will cover the prerequisites, necessary downloads, and configuration steps required to automate the installation and setup of PVS.

This is second part of “Project Automate CVAD”. And I would very much recommend to read Part one.
In this post, we take a look at the Citrix Provisioning Services part.

In case PVS is the only thing needed for automation, here’s a short list of prerequisites.

Prerequisites for all installations in this series

  • All scripts are written for Citrix CVAD LTSR 2402 and Microsoft Windows Server 2022.
  • The user used for script execution, needs temporary sysadmin on SQL server
  • The user used for script execution, needs local administrator on every server
  • All servers needs to have Windows Server 2022 installed, domain joined and updated with latest Windows Updates
  • Create a share to host all scriptfiles
  • Execution command: Powershell.exe -executionpolicy Bypass -File .\Component\xxx.ps1 -force
  • Restart all servers

Prerequisites for this post

├── PVS
│   ├── AddSecodaryPVS.ps1
│   ├── ConfigurePVS.ps1
│   ├── ConfigWizard_Primary.ans
│   ├── ConfigWizard_Secondary.ans
│   ├── InstallPrerequisites.ps1
│   └── InstallPVS.ps1
└── ConfigurationVariable.json

Editing ConfigurationVariable.json and ConfigWizard_xxx.ans answer files

As in the first part of this series, you will need to customize the ConfigurationVariable.json file to match your specific environment.
To configure PVS, answerfiles are needed. They need to be customized aswell.

Let’s take a closer look at ConfigurationVariable.json.

If PVS is the only component needed, then copy json code below, and create a ConfigurationVariable.json. Keep in mind, the linenumbers below, will be incorrect.

Lines 3 to 25 are static and do not need to be changed. Lines 3 to 13 are installer names, and lines 16 to 25 are the parameters. They can, of course, be changed if needed. Line 28 - 31 needs to changed, to fit your environment.
JSON interprets backslashes as escape characters. So for a UNC path to work, four backslashes are needed, with two backslashes to seperate each folder.
Line 60 - 64 pretty much speaks for it self, and needs to be changed.
Line 65 and 66 are being used in ConfigurePVS.ps1 line 47 and 52, and is a path and name specification, to create a .sql file. The path needs to be local, like C:\
Line 68 is a UNC to C$ on the SQL Server. This is used ConfigurePVS.ps1 line 52.
If changed from \\FQDNSQLServer.local\C$, edit line 53 in ConfigurePVS.ps1 ScriptBlock { sqlcmd -S -i ‘C:\DBScript.sql’ }, to the value.

sqlcmd does not work with UNC paths, which is why the .sql file needs to be copied to SQLServer.

Line 69 and 70 doesn’t need to be edited, if commands seen later in the post, is being used.
Line 73 is the Passphrase for PVS. Remember it’s in cleartext. Remove it from json afterwards.
Line 74 is the local path, where vDisks are being placed.

ConfigurationVariable.json

{
    "AppInstallers": {
        "packagenameRedist_x64": "VC_redist.x64",
        "packagenameRedist_x86": "VC_redist.x86",
        "packagenamemsOLEdbDriver": "msoledbsql",
        "packagenamemsEDGEwebvwr2": "MicrosoftEdgeWebView2RuntimeInstallerX64",
        "packagenameCDF_x64": "cdf_x64",
        "packagenameTelemetry": "TelemetryServiceInstaller_x64",
        "packagenameCitrixPoshSDK": "CitrixPoshSdk",
        "packagenamePVSConsole": "PVS_Console_x64",
        "packagenamePVSServer": "PVS_Server_x64",
        "packagenamePVSTargetDevice": "PVS_Device_x64"
    },
    "UnattendedArguments": {
        "unattendedargsEXE": "/s /v\"/qn\"" ,
        "unattendedargsmsOLEdbDriver": "/qb ADDLOCAL=ALL IACCEPTMSOLEDBSQLLICENSETERMS=YES",
        "unattendedargsmsEDGEwebvwr2": "/silent /install",
        "unattendedargsCDF_x64": "/qb",
        "unattendedargsTelemetry": "/qb",
        "unattendedargsCitrixPoshSDK": "/silent"
    },
    "Common": {
        "DomainName": "domain.local",
        "DomainDN": "DOMAIN",
        "InstallShare": "\\\\FQDN\\TO\\INSTALLSHARE",
        "DeliveryControllers": ["DDC#1","DDC#2"]
    },
    "PVS": {
        "PVSAdminGroup": "domain.local\\PVSAdminGroup",
        "PVSDBName": "PVSDBName",
        "PVSSiteName": "PVSSiteName",
        "PVSFarmName": "PVSFarmName",
        "PVSCollectionName": "PVSDeviceCollectionName",
        "DBScriptFilePath": "C:\\",
        "DBScriptFile": "DBScript.sql",
        "SQLServerName": "PVSServerName",
        "SQLDBScriptRemotePath": "\\\\FQDNSQLServer\\C$",
        "PVSConfigWizardPrimaryFile": "Z:\\PVS\\ConfigWizard_Primary.ans",
        "PVSConfigWizardSecondaryFile": "Z:\\PVS\\ConfigWizard_Secondary.ans",
        "PVSConfigWizardPath": "C:\\ProgramData\\Citrix\\Provisioning Services\\",
        "PVSConfigWizardLog": "$Env:SystemRoot\\Temp\\ConfigWizard.log",
        "PVSPassphrase": "PVSPassphrase",
        "vDisk": "Local_path_to_vDisks"
    }
}

The answer files are used to configure PVS and are being copied to each of the PVS Servers, path: C:\ProgramData\Citrix\Provisioning Services
If the files are not placed in this location, ConfigWizard.exe fails the configuration.
ConfigWizard_Primary and ConfigWizard_Secondary is close to being the same, except for line 13. I’ve tried changing value from “Store” to whatever, but everytime the configuration fails. So I kept the default name “Store” and everything works.
Lines that needs to be edited: 2, 11, 12, 14, 16, 20, 21, 23 and 25.
I’ve tried naming the values, so it pretty much speaks for itself.

ConfigWizard_Primary.ans

FarmConfiguration=2
DatabaseServer=servername.fqdn.local
DatabaseInstance=
MultiSubnetFailover=0
DatabaseAuthenticationMode=ActiveDirectoryIntegrated
DatabaseUsername=
DatabaseUsername2=
DatabaseAdminAuthenticationMode=ActiveDirectoryIntegrated
DatabaseAdminUsername=
DatabaseAdminUsername2=
FarmExisting=FarmNameFromJson
ExistingSite=SiteNameFromJson
Store=Store
DefaultPath=LocalPathToVdisk
JoinFarm=None
LicenseServer=licenserver.fqdn.local
LicenseServerPort=27000
LicenseTradeup=0
LicenseSKU=0
UserName=domainname.local\serviceaccountname
UserPass=EnterSamePasswordAsPassphraseFromJson
PasswordManagementInterval=7
StreamNetworkAdapterIP=IPAddressOfPVSServer
StreamNetworkAdapterIPv6=
ManagementNetworkAdapterIP=IPAddressOfPVSServer
IpcPortBase=6890
IpcPortCount=20
SoapPort=54321

ConfigWizard_Secondary.ans

FarmConfiguration=2
DatabaseServer=servername.fqdn.local
DatabaseInstance=
MultiSubnetFailover=0
DatabaseAuthenticationMode=ActiveDirectoryIntegrated
DatabaseUsername=
DatabaseUsername2=
DatabaseAdminAuthenticationMode=ActiveDirectoryIntegrated
DatabaseAdminUsername=
DatabaseAdminUsername2=
FarmExisting=FarmNameFromJson
ExistingSite=SiteNameFromJson
ExistingStore=Store
DefaultPath=LocalPathToVdisk
JoinFarm=None
LicenseServer=licenserver.fqdn.local
LicenseServerPort=27000
LicenseTradeup=0
LicenseSKU=0
UserName=domainname.local\serviceaccountname
UserPass=EnterSamePasswordAsPassphraseFromJson
PasswordManagementInterval=7
StreamNetworkAdapterIP=IPAddressOfPVSServer
StreamNetworkAdapterIPv6=
ManagementNetworkAdapterIP=IPAddressOfPVSServer
IpcPortBase=6890
IpcPortCount=20
SoapPort=54321

Component installations

After each successful installation, a Restart-Computer is forced.

PVS Prerequisites

Logon to both PVS servers
Start Powershell as an administrator and execute:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\PVS\InstallPrerequisites.ps1

PVS Installation

Logon to both PVS servers
Start Powershell as an administrator and execute:

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\PVS\InstallPVS.ps1

PVS Configuration

Logon to the primary PVS server
This creates the SQL script file, creates DB on SQL server and configures PVS site.

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\PVS\ConfigurePVS.ps1

Logon to the secondary PVS server
This will add a secondary PVS server to the site

net use Z: \\servername.domain.local\InstallScripts
Z:
Powershell.exe -executionpolicy Bypass -File .\PVS\AddSecondaryPVS.ps1