VMware Cloud Community
VITC
Contributor
Contributor

Move configuration files with PowerCLI?

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?

18 Replies
LucD
Leadership
Leadership

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

Reply
0 Kudos
avlieshout
VMware Employee
VMware Employee

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.

Arnim van Lieshout Blogging: http://www.van-lieshout.com Twitter: http://www.twitter.com/avlieshout If you find this information useful, please award points for "correct" or "helpful".
Reply
0 Kudos
LucD
Leadership
Leadership

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

VITC
Contributor
Contributor

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!

Reply
0 Kudos
Oatcake
Contributor
Contributor

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

Reply
0 Kudos
LucD
Leadership
Leadership

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

Reply
0 Kudos
Oatcake
Contributor
Contributor

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.

Reply
0 Kudos
LucD
Leadership
Leadership

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

Reply
0 Kudos
Oatcake
Contributor
Contributor

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?

Reply
0 Kudos
LucD
Leadership
Leadership

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

Reply
0 Kudos
Oatcake
Contributor
Contributor

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 this

Get-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.
Reply
0 Kudos
LucD
Leadership
Leadership

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

Reply
0 Kudos
Oatcake
Contributor
Contributor

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

Reply
0 Kudos
Mike_Yazbeck
Enthusiast
Enthusiast

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 Smiley Happy

Thanks All Smiley Happy

Reply
0 Kudos
HenryCano
Contributor
Contributor

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('[')

}

Reply
0 Kudos
Yom007fr
Contributor
Contributor

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! Smiley Happy

Reply
0 Kudos
Yom007fr
Contributor
Contributor

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 !! Smiley Happy

Reply
0 Kudos
LucD
Leadership
Leadership

One way of doing that could be like this

$data = @("Hard Disk 11", "Hard Disk 7", "Hard Disk 1", "Hard Disk 1")

$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

Reply
0 Kudos