Hi,
Is it possible to move a VMs configuration files with PowerCli? Currently I have a script to empty a datastore, which basically move all harddisks associated with this datastore to another one.
BUT, for a given VM, if the configuration files is located at datastore "A", and one or more of the harddisks are located on say datastore "B", I am unable to move the configuration file. Or at least I haven't been able to figure out how.
Does anyone know if this is possible?
Afaik that is currently not possible. The Move-VM cmdlet moves everything (config files and vdisks) to another datastore.
So if you already have your vdisk on another datastore, the Move-VM will move these also to the new destination datastore.
But with the RelocateVM_Task method, which is an SDK method, you should be able to do what you want to do.
Use the Onyx project to get the PowerCLI code to do this or let me know if you need a sample script.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
This is only possible using the SDK methods.
You can find out the exact syntax easily by using Onyx.
Perform a migration from the vSphere Client and move only the config file using the Advanced option in the Select Datastore Window.
Onyx will output the code to do this.
difficulty is that you need to find out the locations of all harddisks first and specify them. If you forget to specify the current location of a harddisk, that harddisk will be moved to the location you are copying the config files to.
A quick sample script.
This will move the config files to the datastore specified in $tgtConfigDS and leave all the vdisks in place.
$vmName = "MyVM"
$tgtConfigDS = "MyDS"
$vm = Get-VM -Name $vmName
$hds = Get-HardDisk -VM $vm
$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.datastore = (Get-Datastore -Name $tgtConfigDS).Extensiondata.MoRef $hds | %{ $disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$disk.diskId = $_.Extensiondata.Key $disk.datastore = $_.Extensiondata.Backing.Datastore $spec.disk += $disk
} $ vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority")
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi,
Thanks for your reply! This is very much what I needed. I did try to use Onyx, but since by the glance of the code it would move all of the hard disks, I just ignored to try it. But this works, and I am allready using RelocateVM_Task() so this is a no-brainer to implement.
Thanks!
Many apologies for replying to such and old thread but I was wondering if this script could be modified to move the config file for all VMs in a specific resource pool?
Regards
No problem, but could you perhaps explain what you mean by moving the config file into a resource pool ?
Do you mean moving all the VMs to a specific resource pool.
That can be done as follows
Get-VM | Move-VM -Destination (Get-ResourcePool -Name tgtResPool)
Or do you mean something else ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks for the quick response.
Yes that's exactly I meant. I have a resource pool with around 70 vm servers in, I have managed to move all the hard disks to the correct datastore but this doesnt move the Configuration File. Each server has two disks, hard disk 1 & 2, and both reside on different datstores. I would the config file to reside with disk one.
Hope that makes sense.
You can use the earlier script I provided in this thread.
Combined with a loop over all your VMs the resulting script looks like this
function Move-VMConfig{ param($vm,$dsName) $hds = Get-HardDisk -VM $vm $spec = New-Object VMware.Vim.VirtualMachineRelocateSpec $spec.datastore = (Get-Datastore -Name $dsName).Extensiondata.MoRef $hds | %{ $disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$disk.diskId = $_.Extensiondata.Key $disk.datastore = $_.Extensiondata.Backing.Datastore $spec.disk += $disk
} $vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority") } Get-VM | %{ Move-VMConfig $_ $_.Harddisks[0].Filename.Split(']')[0].TrimStart('[') }
It will move the Config file to the same datastore where "Hard disk 1" is located and leave all the hard disk files in place.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
This is great. So just to confirm if I run this as is it will move the config file for every VM in the datacenter?
Correct, but perhaps you better test it first with a couple of VMs before running it against the complete vCenter.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
So if I wanted to try it on a Resource Pool that just has a couple of VM's in there I could just amend the following line:
Get-VM | %{ Move-VMConfig $_ $_.Harddisks[0].Filename.Split(']')[0].TrimStart('[') }
to something like thisGet-ResourcePool "UAT Environment" | Get-VM | %{ Move-VMConfig $_ $_.Harddisks[0].Filename.Split(']')[0].TrimStart('[') }
I'm still trying to get my head around PowerCLI I'm afraid. Could do with some good reading material.
That is correct.
Or you could try it with just 1 VM by specifying the name on the Get-VM cmdlet.
Get-VM MyVM | %{ Move-VMConfig $_ $_.Harddisks[0].Filename.Split(']')[0].TrimStart('[') }
Btw I mentioned a number of PowerShell and PowerCLI resources in my My PS library post.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That works perfectly. Thanks very much, you've saved me a hell of a lot of time with this.
I will take a good look at your blog in my spare time.
Many Thanks
Julian
Hey Guys,
Apologies so late in this thread, but I cant get this to script work...
I have tweaked it using various different methods and it always says:
"You cannot call a method on a null-valued expression."
Any ideas please?
It literally fails on line:
$vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority")
I use PowerGUI to code by the way
Thanks All
Couldn't get it to work either. Passing null-valued expression is probably from the fact that there is no harddisk at the VM object level ($_.Harddisks[0].)
Here's a revised:
function Move-VMConfig {
param($vm,$dsName)
$hds=Get-HardDisk -VM $vm
$spec=New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.datastore=(Get-Datastore -Name $dsName).Extensiondata.MoRef
$hds | % {$disk=New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$disk.diskId=$_.Extensiondata.Key
$disk.datastore=$_.Extensiondata.Backing.Datastore
$spec.disk+=$disk
}
$vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority")
}
$vms=get-vm atest
$vms | % {
Move-VMConfig -vm $_ -dsname (Get-HardDisk -VM $($_))[0].Filename.Split(']')[0].TrimStart('[')
}
Hello Mike,
I don't know how you use the script provided by LucD but i had the same issue because in this expression; $vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority") $VM had to be an object containing the VM. If it's a string it won't work.... For example:
i had to correct:
Move-VMConfig "myVmName" "MydatastoreName"
with:
Move-VMConfig (get-VM "myVmName") "MydatastoreName"
Hope it may help!
Hello,
Thank you for this great script to move configuration file, I plan to use it for a massive array migration but I'm stuck because on large VM with many disks and the script change the name of the hard-disks maybe because "$spec" contains the list of the disk but their order is not set so I assumed i had to had : "| sort Name"
function Move-VMConfig{
param($vm,$dsName)
$hds = Get-HardDisk -VM $vm | sort Name
$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
$spec.datastore = (Get-Datastore -Name $dsName).Extensiondata.MoRef
$hds | %{
$disk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$disk.diskId = $_.Extensiondata.Key
$disk.datastore = $_.Extensiondata.Backing.Datastore
$spec.disk += $disk
}
$vm.Extensiondata.RelocateVM_Task($spec, "defaultPriority")
But i quickly ran into another issue :
how to sort harddisk name when they exceed 9...??
Get-HardDisk -VM "MyVmName" | select Name,CapacityGB,Filename | sort Name
Name
----
Disque dur 1
Disque dur 10
Disque dur 11
Disque dur 12
Disque dur 13
Disque dur 14
Disque dur 15
Disque dur 2
Disque dur 3
Disque dur 4
Disque dur 5
Disque dur 6
Disque dur 7
Disque dur 8
Disque dur 9
Thank for you help !!
One way of doing that could be like this
$obj = @()
$data | % {
$obj += New-Object PSObject -Property @{
String = $_
Number = [int]([regex]::Match($_, '\d+')).Value
}
}
$obj | Sort-Object -Property Number |
Select String
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference