VMware vSphere/IOPS-Limit per virtueller Disk

From wiki.krogloth.de
Jump to: navigation, search

1 Beschreibung

Das folgende Skript limitiert alle virtuellen Platten einer virtuellen Maschine auf einen gemeinsamen maximalen Wert für IOPS pro Datastore.

Ob hier nun eine Platte alle IOPS macht oder ob es sich auf mehrere Platten verteilt spielt keine Rolle - in Summe ist die VM auf diesem Datastore auf den definierten Wert limitiert.

2 Usage

Um die gesetzen Limits aller VMs auf einem Datastore anzuzeigen:

./limit_vmware_iops list <DATASTORE>

Um die im Skript definierten Limits auf allen VMs auf diesem Datastore zu setzen:

./limit_vmware_iops set <DATASTORE>

3 Code

  1. #!/usr/bin/perl -w
  2.  
  3. use strict;
  4. use warnings;
  5. use 5.010;
  6.  
  7. use FindBin;
  8. use lib "/usr/lib/vmware-vcli/apps";
  9.  
  10. use VMware::VIRuntime;
  11. use AppUtil::HostUtil;
  12. use AppUtil::VMUtil;
  13.  
  14. my %opts = (
  15.    name => {
  16.       type => "=s",
  17.       help => "Name of the Datastore",
  18.       required => 1,
  19.    },
  20.    todo => {
  21.       type => "=s",
  22.       help => "What to do? [list|set]",
  23.       required => 1,
  24.    },
  25. );
  26.  
  27. my @ausnahmen = ("VM-Name-1","VM-Name-2");
  28.  
  29. Opts::add_options(%opts);
  30. Opts::parse();
  31. Opts::validate();
  32.  
  33. my @valid_properties;
  34.  
  35. Util::connect();
  36.  
  37. my $datastores = find_datastores();
  38.  
  39. foreach my $datastore (@$datastores) {
  40.  
  41.     my $vm_views = Vim::get_views( mo_ref_array => $datastore->vm );
  42.     foreach my $vm_view (@$vm_views) {
  43.  
  44.         if ( !( $vm_view->config->template ) ) {
  45.  
  46.             my $vm_entity_view = Vim::find_entity_views( view_type => 'VirtualMachine', filter => { 'name' => $vm_view->name } );
  47.  
  48.             foreach my $vm ( sort { $a->summary->config->name cmp $b->summary->config->name } @$vm_entity_view ) {
  49.  
  50.                 if ( $vm->summary->runtime->connectionState->val eq 'connected' ) {
  51.                     if ( !$vm->config->template ) {
  52.                         my $vmname = $vm->summary->config->name;
  53.                         my $devices = $vm->config->hardware->device;
  54.  
  55.                         my $disk_count = 0;
  56.  
  57.                         foreach my $device (@$devices) {
  58.                            if ( $device->isa('VirtualDisk') ) {
  59.                               my $datastore;
  60.                               my $diskName = $device->backing->fileName;
  61.  
  62.                              if ( $diskName =~ m/\[([^\]]*)\]/ ) {
  63.                                  $datastore = $1;
  64.                               }
  65.  
  66.                               my $datastore_attribute = Opts::get_option('name');
  67.                               if ( defined $datastore && $datastore eq $datastore_attribute ) {
  68.                                  $disk_count++;
  69.                               }
  70.                            }
  71.                         }
  72.  
  73.                         foreach my $device (@$devices) {
  74.  
  75.                             if ( $device->isa('VirtualDisk') ) {
  76.  
  77.  
  78.                                 my $datastore;
  79.                                 my $diskName = $device->backing->fileName;
  80.                                 if ( $diskName =~ m/\[([^\]]*)\]/ ) {
  81.                                     $datastore = $1;
  82.                                 }
  83.  
  84.                                 my $datastore_attribute = Opts::get_option('name');
  85.                                 if ( defined $datastore && $datastore eq $datastore_attribute ) {
  86.  
  87.                                     my $limit;
  88.                                     my $label       = $device->deviceInfo->label;
  89.                                     my $scsiadapter = $device->controllerKey;
  90.                                     $scsiadapter =~ s/100//;
  91.                                     my $scsitarget = $device->unitNumber;
  92.  
  93.                                     my $advOptions = $vm->config->extraConfig;
  94.  
  95.                                   ADVOPTIONS:
  96.                                     foreach my $option ( sort { $a->key cmp $b->key } @$advOptions ) {
  97.                                         if ( $option->key =~ /^sched\.scsi$scsiadapter:$scsitarget\.throughputCap/ ) {
  98.                                             $limit = $option->value;
  99.                                             last ADVOPTIONS;
  100.                                         }
  101.                                         else {
  102.                                             $limit = "off";
  103.                                         }
  104.                                     }
  105.  
  106.                                     if(Opts::get_option('todo') eq "set"){
  107.  
  108.                                        my $iops_limit;
  109.  
  110.                                        given ($datastore) {
  111.                                           when(/^stor1-SAS-\d+$/) { $iops_limit = 2000/$disk_count; }
  112.                                           when(/^stor1-ATA-\d+$/) { $iops_limit = 500/$disk_count; }
  113.                                           default {
  114.                                              print "Unbekannter Datastore";
  115.                                              die;
  116.                                           }
  117.  
  118.                                      }
  119.  
  120.                                        unless ( grep /^$vmname$/, @ausnahmen ) {
  121.                                            if ( $vm && $limit ne $iops_limit ) {
  122.                                                my $vm_config_spec = VirtualMachineConfigSpec->new(
  123.                                                    name        => $vmname,
  124.                                                    extraConfig => [
  125.                                                        OptionValue->new(
  126.                                                            key   => "sched.scsi$scsiadapter:$scsitarget.throughputCap",
  127.                                                            value => $iops_limit
  128.                                                        ),
  129.                                                    ]
  130.                                                );
  131.                                                $vm->ReconfigVM_Task( spec => $vm_config_spec );
  132.                                                 print "IOPS-Limit gesetzt fuer: " . $vmname . "\n";
  133.                                            }
  134.                                        }
  135.                                     }
  136.  
  137.                                     if(Opts::get_option('todo') eq "list"){
  138.  
  139.                                        print "VM: \t" . $vm->name . "\n";
  140.                                        print "Disk: \t" . $diskName . "\n";
  141.                                        print "IOPS-Limit: \t" . $limit . "\n\n";
  142.                                     }
  143.                                 }
  144.                             }
  145.                         }
  146.                     }
  147.                 }
  148.             }
  149.         }
  150.     }
  151. }
  152.  
  153. Util::disconnect();
  154.  
  155. sub find_datastores {
  156.     my $datastore_name = Opts::get_option('name');
  157.     my $dc             = Vim::find_entity_views( view_type => 'Datacenter' );
  158.     my @ds_array       = ();
  159.  
  160.     foreach (@$dc) {
  161.         if ( defined $_->datastore ) {
  162.             @ds_array = ( @ds_array, @{ $_->datastore } );
  163.         }
  164.     }
  165.  
  166.     my $datastores = Vim::get_views( mo_ref_array => \@ds_array );
  167.     @ds_array = ();
  168.     foreach my $ds (@$datastores) {
  169.         my $match_flag = 1;
  170.         if ( $ds->summary->accessible ) {
  171.             if ( $match_flag && $datastore_name ) {
  172.                 if ( $ds->summary->name eq $datastore_name ) {
  173.  
  174.                     # Do Nothing
  175.  
  176.                 }
  177.                 else {
  178.                     $match_flag = 0;
  179.                 }
  180.             }
  181.  
  182.             if ($match_flag) {
  183.                 @ds_array = ( @ds_array, $ds );
  184.             }
  185.         }
  186.     }
  187.  
  188.     return \@ds_array;
  189. }