VMware Cloud Community
AshuC
Contributor
Contributor
Jump to solution

using powercli to control limit disk iops

Hey there, I need to limit the iops of the disks connected to my virtual machines via powercli.

I am  using the following command :

Get-VM 'vm_name' | Get-VMResourceConfiguration | Set-VMResourceconfiguration -configuration DiskResourceConfiguration -DiskLimitIOPerSecond 100

But this gives an error:

Set-VMResourceConfiguration : Cannot bind parameter 'Configuration'. Cannot convert the "DiskResourceConfiguration" value of type "System.String
" to type "VMware.VimAutomation.ViCore.Types.V1.VM.VMResourceConfiguration".
At line:1 char:86
+ Get-VM $vm | Get-VMResourceConfiguration | Set-VMResourceconfiguration -configuration <<<<  DiskResourceConfiguration -DiskLimitIOPerSecond 10
0
    + CategoryInfo          : InvalidArgument: (:) [Set-VMResourceConfiguration], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetVMResourceConfiguration

Can someone please suggest me, where am I going wrong ?

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Try it like this

foreach($group in (Import-Csv C:\vmiopslimit.csv -UseCulture | Group-Object -Property vmName)){
  $vm = Get-VM -Name $group.Name
  $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
  $vm.ExtensionData.Config.Hardware.Device |  where {$_ -is [VMware.Vim.VirtualDisk]} | %{     $dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
    $dev.Operation = "edit"
    $dev.Device = $_
    $label = $_.DeviceInfo.Label
    $dev.Device.StorageIOAllocation.Limit = $group.Group | where {$_.Harddisk -eq $label} | Select -ExpandProperty IOPSLimit
    $spec.DeviceChange += $dev
  }  
$vm.ExtensionData.ReconfigVM_Task($spec) }

The CSV file should look like this

"vmName","harddisk","IOPSLimit"
"VM1","Hard disk 1","50"
"VM1","Hard disk 2","75"

"VM2","Hard disk 1","75"

"VM3","Hard disk 1","35"
"VM3","Hard disk 2","55"

"VM3","Hard disk 3","65"


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

View solution in original post

0 Kudos
21 Replies
LucD
Leadership
Leadership
Jump to solution

You pass the VMResourceConfiguration through the pipeline from the Get-VMResourceConfiguration

Just do

Get-VM 'vm_name' | Get-VMResourceConfiguration |  Set-VMResourceconfiguration -DiskLimitIOPerSecond 100



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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

Hey LucD thanks a lot for your reply. But when I type the command suggested by you :

I am getting the output as

VM                   NumCpuShares    CpuSharesLevel  NumMemShares    MemShares
                                                                     evel
--                   ------------    --------------  ------------    ---------
Vm_name            16000           Normal          163840          Normal

but its not limiting the iops of the disk.

I am getting the same output if I just type the command :

Get-VM vm_name | Get-VMResourceConfiguration

Can you plaese tell me why its not reading the second pipeline argument. Also if I have more than one disk connected to VM can I specify  diffrent iops for each of them.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The Set-VMResourceConfiguration cmdlet returns indeed the same object as the Get-VMResourceConfiguration cmdlet.

But the difference is that the Set- cmdlet will display the updated values, as you specified them on the Set-VMResourceConfiguration cmdlet.

Is that VM powered off ?

Some of the resource changes only take effect after a poweroff/poweron. See KB1038241.


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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

Thanx again for the reply!!

Yes my Virtual machine is powered off and after executing the command when I try to check the update manually in GUI I dont see the new values there.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Just checked again, and there seems to be indeed a problem with the DiskLimitIOPerSecond parameter :smileycry:

Try it like this

$vmName = "MyVM" 
$DiskLimitIOPerSecond
= 50
# $DiskLimitIOPerSecond = -1 # Unlimited
$vm = Get-VM -Name $vmName $spec = New-Object VMware.Vim.VirtualMachineConfigSpec $vm.ExtensionData.Config.Hardware.Device |
where {$_ -is [VMware.Vim.VirtualDisk]} | %{   $dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
  $dev.Operation = "edit"
  $dev.Device = $_
 
$dev.Device.StorageIOAllocation.Limit = $DiskLimitIOPerSecond
 
$spec.DeviceChange += $dev
}
$vm.ExtensionData.ReconfigVM_Task($spec)

Note: to set the limit back to unlimited, you have to give the value -1


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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

Thanks a ton LucD this works perfectly fine Smiley Happy .

