The script below is meant to clone VM templates to Resource Pools which -match parameter $environmentID.
However I get the error below. If i don't use parameter $environmentID the script works and clones to all Resource Pools within a Folder which I do not want.
Any help would be much appreciated.
ERROR
You cannot call a method on a null-valued expression.
At C:\Scripts\Dev\devCloneEnvironmentContentPerResource.ps1:13 char:35
+ $envID = ($pool.Name.Split <<<< ("_"))[0].Substring(3)
+ CategoryInfo : InvalidOperation: (Split:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Scripts\Dev\devCloneEnvironmentContentPerResource.ps1:14 char:33
+ $networkID = ($pool.Name.Split <<<< ("_"))[1].Substring(0)
+ CategoryInfo : InvalidOperation: (Split:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Scripts\Dev\devCloneEnvironmentContentPerResource.ps1:15 char:37
+ $netID = ( ($pool.Name.Split <<<< ("_"))[2].Substring(3).Split(" ") )[0]
+ CategoryInfo : InvalidOperation: (Split:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
SCRIPT
#
# Parameter Declarations
#
Param($folder_param, $resourcePool_param, $environmentID)
#
# Function Definitions
#
Function Get-PoolID ($pool)
{
$envID = ($pool.Name.Split("_"))[0].Substring(3)
$networkID = ($pool.Name.Split("_"))[1].Substring(0)
$netID = ( ($pool.Name.Split("_"))[2].Substring(3).Split(" ") )[0]
$poolID = New-Object PSObject
Add-Member -InputObject $poolID -MemberType NoteProperty -Name "Env" -Value $envID
Add-Member -InputObject $poolID -MemberType NoteProperty -Name "Net" -Value $netID
Add-Member -InputObject $poolID -MemberType NoteProperty -Name "Network" -Value $networkID
$poolID
}
#
# Usage Statement
#
If (!$folder_param -or !$resourcePool_param)
{
"usage: CloneContent-Sandbox.ps1 -f targetFolder -r sourceResourcePool"
Exit
}
#
# Retrieve Locations
#
$source = Get-Folder -Location 'Library' -Name 'Library Hosts' | Get-ResourcePool -Name $resourcePool_param
$sourceVM_list = Get-VM -Location $source | Sort
Write-Host -ForegroundColor "Yellow" ("Source found on " + ($sourceVM_list|Select -First 1).VMHost.Name.TrimEnd("company.com"))
$target = Get-Folder -Location "Production" -Name $folder_param
$vmhost_list = Get-VMHost -Location $target | Sort
If (!$source -or !$sourceVM_list -or !$target -or !$vmhost_list) { Exit }
#
# Main Script
#
Foreach ($vmhost in $vmhost_list)
{
$pool_list = Get-ResourcePool -Location $vmhost | Where-Object { $_.Name -match $environmentID } | Sort
Foreach ($pool in $pool_list)
{
""
$pool.Name
"-------------"
$poolID = Get-PoolID $pool
$process = @() # Added to consume return data from Wait-Task
$tasks = @()
Foreach ($sourceVM in $sourceVM_list)
{
$vm_name = $sourceVM.Name -replace "_bak.*",("_NET" + $poolID.Network + "_" + $poolID.Env)
If ( !(Get-VM -Location $vmhost -Name $vm_name 2> $null) )
{
$tasks += (New-VM -VMHost $vmhost -ResourcePool $pool -VM $sourceVM -Name $vm_name -Confirm:$false -RunAsync)
" Cloning: " + $vm_name
}
}
If ($tasks)
{
# Wait-Task -Task $tasks
$process = Wait-Task -Task $tasks
}
}
}
""
Did you already check which ResourcePool is in $pool when the error is fired ?
Could you be hitting the hidden pool named Resources ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD,
When running $pool_list = Get-ResourcePool -Location $vmhost | Where-Object { $_.Name -match $environmentID } | Sort
$pool returns as empty.
However when running $pool_list = Get-ResourcePool -Location $vmhost | Where-Object { $_.Name -match "501" } | Sort
$pool contains all ResourcePools with "501".
Seems as though I' am unable to run -match against an array.
Same issue occurs when I use {$_.Name -like "*$environmentID*"}. $pool returns empty.
Do you have any ideas how I would return any ResourcePools matching the items in $environmentID.
Thanks
If you want to match against an array of names, you can use the -contains operator
$pool_list = Get-ResourcePool -Location $vmhost | Where-Object { $environmentID -contains $_.Name } | Sort
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
The problem with -contains is it requires an exact match.
However $environmentID is only part of the ResourcePool name.
Ok, then we use the RegEx 'or' operator (|)
Like this, that should allow multiple, partial matches.
# Assume $environmentId contains a number of strings
$regexEnvId = $environmentId -join '|'
$pool_list = Get-ResourcePool -Location $vmhost | Where-Object { $_.Name -match $regexEnvId } | Sort
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That did the trick.
Thanks for the help.