Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoke-LabCommand -PostInstallationActivity -AsJob not creating a background job #1303

Open
Trentent opened this issue Mar 24, 2022 · 2 comments
Assignees
Labels
Non Trivial Takes quite an amount of time to fix

Comments

@Trentent
Copy link
Contributor

Trentent commented Mar 24, 2022

I've created custom Citrix roles to be installed on a series of VM's. These need to be installed in a sequence which AutomatedLab seems to do via the order the custom roles are added to the LabMachineDefinition. But they have no other dependency so executing them in parallel across multiple machines would save lots of time.

In order to execute in parallel I'm using the following command:
$PostInstalljobs = Invoke-LabCommand -PostInstallationActivity -ActivityName 'Post-installation' -ComputerName $postInstallMachines -AsJob

This is not creating a job per-machine and executing in the background, it is executing sequentially starting for the first machine and first role, waiting for that first role execution to finish, then executing the next role.. Once all roles are complete for the first machine it moves onto the next machine.

Expected behavior

Each machine should have a job created to be executed in the background and the roles installed in order

Actual behavior

AsJob appears to be ignored and each machine is operated on one at a time.

VERBOSE: [10:56:06][Write-LogFunctionEntry] Invoke-LabCommand Entering...
(PostInstallationActivity=True,ActivityName=Post-installation,ComputerName=CTX01,AsJob=True,NoDisplay=True,PassThru=True,Verbose=True)
VERBOSE: [10:56:06][Invoke-LabCommand] Executing lab command activity 'Post-installation' on machines 'CTX01'
VERBOSE: [10:56:06][Write-LogFunctionEntry] Get-LabVM Entering... (IncludeLinux=True)
VERBOSE: [10:56:06][Write-LogFunctionEntry] Get-LabVM Entering... (ComputerName=CTX01)
VERBOSE: [10:56:06][Write-LogFunctionEntry] Get-LabVM Entering... (ComputerName=CTX01,IncludeLinux=True)
VERBOSE: [10:56:07][Write-LogFunctionExit] Get-LabVMStatus...leaving...(Time elapsed: 00:00:00:031)
VERBOSE: [10:56:07][Write-ScreenInfo] Performing pre/post-installation tasks defined for each machine
VERBOSE: [10:56:07][Write-ScreenInfo] 10:56:07|08:27:38|00:00:00.000|       - Performing pre/post-installation tasks defined for each machine
10:56:07|08:27:38|00:00:00.000|       - Performing pre/post-installation tasks defined for each machine
VERBOSE: [10:56:07][Write-ScreenInfo] Installing Custom Role 'CitrixLicensing' on machine 'CTX01'
VERBOSE: [10:56:07][Write-ScreenInfo] 10:56:07|08:27:38|00:00:00.000|         - Installing Custom Role 'CitrixLicensing' on machine 'CTX01'
10:56:07|08:27:38|00:00:00.000|         - Installing Custom Role 'CitrixLicensing' on machine 'CTX01'
10:56:07|08:27:38|00:00:00.000|           - Validating lab definition
10:56:10|08:27:41|00:00:03.406|             - Success
10:56:10|08:27:41|00:00:03.500|           - Lab 'TestEnv' hosted on 'HyperV' imported with 6 machines
VERBOSE: [10:56:10][Write-LogFunctionEntry] Get-LabVM Entering... (ComputerName=CTX01)
VERBOSE: [10:56:10][Write-ScreenInfo] Detected the following operating system for 'CTX01' : Windows Server 2022 Standard (Desktop Experience)
VERBOSE: [10:56:10][Write-ScreenInfo] 10:56:10|08:27:41|00:00:03.593|           - Detected the following operating system for 'CTX01' : Windows Server 2022 Standard
(Desktop Experience)
10:56:10|08:27:41|00:00:03.593|           - Detected the following operating system for 'CTX01' : Windows Server 2022 Standard (Desktop Experience)
VERBOSE: [10:56:10][Write-ScreenInfo] Found Citrix product: Citrix_Virtual_Apps_and_Desktops version: 7.2109
VERBOSE: [10:56:10][Write-ScreenInfo] 10:56:10|08:27:41|00:00:03.609|           - Found Citrix product: Citrix_Virtual_Apps_and_Desktops version: 7.2109
10:56:10|08:27:41|00:00:03.609|           - Found Citrix product: Citrix_Virtual_Apps_and_Desktops version: 7.2109
VERBOSE: [10:56:10][Write-ScreenInfo] Selected version of Citrix Licensing (7.2109) supports this operating system 2022
VERBOSE: [10:56:10][Write-ScreenInfo] 10:56:10|08:27:41|00:00:03.640|           - Selected version of Citrix Licensing (7.2109) supports this operating system 2022
10:56:10|08:27:41|00:00:03.640|           - Selected version of Citrix Licensing (7.2109) supports this operating system 2022
...

Steps to reproduce

Create custom roles that take a while (eg, HostStart.ps1 with a Start-Sleep 600)
Add Custom Role to multiple LabMachineDefinition
Create Machines in Lab:

Install-Lab -BaseImages -NetworkSwitches -VMs -Domains

Attempt to execute post installation activities manually:

$PostInstallActivityMachines = Get-LabMachineDefinition | Where {$_.PostInstallationactivity.count -ge 1}
$postInstallJobs = New-Object System.Collections.Generic.List[PsObject]
foreach ($PostInstallMachine in $PostInstallActivityMachines) {
    $PostInstalljob = Invoke-LabCommand -PostInstallationActivity -ActivityName 'Post-installation' -ComputerName $PostInstallMachine.Name -AsJob -PassThru -NoDisplay
    $postInstallJobs.Add($PostInstalljob)
}

Environment details

PowerShell Version

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.20348.558
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.20348.558
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

AutomatedLab components

Please paste the output of Get-Module AutomatedLab* -List | Select Name,Version in this output field

Get-Module AutomatedLab* -List | Select Name,Version

Name                      Version
----                      -------
AutomatedLab              5.41.0
AutomatedLab.Common       2.1.223
AutomatedLab.Recipe       5.41.0
AutomatedLab.Ships        5.41.0
AutomatedLabDefinition    5.41.0
AutomatedLabNotifications 5.41.0
AutomatedLabTest          5.41.0
AutomatedLabUnattended    5.41.0
AutomatedLabWorker        5.41.0
@nyanhp
Copy link
Member

nyanhp commented Apr 8, 2022

Hi @Trentent, we wait for custom roles, as they can consist of more than one script that is being executed. Normal PostInstall and PreInstall activities are jobs which can be returned using the PassThru parameter.

Changing will take time as it would require a lot more orchestration to work for all possible scenarios

@nyanhp nyanhp self-assigned this Apr 8, 2022
@nyanhp nyanhp added the Non Trivial Takes quite an amount of time to fix label Apr 8, 2022
@nyanhp nyanhp added this to the vNext - no date yet milestone Apr 8, 2022
@Trentent
Copy link
Contributor Author

I've written a little piece of code that can partially do this functionality (for the purposes I need, this works perfectly).

I'm using the install-lab command to create the resources I require, which will power on and configure the domain controller machine.

Machines with custom roles (aka, PostInstallationActivities) are not managed with the install-lab command when used with the install-lab command I have specified. With that, I can take control of the power on and install of post installation activities.

Install-Lab -BaseImages -NetworkSwitches -VMs -Domains -NoValidation -verbose

Write-ScreenInfo "Getting list of machines yet to be booted"
$machineStatus = Get-LabVMStatus
$vms = New-Object System.Collections.Generic.List[string]
foreach ($machineToStart in $machineStatus.Keys) {if (($machineStatus[$machineToStart]) -eq "Stopped") { $vms.add("$machineToStart")}} ## Get list of machines yet to be started
Write-ScreenInfo "Starting $($vms.count) virtual machine(s)"
Start-VM -Name $vms

Write-ScreenInfo "Waiting for AutomatedLab to be able to contact virtual machines..."
Wait-LabVM -ComputerName $vms ## wait for all machines to finish booting

Write-ScreenInfo "Starting Postinstallation installs"
$PostInstallActivityMachines = Get-LabMachineDefinition | Where {$_.PostInstallationactivity.count -ge 1}

$RunSpaceJobs = New-Object System.Collections.Generic.List[PsObject]
## Need to get a list of post-install tasks and create a runspace to start each process with a process wait so that an order of install can be completed.
foreach ($postInstallMachine in $PostInstallActivityMachines) {
    $postInstallJobs = New-Object System.Collections.Generic.List[PsObject]
    if (Get-Variable $postInstallMachine.Name -ErrorAction SilentlyContinue) { Remove-Variable $postInstallMachine.Name -ErrorAction SilentlyContinue }
    New-Variable -Name $postInstallMachine.Name -Value $(New-RunspacePool -ThrottleLimit 1000)
    foreach ($postInstallActivity in $postInstallMachine.PostInstallationActivity) {
        $Script = "$(($postInstallActivity).DependencyFolder.Value)\HostStart.ps1"
        $Parameters = ($postInstallActivity).SerializedProperties | ConvertFrom-PSFClixml
        Write-ScreenInfo "Start-Process -FilePath powershell.exe -ArgumentList `"-ExecutionPolicy Unrestricted -File $Script $(&{$args}@Parameters)`" -PassThru  -Wait"
        $postInstallJobs.Add("Start-Process -FilePath powershell.exe -ArgumentList `"-ExecutionPolicy Unrestricted -File $Script $(&{$args}@Parameters)`" -PassThru -Wait`n") ##new line backtick required or else the scriptblock will be interpreted as a single line.
        
        Start-Sleep -Seconds 2 #just to give powershell processes a second or two to start
        #$PostInstallJobs.add($postInstallJob)
    }
     Write-Output "Starting Runspace Job: $($postInstallMachine.Name)"
     Write-Host "ScriptBlock: `n Number of Lines: $($postInstallJobs.count)" -ForegroundColor Green
     Write-Host "$($postInstallJobs | Out-String)" -ForegroundColor Green
     $RunSpaceJobs.Add($(Start-RunSpaceJob -ScriptBlock ([scriptblock]::create($postInstallJobs)) -RunspacePool $((Get-Variable -Name $postInstallMachine.Name).Value )))
}

This code will power on all VM's after the domain is stood up. It will then wait for all machines to be online and available. Once that occurs, it will generate a "script" based on the post installation activities "HostStart.ps1" command and execute each in order, asynchronously, per-machine. This code does not take into account HostEnd or local execution of Post Installation Activities (at this time).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Non Trivial Takes quite an amount of time to fix
Projects
None yet
Development

No branches or pull requests

2 participants