However this works only for the virtual disk connected to the VM but I also have a large number of raw devices(LUN's)  mapped to my VM. Is it possible to control the IOPS on each of them ?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Strange, when the RDM is connected to a VM as a harddisk it works as well.

How are these RDM connected ?


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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

I am not sure if I have understood your question correctly. If not then I am sorry and request you to be more specific.

Following is the table shown during the connectivity of a new RDM :

Hardware type: HardDisk

create disk: Use mapped system LUN

Virtual Device Node: SCSI(0:2)

Disk mode: Persistent

Target LUN: Fibre channel Disk(naa.60...)

compatiblity moded: physical

mapped datastore: Store with VM

0 Kudos
LucD
Leadership
Leadership
Jump to solution

No, that is what I wanted to know.

The RDM is connected as a virtualdisk.

And the above code doesn't change the IOPS limit for that harddisk ?

Are there any errors in the vSphere client ?


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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

okay I checked it again and it works fine Smiley Happy.

But it changes the iops only for single RDM connected to the virtual machine. Can you suggest me the modifications I should perform in order to limit the iops of all the RDM's connected to my VM.

Also can i specify diffrent IOPS limit for diffrent RDM's connected to a single VM.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

It should change the IOPS limit for all harddisks connected to a VM.

Tested again, and that seems to work for me.

And yes, you can have different IOPS limits for different harddisks.

You could test on the harddisk label ("Hard disk n") in the DeviceInfo.Label property, and based on that specify different limits.


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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

Strange because in my case it just modifies the IOPS for first hard disk Smiley Sad .

As I am not much familiar with the power cli commands I request you to please provide me with a code which can assign diffrent iops to the RDM's of a single VM( I tried it myself but got no sucess )

Sorry if I am asking too much but your support will be a great help to me .

0 Kudos
LucD
Leadership
Leadership
Jump to solution

First another question, how do you intend to provide that information to the script ?

In a CSV file ?


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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

Yes,I will be providing values to the script via csv file which will have the hard disk name and the limit of IOPS.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try it like this

foreach($group in (Import-Csv C:\vmiopslimit.csv -UseCulture | Group-Object -Property vmName)){
  $vm = Get-VM -Name $group.Name
  $spec = New-Object VMware.Vim.VirtualMachineConfigSpec
  $vm.ExtensionData.Config.Hardware.Device |  where {$_ -is [VMware.Vim.VirtualDisk]} | %{     $dev = New-Object VMware.Vim.VirtualDeviceConfigSpec
    $dev.Operation = "edit"
    $dev.Device = $_
    $label = $_.DeviceInfo.Label
    $dev.Device.StorageIOAllocation.Limit = $group.Group | where {$_.Harddisk -eq $label} | Select -ExpandProperty IOPSLimit
    $spec.DeviceChange += $dev
  }  
$vm.ExtensionData.ReconfigVM_Task($spec) }

The CSV file should look like this

"vmName","harddisk","IOPSLimit"
"VM1","Hard disk 1","50"
"VM1","Hard disk 2","75"

"VM2","Hard disk 1","75"

"VM3","Hard disk 1","35"
"VM3","Hard disk 2","55"

"VM3","Hard disk 3","65"


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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

Hey LucD, it works perfectly :smileygrin:.

Thanks a lot for the great help. you ROCK !!

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

Hey LucD,

Thanks again for the great help, I have been working on this script from quite some time and it has really helped me with my project.

However, I have one more request. As of now when I execute this script it takes initial 10- 15 seconds to from connection with the server and once the connection is formed it takes almost 1second per VM to get reconfigured, moreover it is done in sequential manner.

Currently in my environment I have around 100 VM, hence it takes around 100 seconds for the task to get finish. Is there any way by which i can execute all this in parallel mode and it should take comparatively less time to reconfigure all.

I need this because I have a seprate set of code which start the benchmarking software on these VM's.  The script provided by you and my code  works in parallel.

FYI** my server is of very high configuration, so I am sure that this problem is not due to slow hardware

Any kind of  suggestion will be really helpful to me.

Best Regards,

Ashish

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The script calls the  ReconfigVM_Task method.

Each SDK method is mapped to 2 entry points in PowerCLI, the method with a _Task suffix and without that suffix.

If you call the method with _Task suffix it will return immediatly, the entry point without the suffix will wait till the task is complete.

So in fact, the script above should already be launching these calls without waiting for the completion.

Perhaps you are hitting a vSphere limitation on the numbers of tasks that can be running in parallel.

How many of these tasks do you see running in parallel, if any ?


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

0 Kudos
AshuC
Contributor
Contributor
Jump to solution

Hey thanks for your response,

With this I am attaching the event list for first 16 VM's. As you can see the new request start time is always after the end request of the previous one. Also the difference between the starting time of 1st VM and completion time of last VM is 9 seconds.

Moreover as you mentioned regarding task limit, I have one more doubt. As i said  in my previous post that  I execute 2 sperate scripts in parallel:

1. to control IOPS on each RDM connected to VM (using POWERCLI)

2. to start benchmarking application (FIO) on these VM ( using VMRUN)

I am running both these scripts in a LOOP, such  that after every 5 minutes they execute a new set of instructions. What's happening is,  for initial few hours( around 6 hours) everything works perfectly. But after that either VM becomes very slow in response to both the request or second script(to start FIO) is totally stopped. However, if I restart the VM's, everything is fine again

Until now I have no valid solution for this kind of behavior, it will be really great if you can suggest something regarding this too.

I hope I was clear enough in specifying my problem, if not then i request you to let me know, will try to elaborate.

Best Regards,

Ashish

0 Kudos