VMware Cloud Community
Rangdo7
Contributor
Contributor
Jump to solution

Storage VMotion to multiple datastores

I'm looking for some advice and assistance with using the vSphere PowerCLI to do SVMotions.

I found that I can use Get-VM vmname | Move-VM -datastore (Get-Datastore datastorename) which worked great and I was ready to roll. However, it occured to me that I can only reference one datastore in the cmdlet and some of our VM's have their disks located on different datastores.

So I set up a test VM with two disks on different datastores and kicked off a SVMotion. The result was that it migrated all the disks from from their seperate datastores to a single folder on the target.

What I need to be able to do is migrate one disk and leave the other in its original location or migrate two disks from different locations to two different new locations. Like you can if you power off the VM and migrate through the GUI, relocating the storage with the Advanced options (and presumably what you can do through the GUI with the VM powered on in vSphere).

I've got ESX 3.5 Update 5 with vCenter 2.5 Update 6 so no GUI option in VirtualCenter and the unsupported free snapin is not an option.

Is there a way to do this with the PowerCLI or am I limited to migrating single datastore VM's?

Many thanks .

0 Kudos
1 Solution

Accepted Solutions
avlieshout
VMware Employee
VMware Employee
Jump to solution

This can be achieved using the .RelocateVM_Task() method of the VirtualMachine SDK object

See the code below:

$configDatastoreName = "DataStore_01"
$HardDisk1DatastoreName = "DataStore_02"
$HardDisk2DatastoreName = "Datastore_03"

$vm = Get-VM VM001
 
$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
#Get MoRef for Destination datastore for Config files
$spec.Datastore = (Get-Datastore $configDatastoreName | Get-View).MoRef

#for each disk specify where the vmdk files should be placed.
#If a vmdk should NOT be moved, enter its CURRENT datastore
#If you forget to specify a disks location, it will be moved to the datastore
#specified in $spec.Datastore

#HardDisk 1
$objDisk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$objDisk.DiskID = $vm.HardDisks[0].Id.Split('/')[1]
$objDisk.DataStore = (Get-Datastore $HardDisk1DatastoreName | Get-View).MoRef
$spec.Disk += $objDisk

#HardDisk 2
$objDisk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$objDisk.DiskID = $vm.HardDisks[1].Id.Split('/')[1]
$objDisk.DataStore = (Get-Datastore $HardDisk2DatastoreName | Get-View).MoRef
$spec.Disk += $objDisk

#When all harddisks are specified call the RelocateVM_task() 
$vm.ExtensionData.RelocateVM_Task($spec, "defaultPriority")

-


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".

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".

View solution in original post

0 Kudos
16 Replies
avlieshout
VMware Employee
VMware Employee
Jump to solution

This can be achieved using the .RelocateVM_Task() method of the VirtualMachine SDK object

See the code below:

$configDatastoreName = "DataStore_01"
$HardDisk1DatastoreName = "DataStore_02"
$HardDisk2DatastoreName = "Datastore_03"

$vm = Get-VM VM001
 
$spec = New-Object VMware.Vim.VirtualMachineRelocateSpec
#Get MoRef for Destination datastore for Config files
$spec.Datastore = (Get-Datastore $configDatastoreName | Get-View).MoRef

#for each disk specify where the vmdk files should be placed.
#If a vmdk should NOT be moved, enter its CURRENT datastore
#If you forget to specify a disks location, it will be moved to the datastore
#specified in $spec.Datastore

#HardDisk 1
$objDisk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$objDisk.DiskID = $vm.HardDisks[0].Id.Split('/')[1]
$objDisk.DataStore = (Get-Datastore $HardDisk1DatastoreName | Get-View).MoRef
$spec.Disk += $objDisk

#HardDisk 2
$objDisk = New-Object VMware.Vim.VirtualMachineRelocateSpecDiskLocator
$objDisk.DiskID = $vm.HardDisks[1].Id.Split('/')[1]
$objDisk.DataStore = (Get-Datastore $HardDisk2DatastoreName | Get-View).MoRef
$spec.Disk += $objDisk

