Hello,
I am having issues when using a script to move VMs from the Discovered VMs folder to their dedicated VM folders as they were on the old vCenter. I already recreated the folder structure on the new vCenter.
The csv from where i am importing is on the form:
Name Path
vm1 DatacenterFolderName\folder1\folder2\vm1
vm2 DatacenterFolderName\folder2\folder3\vm2 etc
The script is the following:
Get-Module -Name VMware* -ListAvailable | Import-Module
If ($globale:DefaultVIServers ) {
Disconnect-VIServer -Server $global:DefaultVIServers -Force
}
$destVI = Read-Host "Please enter name or IP address of the destination Server"
$datacenter = Read-Host "DataCenter name in VC"
$creds = get-credential
connect-viserver -server $destVI -Credential $creds
# move the vm's to correct location
$VMfolder = @()
$VMfolder = import-csv "c:\csv-files\test\04-$($datacenter)-vms-with-FolderPath.csv" | Sort-Object -Property Path
foreach($guest in $VMfolder){
$key = @()
$key = Split-Path $guest.Path | split-path -leaf
if ($key -eq $datacenter) {
Write-Host "Root folder $guest.path"
#
Move-VM (Get-VM $guest.Name) -Destination "vm"
}
else
{
Move-VM (Get-VM $guest.Name) -Destination (Get-folder $key)
}
}
Disconnect-VIServer "*" -Confirm:$False
and the error i am getting is the following:
Move-VM : 10/19/2018 7:50:24 AM Move-VM Server task failed: The request refers to an unexpected or unknown type.
At C:\Users\username\Desktop\CheapDisasterRecovery\import-05-move-vms-folders.ps1:27 char:3
+ Move-VM (Get-VM $guest.Name) -Destination (Get-folder $key)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Move-VM], VimException
+ FullyQualifiedErrorId : Security_Impl_TaskResultConverter_TaskNotSucceeded,VMware.VimAutomation.ViCore.Cmdlets.Commands.MoveVM
Can someone let me know what i am doing wrong or if there is something that needs to be modified to make it work?
The original vCenter is 5.5 and the destination vCenter is 6.5.
Thank you.
Your script will not work when you have two subfolders with the same name.
DC\Folder1\TestFolder\vm2
DC\Folder2\TestFolder\vm2
To avoid that I have added a modified version of my Get-FolderByPath function.
Can you try with this version.
param(
[CmdletBinding()]
[parameter(Mandatory = $true)]
[System.String[]]${Path},
[char]${Separator} = '/'
)
process{
foreach($strPath in $Path){
$root = Get-Folder -Name Datacenters
$strPath.Split($Separator) | %{
$root = Get-Inventory -Name $_ -Location $root -NoRecursion
if((Get-Inventory -Location $root -NoRecursion | Select -ExpandProperty Name) -contains "vm"){
$root = Get-Inventory -Name "vm" -Location $root -NoRecursion
}
}
$root | where {$_ -is [VMware.VimAutomation.ViCore.Impl.V1.Inventory.FolderImpl]}|%{
Get-Folder -Name $_.Name -Location $root.Parent -NoRecursion
}
}
}
}
Get-Module -Name VMware* -ListAvailable | Import-Module
If ($globale:DefaultVIServers ) {
Disconnect-VIServer -Server $global:DefaultVIServers -Force
}
$destVI = Read-Host "Please enter name or IP address of the destination Server"
$creds = Get-Credential
connect-viserver -server $destVI -Credential $creds
# move the vm's to correct location
$VMfolder = Import-Csv "C:\csv-files\test\04-$datacenter-vms-with-FolderPath.csv" | Sort-Object -Property Path
foreach($guest in $VMfolder){
$key = Split-Path $guest.Path
$keyFolder = Get-FolderByPath -Path $key -Separator '\'
$vm = Get-VM -Name $guest.Name
Move-VM -VM $vm -Destination $vm.VMHost -InventoryLocation $keyFolder
}
Disconnect-VIServer "*" -Confirm:$False
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
If you are using a recent PowerCLI version, you have to use the InventoryLocation parameter to move a VM to a VM type folder.
Which PowerCLI version are you using?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc, thanks so much for replying.
This is what i get when list the modules:
PS C:\Windows\system32> Get-Module -ListAvailable -Name VMware*
Directory: C:\Program Files\WindowsPowerShell\Modules
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 6.7.0.8... VMware.DeployAutomation {Add-DeployRule, Add-ProxyServer, Add-ScriptBundle, Copy-D...
Script 6.7.0.8... VMware.ImageBuilder {Add-EsxSoftwareDepot, Add-EsxSoftwarePackage, Compare-Esx...
Manifest 11.0.0.... VMware.PowerCLI
Script 6.7.0.1... VMware.Vim
Script 11.0.0.... VMware.VimAutomation.Cis.Core {Connect-CisServer, Disconnect-CisServer, Get-CisService}
Script 11.0.0.... VMware.VimAutomation.Cloud {Add-CIDatastore, Connect-CIServer, Disconnect-CIServer, G...
Script 11.0.0.... VMware.VimAutomation.Common
Script 11.0.0.... VMware.VimAutomation.Core {Add-PassthroughDevice, Add-VirtualSwitchPhysicalNetworkAd...
Script 7.6.0.1... VMware.VimAutomation.HorizonView {Connect-HVServer, Disconnect-HVServer}
Script 10.0.0.... VMware.VimAutomation.License Get-LicenseDataManager
Script 11.0.0.... VMware.VimAutomation.Nsxt {Connect-NsxtServer, Disconnect-NsxtServer, Get-NsxtService}
Script 11.0.0.... VMware.VimAutomation.Sdk {Get-ErrorReport, Get-PSVersion, Get-InstallPath}
Script 11.0.0.... VMware.VimAutomation.Security {Get-SecurityInfo, Get-VTpm, Get-VTpmCertificate, Get-VTpm...
Script 10.0.0.... VMware.VimAutomation.Srm {Connect-SrmServer, Disconnect-SrmServer}
Script 11.0.0.... VMware.VimAutomation.Storage {Add-KeyManagementServer, Copy-VDisk, Export-SpbmStoragePo...
Script 1.3.0.0 VMware.VimAutomation.StorageUtility Update-VmfsDatastore
Script 11.0.0.... VMware.VimAutomation.Vds {Add-VDSwitchPhysicalNetworkAdapter, Add-VDSwitchVMHost, E...
Script 11.0.0.... VMware.VimAutomation.Vmc {Connect-Vmc, Disconnect-Vmc, Get-VmcSddcNetworkService, G...
Script 10.0.0.... VMware.VimAutomation.vROps {Connect-OMServer, Disconnect-OMServer, Get-OMAlert, Get-O...
Script 6.5.1.7... VMware.VumAutomation {Add-EntityBaseline, Copy-Patch, Get-Baseline, Get-Complia...
So what do i have to replace in the script to make it work?
Do i need to replace the -Destination parameter with -InventoryLocation ?
No, due to a "feature" you also have to use the Destination parameter.
But you can point Destination to the same ESXi node where the VM is already running.
Something like this seems to work for me.
$vm = Get-VM -Name $guest.Name
$folder = Get-Folder -Name $key -Type VM
Move-VM -VM $vm -Destination $vm.VMHost -InventoryLocation $folder
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks for the reply and clarification.
Do i replace the whole if / else sequence in the script or just the lines containing the Move-VM command? I am a bit confused as to what do i need to modify in the script... Do i need to also have a column in the CSV with the host where the VM resides? the exported csv only contains the vm name and path as described in the original post.
You only should replace the single Move-VM line in your Else-block with these lines.
No need to add a column, the Get-VM will return an object that shows where the VM is running in the VMHost property.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I did that initially but it throws another error and i thought am not doing something right and something else must be modified.
This is the error i am getting now, with only the single Move VM line replaced in the else block from the script:
Move-VM : 10/22/2018 9:13:52 AM Move-VM Value cannot be found for the mandatory parameter VM
At C:\Users\username\Desktop\CheapDisasterRecovery\import-05-move-vms-folders.ps1:29 char:9
+ Move-VM -Destination $vm.VMHost -InventoryLocation $folder
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Move-VM], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.MoveVM
Any thoughts?
The Move-VM should of course include the VM parameter.
I updated the code above.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thank you so much for your help. It is working as expected now.
Hi Luc,
The script works when moving the vms into unique folders, however when trying to move the vms into duplicate folder names from different paths it errors out like this:
Move-VM : Cannot convert 'System.Object[]' to the type
'VMware.VimAutomation.ViCore.Types.V1.Inventory.VIContainer' required by parameter
'Destination'. Specified method is not supported.
At C:\Users\username\Desktop\CheapDisasterRecovery\import-05-move-vms-folders.ps1:29 char:38
+ Move-VM -VM $vm -Destination $vm.VMHost -InventoryLocation $f ...
+ ~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Move-VM], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,VMware.VimAutomation.ViCore.Cmdlets.C
ommands.MoveVM
Any idea on how to correct this?
Now i tried again with the unique folders and it is throwing the same error...
I suspect that the $vm variable holds more than 1 VM.
Can you check?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I modified the csv and I tried to move a single vm now which has unique name within the whole vcenter and it is erroring out.
This is the code i tried with it:
Get-Module -Name VMware* -ListAvailable | Import-Module
If ($globale:DefaultVIServers ) {
Disconnect-VIServer -Server $global:DefaultVIServers -Force
}
$destVI = Read-Host "Please enter name or IP address of the destination Server"
$datacenter = Read-Host "DataCenter name in VC"
$creds = get-credential
connect-viserver -server $destVI -Credential $creds
# move the vm's to correct location
$VMfolder = @()
$VMfolder = import-csv "C:\csv-files\test\04-$datacenter-vms-with-FolderPath.csv" | Sort-Object -Property Path
foreach($guest in $VMfolder){
$key = @()
$key = Split-Path $guest.Path | split-path -leaf
if ($key -eq $datacenter) {
Write-Host "Root folder $guest.path"
##
Move-VM (Get-VM $guest.Name) -Destination "vm"
}
else
{
$vm = Get-VM -Name $guest.Name
$folder = Get-Folder -Name $key -Type VM
Move-VM -VM $vm -Destination $vm.VMHost -InventoryLocation $folder
}
}
Disconnect-VIServer "*" -Confirm:$False
Still no luck... Either that or i am not sure exactly what 1 VM into the $vm variable means... what do i need to check by that?
You could be connected multiple times. CHeck what is in $global:defaultviservers
You could have multiple VMs with the same displayname in the environment.
How many objects does this return (use the name of the single VM you tested with)?
Get-VM -Name <your-VM>
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hello,
Nope, just a single object returned for each of the commands.
PS C:\Windows\system32> $global:defaultviservers
Name Port User
---- ---- ----
prdvcsa 443 DOMAIN\malbu
PS C:\Windows\system32> Get-VM -Name malbu-vm
Name PowerState Num CPUs MemoryGB
---- ---------- -------- --------
malbu-vm PoweredOn 2 6.000
I added some debugging lines.
Can you run this version, and tell me what is shown on the console?
Get-Module -Name VMware* -ListAvailable | Import-Module
If ($global:DefaultVIServers ) {
Disconnect-VIServer -Server $global:DefaultVIServers -Force
}
$destVI = Read-Host "Please enter name or IP address of the destination Server"
$datacenter = Read-Host "DataCenter name in VC"
$creds = Get-Credential
connect-viserver -server $destVI -Credential $creds
# move the vm's to correct location
$VMfolder = @()
$VMfolder = Import-Csv "C:\csv-files\test\04-$datacenter-vms-with-FolderPath.csv" | Sort-Object -Property Path
foreach($guest in $VMfolder){
$key = @()
$key = Split-Path $guest.Path | split-path -leaf
if ($key -eq $datacenter) {
Write-Host "Root folder $guest.path"
##
Move-VM (Get-VM $guest.Name) -Destination "vm"
}
else
{
$vm = Get-VM -Name $guest.Name
$folder = Get-Folder -Name $key -Type VM
Write-Host "VM : $($vm.Count)"
Write-Host "ESX : $($VM.VMHost.Name -join '|')"
Move-VM -VM $vm -Destination $vm.VMHost -InventoryLocation $folder
}
}
Disconnect-VIServer "*" -Confirm:$False
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I ran your version and it's working...seriously, i don't understand this anymore... This is the output with the debugging:
PS C:\Windows\system32> C:\Users\username\Desktop\CheapDisasterRecovery\import-05-move-vms-folders-debugging.ps1
Please enter name or IP address of the destination Server: prdvcsa
DataCenter name in VC: Corporate
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Name Port User
---- ---- ----
prdvcsa 443 DOMAIN\malbu
VM : 1
ESX : prd1.domain.com
PowerState : PoweredOn
Version : v10
HardwareVersion : vmx-10
Notes :
Guest : malbu-vm:Microsoft Windows 7 (64-bit)
NumCpu : 2
CoresPerSocket : 1
MemoryMB : 6144
MemoryGB : 6
VMHostId : HostSystem-host-13
VMHost : prd1.domain.com
VApp :
FolderId : Folder-group-v2060
Folder : Employees
ResourcePoolId : ResourcePool-resgroup-30
ResourcePool : Resources
PersistentId : 5028db3d-0246-08c0-d83c-1103dd2c7a9e
UsedSpaceGB : 54.409996171481907367706298828
ProvisionedSpaceGB : 66.109215467236936092376708984
DatastoreIdList : {Datastore-datastore-1664}
HARestartPriority : ClusterRestartPriority
HAIsolationResponse : AsSpecifiedByCluster
DrsAutomationLevel : AsSpecifiedByCluster
VMSwapfilePolicy : Inherit
VMResourceConfiguration : CpuShares:Normal/2000 MemShares:Normal/61440
GuestId : windows7_64Guest
Name : malbu-vm
CustomFields : {[XdConfig, ]}
ExtensionData : VMware.Vim.VirtualMachine
Id : VirtualMachine-vm-1558
Uid : /VIServer=domain\malbu@prdvcsa:443/VirtualMachine=VirtualM
achine-vm-1558/
PS C:\Windows\system32>
Can you attach your last version of the script as a file (bottom right - attach button)?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference