Full disclosure: My problem may be based on a incomplete understanding of the Citrix PowerShell module for Xen Desktop.
I have the following script block. It's called in a loop, once for each VM in a list. I'm using PowerShell Jobs
because I want to keep the UI thread free to update the UI while the jobs run.
Code "A"
$j = Start-Job -Name $jobName -ScriptBlock {
param($url, $uuid, $cred, $snapshotName)
$ErrorActionPreference = "Stop"
try
{
$error.clear()
$xSS = $cred | Connect-XenServer -url $url -NoWarnCertificates -SetDefaultSession -PassThru;
$vm = (Get-XenVM -SessionOpaqueRef $xss.opaque_ref -uuid $uuid)
#Create snapshot
Invoke-XenVM -Async -SessionOpaqueRef $xss.opaque_ref -VM $vm -XenAction Snapshot -NewName $snapshotName
return "OK"
}
catch
{
return ("ERROR: "+$error)
}
} -ArgumentList $global:configFileVmMetaData.poolUrl, $xenVm.key, $global:cred, $snapshotName
Code "A" works ok, but it takes longer then necessary because I'm executing the Connect-XenServer
cmdlet each time I invoke the script block.
So, I tried calling Connect-XenServer
once outside the loop and passing in the session variable as shown below in Code "B". The result was the error Could not find open sessions to any XenServers
being thrown inside the script block. I'm assuming that the $xss session variable is getting whanged somehow when its passed into the script block.
Any ideas why $xss session variable is getting whanged?
Code "B"
$xSS = $cred | Connect-XenServer -url $global:configFileVmMetaData.poolUrl -NoWarnCertificates -SetDefaultSession -PassThru;
loop
{
$j = Start-Job -Name $jobName -ScriptBlock {
param($xss, $uuid, $snapshotName)
$ErrorActionPreference = "Stop"
try
{
$error.clear()
$vm = (Get-XenVM -SessionOpaqueRef $xss.opaque_ref -uuid $uuid)
#Create snapshot
Invoke-XenVM -Async -SessionOpaqueRef $xss.opaque_ref -VM $vm -XenAction Snapshot -NewName $snapshotName
return "OK"
}
catch
{
return ("ERROR: "+$error)
}
} -ArgumentList $xss, $xenVm.key, $snapshotName
}
Additional examples inspired by the
Robert Cotterman
answerIn all cases, I still get the
Could not find open sessions to any XenServers
errorFYI - Using PowerShell 5.1
Example using $using
. Variable contents are passed in and back out as expected
cls
$aLocal = "AAA"
$bLocal = "BBB"
$j = Start-Job -Name "TestJob" -ScriptBlock {
return ($using:aLocal + " *** " + $using:bLocal)
}
while ($true)
{
$g = get-job -name "TestJob"
write-host ("get-job " + $g.Name + " is " + $g.State)
if ($g.State -ne "Running")
{
break
}
start-sleep -Seconds 1
}
write-host ("receive-Job='" + (receive-Job -Name "TestJob") +"'")
$g = get-Job -Name "TestJob"
Write-Host ("get-Job "+$g.name + " " + $g.state + " " + $g.HasMoreData + " " + $g.id)
if($g)
{
Remove-Job -Name "TestJob"
}
Output
get-job TestJob is Running
get-job TestJob is Completed
receive-Job='AAA *** BBB'
get-Job TestJob Completed False 45
Remove-Job
Example using args. Variable contents are passed in and back out as expected
cls
$aLocal = "AAA"
$bLocal = "BBB"
$j = Start-Job -Name "TestJob" -ScriptBlock {
return ($args[0] + " *** " + $args[1])
} -ArgumentList ($aLocal, $bLocal)
while ($true)
{
$g = get-job -name "TestJob"
write-host ("get-job " + $g.Name + " is " + $g.State)
if ($g.State -ne "Running")
{
break
}
start-sleep -Seconds 1
}
write-host ("receive-Job='" + (receive-Job -Name "TestJob") +"'")
$g = get-Job -Name "TestJob"
Write-Host ("get-Job "+$g.name + " " + $g.state + " " + $g.HasMoreData + " " + $g.id)
if($g)
{
Remove-Job -Name "TestJob"
}
Output
get-job TestJob is Running
get-job TestJob is Completed
receive-Job='AAA *** BBB'
get-Job TestJob Completed False 49
Example using named args. Variable contents are passed in and back out as expected
cls
$aLocal = "AAA"
$bLocal = "BBB"
$j = Start-Job -Name "TestJob" -ScriptBlock {
param($a, $b)
return ($a + " *** " + $b)
} -ArgumentList ($aLocal, $bLocal)
while ($true)
{
$g = get-job -name "TestJob"
write-host ("get-job " + $g.Name + " is " + $g.State)
if ($g.State -ne "Running")
{
break
}
start-sleep -Seconds 1
}
write-host ("receive-Job='" + (receive-Job -Name "TestJob") +"'")
$g = get-Job -Name "TestJob"
Write-Host ("get-Job "+$g.name + " " + $g.state + " " + $g.HasMoreData + " " + $g.id)
if($g)
{
Remove-Job -Name "TestJob"
}
Output
get-job TestJob is Running
get-job TestJob is Completed
receive-Job='AAA *** BBB'
get-Job TestJob Completed False 55
I just don't think it works that way. The connection to the Xen server is created for your PowerShell session, with info about that connection collected in the $xss variable. Each job runs its own PowerShell session. So just passing $xss to the job isn't the same, it's just a description of the connection details.