#When all harddisks are specified call the RelocateVM_task() 
$vm.ExtensionData.RelocateVM_Task($spec, "defaultPriority")

-


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".

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".
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Can't you use the Set-HardDisk cmdlet with the -Datastore parameter for that ?

Get-VM $vmName | Get-HardDisk | where {$_.Name -eq "Hard disk 1"} | Set-HardDisk -Datastore datastore1 -Confirm:$false

____________

Blog: LucD notes

Twitter: lucd22


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
avlieshout
VMware Employee
VMware Employee
Jump to solution

True, but it would require a task for every harddisk. Using the SDK relocateVM_task() method will do it in just one task.

Arnim

Sent from my iPad

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".
0 Kudos
Rangdo7
Contributor
Contributor
Jump to solution

Looks like it may not be possible.

I tried using the Set-HardDisk cmdlet and got the following error:

The operation for the entity VirtualMachine failed with the following message: "The requested Storage VMotion would move a virtual machine's disks without assigning the virtual machine a new home, but such a move is not supported on the source host hostname"

and found this KB article:

http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=102120...

Specifically:

"In ESX 3.5, the .vmdk and .vmx files must be migrated together from the source datastore to the destination datastore. A .vmdk file cannot be migrated independently of the .vmx file."

and

"You can also perform a Storage VMotion of the virtual machine to an ESX/ESXi 4.x host and perform the SVMotion operation with the virtual machine running there. In ESX/ESXi 4.x, the virtual machine files can be moved independently."

I get this even if I try to migrate a .vmdk that is already on a seperate datastore to the .vmx file.

So looks like I may be out of luck until we upgrade. Unless theres any other suggestions?

0 Kudos
sm_in-virtu
Contributor
Contributor
Jump to solution

I find myself in a similar position of needing to migrate VM's with disks on multiple datastores. Arnim's script looked like it was a winner for me but unfortunately it didn't work for me. It gave me a null assignment error on the final relocateVMtask command (I don't have the exact error in front of me now as I'm at home). I did a bit of research and found that in the API documentation that the relocateVMtask is for cold migrations. In my case I do need to do a hot migration (powering off the VM is not an option). I furthermore found that the svmotion.pl command of the RCLI does support what I want (and I think the starter of this thread). Too bad that there doesn't seem to be a functional equivalent in powerCLI (I hope someone will prove me wrong 🙂 )

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Which ESX(i) version are you running ?

The RelocateVM_Task method can do svMotion for powered on guests.

With PowerCLI you need a task per harddisk but is still very easy

$dsHd1 = "datastore1" 
$dsHd2
= "datastore2"
$dsHdi
= "datastore3" foreach($vm in Get-VM){     foreach($hd in (Get-HardDisk -VM $vm | where {$_.DiskType -eq "Flat"})){         switch($hd.Name){             "Hard disk 1"{                 $tgtDs = $dsHd1           
            }            
"Hard disk 2"{                 $tgtDs = $dsHd2
            }             Default{                 $tgtDs = $dsHdi
            }         }         Set-HardDisk -HardDisk $hd -Datastore $tgtDs -Confirm:$false    } }


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

avlieshout
VMware Employee
VMware Employee
Jump to solution

Luc,

Set-HardDisk wil only move the harddisks and not the config files.

If you need to move the complete vm, you need to use Move-VM.

Move-VM can't move to multiple destinations, so in that case afaik

the only other option is using the SDK

Arnim

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".
LucD
Leadership
Leadership
Jump to solution

That is correct.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
sm_in-virtu
Contributor
Contributor
Jump to solution

Luc,

This customer is running ESX version 3.5U1 vCenter 2.5U1...

It was late last night... I'm now looking at it again and you're right.

I now also see that in this version of the SDK there is no priority parameter AND I found your other posts on this issue.

Seems that I'll have to use the RCLI.

Thanks,

Serge

0 Kudos
qwert1235
Enthusiast
Enthusiast
Jump to solution

I am wondering why I am getting the error below when i am trying to run your script?

Property 'Disk' cannot be found on this object; make sure it exists and is settable.

+ $spec. <<<< Disk += $objDisk

+ CategoryInfo : InvalidOperation: (:) [], RuntimeException

+ FullyQualifiedErrorId : PropertyAssignmentException

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Against which vSphere version (vCenter and ESX(i)) are you running this ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
qwert1235
Enthusiast
Enthusiast
Jump to solution

I am connecting to VC 4.0u2.

VMs located on ESX 3.5 and ESXi 4.0u2.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That should work.

Would you mind attaching the script you are using ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
qwert1235
Enthusiast
Enthusiast
Jump to solution

Luc,

You are right!  I did not want to move vm config files and did not copy "$spec= New-Object VMware.Vim.VirtualMachineRelocateSpec".

Now problem solved and it's working as I want.

Let me ask you something else, please.

I attached the script that I am going to use to convert VMs from thin to thick.

Right now it's working for 1 single VM, but I am going to change it.  The problem I am facing is with harddrives. In the script I am using VM that has 2 harddrives (I just know it:) and I am specifiying parameters for 2 harddrives in advance just because I know there are 2 harddrives. But how should I adjust the script if there will be different (unknown in the beging) numbers of harddrives (from 1 to 5)? How can I find all harddrives on VMs, correlate them with datastores (few might be on the same datastore) and use it later on in the script?

Thanks a lot!

Please let me know if you want me to open new discussion for this topic.

UPD: I can use $diskNumber= $VM.HardDisks.Count, count disks and write different "if" for different numbers, but I think there is should be better solution

0 Kudos
JohnnyFive
Contributor
Contributor
Jump to solution

I realize that this is a year old but I am hoping it is still relevant.  I have a similar need to sVmotion over a thousand machines and would like to utilize something like the above. The script seems to be very machine specific though.  I was hoping you could point me in the correct direction on the following:

  • Is there was to build a table for “If Source DataStore = X, then use Destination Datastore Y” Keeping in mind multiple datastores per machine.
  • Would I also be able to add additional statements to cover additional drives? Say 7 or 8 without causing errors for machines with fewer?

I am running 4.1.1

Thanks in Advance and for your past work

0 Kudos
aworkman
Enthusiast
Enthusiast
Jump to solution

Here is an example script that scales a little higher and would assume that you have standardized on a group of datastores for these VM's.  The example shown assumes you have a bunch of VM's in 4 different volumes.  nas1_nfs_os1/nas1_nfs_data1 and nas2_nfs_os2/nas2_nfs_data2.  Then you have 4 new volumes as a home for them.  vmware_nfs_os3/vmware_nfs_data3, vmware_nfs_os4/vmware_nfs_data4.  Respectively you want to move all of the VM's from 1 -> 3, and 2 -> 4.  I also have some extra lines to move configs that are currently on data1/data2 to the proper location in the new OS volumes(some people got lazy with provisioning).  You could have more/less original/new volume combinations by tweaking the if/elseif lines.  It is important to make sure not to move anything if it doesn't match one of your examples, that way if you have disks with dedicated volumes you don't move those.  This is where the else line says if it doesn't match one of the migration volumes just leave it where it's at.

This script loops through the iteration of disks regardless of the number and says if the old one is x, then it should be y.  If it's not x, then leave it where it is.

This would help you do a big migration from several different volumes to several new volumes for a bunch of VM's.  It is also set to start 5 tasks at a time, which can be modified by editing the $numtasks.Count -lt 5 line.  This is tuned to my environment using the other example script that was available in previous posts.  So it will obviously take some tweaking to work in your situation, but it's a good start for anyone doing a big move.

If you are using NetApp/DeDupe you have to be careful not to move them all in one big shot without re-running the dedupe jobs or the new volumes won't be big enough to house what fit in your old volumes.

0 Kudos