Im looking to svMotion VM's based on a spreadsheet or txt file (either will work for me) from one datastore to another. I've found simple ones that do it, but nothing that will import a csv file or txt file and svmotion those VM's.
Try changing line 37 (in the original function) into this
$NumvMotionTasks = (Get-Task | ? { ($_.PercentComplete -ne 100) -and ($_.Description -match 'Relocate')} | Measure-Object).Count
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Do you want to put your destination datastore in the CSV? If so, you'd have something like this:
csv file format:
vmname | destDS |
myVM1 | datastore1 |
myVM2 | datastore2 |
myVM3 | datastore3 |
$filepath = "D:\PathtoCSV\filename.csv
$csvobj = import-csv $filepath
foreach ($row in $csvobj) {
$vmobj = get-vm $row.vmname
$ds = get-datastore $row.destds
$vmobj | move-vm -datastore $ds -confirm:$false
}
Not very eloquent, but should get the job done. Let me know how it works out!
BC
Wouldnt be an issue.
So you're saying I would add the VM's I want to migrate to the "vmname" column, then the DS that I want it to go to in the "DESTDS"?
If I have 30-40 VMs in the csv file.....Is there a way to have say, 3 or 4 run at a time and queue up the ones behind it? Almost like a job.....
I might do it like this:
$VMsToMove = Get-Datastore "NameofDataStoreContainingTargetVMs" | Get-VM
$TargetDatastore = GetDatastore NameofTargetDatastore
Foreach ($VM in $VMsToMove)
{
Move-VM -VM $VM -Destination $TargetDatastore -Confirm:$False
}
Unless of course you have a particular need to make a CSV to import from.
Or, if it's an option, make a datastore cluster and place the datastore you want to move from into maintenance mode.
Yeah, I want to queue up basically 30-40 VM's so having them in a list would work better, since I dont want to evacuate an entire DS.
Not an option, we have some VM's that have RDM's attached and I want to svMotion those VM's separately.
So then you can use Brent's suggestion. Just add the -runasync switch to make it run like a queued job. Like so:
$filepath = "D:\PathtoCSV\filename.csv
$csvobj = import-csv $filepath
foreach ($row in $csvobj) {
$vmobj = get-vm $row.vmname
$ds = get-datastore $row.destds
$vmobj | move-vm -datastore $ds -runasync -confirm:$false
}
Does that only do 1 at a time? is there a value I can set against the -runasync command to run say 3 or 4 at the same time and have it kick off the next in the list when one's done?
The -runasync switch should just send the command and not monitor it's progress allowing the foreach loop to keep going even if the initial storage vmotion didn't start.
Ah
Is there a way to queue up 3 or 4 at a time based on a list of 30 or 40?
You could if you wanted to, but vCenter will normally throttle itself. So you could have all 50 queued up and only a subset of those would actually be active jobs.
One method would be to introduce an arbitrary count and sleep method. Or another more accurate, but would require a bit more coding would be to look @ the tasks and only start another job if the active task count is less than 4 or 5.
Here is the first method as an example:
$filepath = "D:\PathtoCSV\filename.csv
$csvobj = import-csv $filepath
$Count = 4
foreach ($row in $csvobj) {
$Count --
$vmobj = get-vm $row.vmname
$ds = get-datastore $row.destds
$vmobj | move-vm -datastore $ds -runasync -confirm:$false
If ($Count -lt 0){Sleep 1500; $Count = 4}
}
Id feel more comfortable with a script throttling it as apposed to what vCenter can handle. We have almost 4k VM's running and I wouldnt want it to try 30 because it thinks it can and then choke. Im ok with it doing 3-4 at a time though.
I have 3500 VM's in my environment. they are just job queues. I migrated 60 VM's from one datastore to another in the middle of the day using Storage DRS. It did exactly that, moved I think 8 at a time, while the rest of the jobs were just queued. The next one would continue when one finished.
We're not running storage DRS, but Im familiar with both.
Like I said, I'd feel more comfortable scheduling or queuing up a set number before running it. Thanks for the helpful info though.
Have a look at VMware sVmotion throttle
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That might do it LucD, I just didnt want to throttle vCenter's resources with 40+ svMotions and not be able to do any other work until those are done. How would I integrate this code with the one below?
$filepath = "D:\PathtoCSV\filename.csv
$csvobj = import-csv $filepath
foreach ($row in $csvobj) {
$vmobj = get-vm $row.vmname
$ds = get-datastore $row.destds
$vmobj | move-vm -datastore $ds -confirm:$false
}
Like this:
<#
.SYNOPSIS
Will enter a wait/loop if there are running vMotion or svMotion tasks.
.DESCRIPTION
Checks the tasks and counts the number running vMotion or svMotion tasks.
If the number of active tasks is greater than the specified limit
then the function sleeps and checks again. The intended is as a throttle
in large (s)vMotion loops to prevent overloading the environment. Is
especially useful in throttling a script while an unrelated event happens,
such as putting a host or datastore into maintenance mode.
.PARAMETER vMotionLimit
The active tasks to test for. If the number of active tasks is less than
this the function will exit. The default is 1, and must be an integer.
.PARAMETER DelayMinutes
How long to wait before checking the active tasks again. The default
is 1, and must be an integer.
.EXAMPLE
Wait-mTaskvMotions -Verbose
.EXAMPLE
Wait-mTaskvMotions -vMotionLimit 4
.EXAMPLE
Wait-mTaskvMotions -vMotionLimit 2 -DelayMinutes 3 -Verbose
.NOTES
Using -Verbose will output standard script started and finished messages,
and how long the function will sleep before it checks the active tasks again.
.LINK
http://mongit201.be.monster.com/chrism/virtech/blob/master/Repo/Wait-mTaskvMotions.ps1
#>
function Wait-mTaskvMotions {
[CmdletBinding()]
Param(
[int] $vMotionLimit=1,
[int] $DelayMinutes=5
)
$NumvMotionTasks = (Get-Task | ? { ($_.PercentComplete -ne 100) -and ( ($_.Description -like '*DRS*') -or ($_.Description -like '*vMotion*') )} | Measure-Object).Count
While ( $NumvMotionTasks -ge $vMotionLimit ) {
Write-Verbose "$(Get-Date)- Waiting $($DelayMinutes) minute(s) before checking again."
Start-Sleep ($DelayMinutes * 60)
$NumvMotionTasks = (Get-Task | ? { ($_.PercentComplete -ne 100) -and ( ($_.Description -like '*DRS*') -or ($_.Description -like '*vMotion*') )} | Measure-Object).Count
}
Write-Verbose "$(Get-Date)- Proceeding."
} # end function
$filepath = "D:\PathtoCSV\filename.csv
$csvobj = import-csv $filepath
foreach ($row in $csvobj) {
$vmobj = get-vm $row.vmname
$ds = get-datastore $row.destds
$vmobj | move-vm -datastore $ds -confirm:$false -runasync
Wait-mTaskvMotions -vMotionLimit 4 # This will keep going through the foreach loop until 4 tasks are registered (vMotion or Storage vMotion), waits 5 minutes between checks. Will only continue to process loop when vMotion tasks are less than 4.
}
Not sure what Im missing, but when I run it, it just opens the .csv file.
I actually added connect-viserver VSERVERNAME to the script and it worked instead of doing it from the powercli prompt first.
Only downside is, its migrating all the VM's and not queuing any up. I was hoping it would just grab the first 4 in the csv file, process them, and when one is done it moves on to the next one.