I am trying to change hw version for some vms in a cluster with the below script. Its failing for some vms while split of vmx path in line 7 & 8.
$hwveroffvms=Get-Cluster "WTR_LABS_02" | Get-VM |?{$_.powerstate -eq 'PoweredOff' -and $_.version -eq 'v11'} |select name ,version,powerstate
foreach($vmName in $hwveroffvms.name){
$tgtFolder = $env:Temp
Get-VM -Name $vmName | %{
$dsName,$vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split()
$vmxName = $vmxPath.Split('/')[-1]
$vmxFolder = [string]::Join('/',($vmxPath.Split('/')[-99..-2]))
$dsName = $dsName.Trim('[]')
$ds = Get-Datastore -Name $dsName
New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root "\" | Out-Null
Copy-DatastoreItem -Item "DS:$vmxPath" -Destination $tgtFolder
(Get-Content -Path "$tgtFolder\$vmxName")| ForEach-Object {$_ -Replace 'virtualHW.version = "11"', 'virtualHW.version = "10"'} | Set-Content -Path "$tgtFolder\$vmxName"
Copy-DatastoreItem -Item "$tgtFolder\$vmxName" -Destination "DS:$vmxFolder" -Force
Get-ChildItem -Path "$tgtFolder\$vmxName" | Remove-Item -Confirm:$false
Remove-PSDrive -Name DS -Confirm:$false
}
}
For example if the VM name something like vm01 the script is able to execute successfully but in the environment there are multiple vcloud vms with name some this like below snap. There script is not splitting the vmx path correctly.
Can you try like this
Get-VM -Name 'SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d)',
'POSSoulFoods (868a2a98-9509-4646-b396-6b8093101f81)',
'AV_SCM_3 - wusas230233-003 (d7ef0854-c5f3-4ad9-aedf-2ddc70d6b36e)' |
ForEach-Object -Process {
$dsName = $_.ExtensionData.Config.Files.VmPathName.Split(']').TrimStart('[')[0]
$vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split(']')[1].TrimStart(' ')
$vmxName = $vmxPath.Split('/')[-1]
$vmxFolder = [string]::Join('/', ($vmxPath.Split('/')[-99..-2]))
$ds = Get-Datastore -Name $dsName
New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root "\" | Out-Null
Copy-DatastoreItem -Item "DS:$vmxPath" -Destination $tgtFolder
(Get-Content -Path "$tgtFolder\$vmxName")| ForEach-Object {$_ -Replace 'virtualHW.version = "11"', 'virtualHW.version = "10"'} | Set-Content -Path "$tgtFolder\$vmxName"
Copy-DatastoreItem -Item "$tgtFolder\$vmxName" -Destination "DS:$vmxFolder" -Force
Get-ChildItem -Path "$tgtFolder\$vmxName" | Remove-Item -Confirm:$false
Remove-PSDrive -Name DS -Confirm:$false
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
1) Why are you doing it that way, and not for example like this?
$do.ScheduledHardwareUpgradeInfo = New-Object -TypeName VMware.Vim.ScheduledHardwareUpgradeInfo
$do.ScheduledHardwareUpgradeInfo.UpgradePolicy = [VMware.Vim.ScheduledHardwareUpgradeInfoHardwareUpgradePolicy]::onSoftPowerOff
$do.ScheduledHardwareUpgradeInfo.VersionKey = “vmx-13”
$do.Tools = New-Object VMware.Vim.ToolsConfigInfo
$do.Tools.ToolsUpgradePolicy = "UpgradeAtPowerCycle"
foreach ($vmName in (Get-Cluster "WTR_LABS_02" | Get-VM |? {$_.powerstate -eq 'PoweredOff' -and $_.version -eq 'v11'} )) {
$vm = Get-VM -Name $vmName
$vm.ExtensionData.ReconfigVM_Task($do)
}
2) What part of the name do you need to extract, in other words what is the name of the .vmx file?
The part before the string between parenthesis?
For example for the 1st line SEP00VVM-278?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD,
I am trying to downgrade the hardware version from 11 to 10 not upgrade.
For example the vm name is 'SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d)' and vmx file path is [SEP00_97WTR_AA04] SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d)/SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d).vmx
After this like $vmxName = $vmxPath.Split('/')[-1]
it is showing only this (90389be9-cc74-49e5-aa8a-3079efea166d).vmx
It should show like this SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d).vmx
----
If there is a normal vm (not vcloud vm) without uuid like this SEP00VVM-34. I can able to see correct vmx file path like this
SEP00VVM-34.vmx
---
Problem is I am failing to split the path correctly.
If the ESXi node supports it, you should be able to downgrade this way as well.
Did you try?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
This seems to working for me
$t.Split('/')[-1]
What does that return on your station?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Output
Ok, I think I see what is happening.
Replace this line
with these 2 lines
$vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split('/')[1]
Did you already try the downgrade with the solution I gave in 1)?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
After replacing those lines this time $vmxpath is not showing correctly so $vmxFolder showing blank and copy is failing in the next lines of the script.
Did you already try the downgrade with the solution I gave in 1)?
Yes I tried that script but its not working. Its states 'the virtual machine compatibility is already up-to-date' even if i downgrade to vmx-10
Try with this version
foreach ($vmName in $hwveroffvms.name) {
$tgtFolder = $env:Temp
Get-VM -Name $vmName | % {
$dsName = $_.ExtensionData.Config.Files.VmPathName.Split(']').TrimStart('[')[0]
$vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split(']')[1].TrimStart(' ')
$vmxName = $vmxPath.Split('/')[-1]
$vmxFolder = [string]::Join('/', ($vmxPath.Split('/')[-99..-2]))
$ds = Get-Datastore -Name $dsName
New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root "\" | Out-Null
Copy-DatastoreItem -Item "DS:$vmxPath" -Destination $tgtFolder
(Get-Content -Path "$tgtFolder\$vmxName")| ForEach-Object {
$_ -Replace 'virtualHW.version = "11"', 'virtualHW.version = "10"'
} | Set-Content -Path "$tgtFolder\$vmxName"
Copy-DatastoreItem -Item "$tgtFolder\$vmxName" -Destination "DS:$vmxFolder" -Force
Get-ChildItem -Path "$tgtFolder\$vmxName" | Remove-Item -Confirm:$false
Remove-PSDrive -Name DS -Confirm:$false
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I think that the issue occurs due to the spaces in the VM's folder/name, where your original split will not provide the result that you may expect.
$dsName,$vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split()
How about something like this:
$extData = $_.ExtensionData.Config.Files.VmPathName
$dsName = $extData.Split('[]')[1]
$vmxFolder,$vmxName = $extData.Substring($ExtData.IndexOf("]")+2).split("/")
This will not only take care of spaces in the names, but will also allow brackets in the file names (if necessary).
André
I'm afraid your solution doesn't handle nested folders (which my original did do).
Try for example with '[ds] folder/vm/vm.vmx'
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
What should also work - with the least changes to your original script - is to modify line 5 from
$dsName,$vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split()
to
$dsName,$vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split('[] ', 4)[1,3]
André
Yes now its copying and changing vmx version as expected but it is only taking one vm in the loop.
For example if i give as below its just changing for this VM 'SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d)' 3 times. Is there anything wrongly mentioned in the loop.
what is $t its no where mentioned in the script.
foreach ($vmName in (Get-VM 'SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d)','POSSoulFoods (868a2a98-9509-4646-b396-6b8093101f81)','AV_SCM_3 - wusas230233-003 (d7ef0854-c5f3-4ad9-aedf-2ddc70d6b36e)')) {
$tgtFolder = $env:Temp
Get-VM -Name $vmName.name | % {
$dsName, $vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split()
$dsName = $t.Split(']').TrimStart('[')[0]
$vmxPath = $t.Split(']')[1].TrimStart(' ')
$vmxName = $vmxPath.Split('/')[-1]
$vmxFolder = [string]::Join('/', ($vmxPath.Split('/')[-99..-2]))
$ds = Get-Datastore -Name $dsName
New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root "\" | Out-Null
Copy-DatastoreItem -Item "DS:$vmxPath" -Destination $tgtFolder
(Get-Content -Path "$tgtFolder\$vmxName")| ForEach-Object {$_ -Replace 'virtualHW.version = "11"', 'virtualHW.version = "10"'} | Set-Content -Path "$tgtFolder\$vmxName"
Copy-DatastoreItem -Item "$tgtFolder\$vmxName" -Destination "DS:$vmxFolder" -Force
Get-ChildItem -Path "$tgtFolder\$vmxName" | Remove-Item -Confirm:$false
Remove-PSDrive -Name DS -Confirm:$false
}
}
Can you try like this
Get-VM -Name 'SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d)',
'POSSoulFoods (868a2a98-9509-4646-b396-6b8093101f81)',
'AV_SCM_3 - wusas230233-003 (d7ef0854-c5f3-4ad9-aedf-2ddc70d6b36e)' |
ForEach-Object -Process {
$dsName = $_.ExtensionData.Config.Files.VmPathName.Split(']').TrimStart('[')[0]
$vmxPath = $_.ExtensionData.Config.Files.VmPathName.Split(']')[1].TrimStart(' ')
$vmxName = $vmxPath.Split('/')[-1]
$vmxFolder = [string]::Join('/', ($vmxPath.Split('/')[-99..-2]))
$ds = Get-Datastore -Name $dsName
New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root "\" | Out-Null
Copy-DatastoreItem -Item "DS:$vmxPath" -Destination $tgtFolder
(Get-Content -Path "$tgtFolder\$vmxName")| ForEach-Object {$_ -Replace 'virtualHW.version = "11"', 'virtualHW.version = "10"'} | Set-Content -Path "$tgtFolder\$vmxName"
Copy-DatastoreItem -Item "$tgtFolder\$vmxName" -Destination "DS:$vmxFolder" -Force
Get-ChildItem -Path "$tgtFolder\$vmxName" | Remove-Item -Confirm:$false
Remove-PSDrive -Name DS -Confirm:$false
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I got the issue.
I am sorry there is already a stored value in $t variable for VM 'SEP00VVM-278 (90389be9-cc74-49e5-aa8a-3079efea166d)' which I executed earlier. I believe that why its executed only for that vm.
This time I closed the ISE and reopen it and executed below script and this is error. what need to replaced in $t
You didn't copy the latest version I included
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Totally Confused. I thought i copied correctly. Thanks LucD now its working as expected
That happens to the best of us.
Happy it is working now :smileygrin:
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference