Monitor the CPU Performance Counters for a time period

exlistcpucntperf.pl

Copyright © 2008 VMware, Inc. All rights reserved.

#!/usr/bin/perl -w
#
# Copyright 2008 VMware, Inc.  All rights reserved.
#
#######################################################################################
# DISCLAIMER. THIS SCRIPT IS PROVIDED TO YOU "AS IS" WITHOUT WARRANTIES OR CONDITIONS 
# OF ANY KIND, WHETHER ORAL OR WRITTEN, EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY 
# DISCLAIMS ANY IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY 
# QUALITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. 
#######################################################################################

use strict;
use warnings;
use VMware::VIRuntime;
use VMware::VIM2Runtime;
use VMware::VILib;
use Data::Dumper;
use Switch;
use Time::Local;

sub get_date_range;
sub get_perf_interval;
sub init_perf_counter_info;
sub filter_metric_ids;

#######################################################################################
#
#   exlistcpucntperf.pl
#	Example script to retrieve all cpu counters for all instances of CPU
#	Parameters:
#		-- countertype  Name of template virtual machine
#		-- date			Name of virtual machine to be created
#		-- entity		ManagedEntity type [VirtualMachine | HostSystem]  Only HostSystem and VirtualMachine entity types are currently supported.
#		-- name			Name of the host/virtual machine if entity is specified.
#		-- freq     	Frequency [daily | weekly | monthly] for which you want data

# This script works with VMware VirtualCenter 2.0 or later.

# This script works with VMware ESX Server 3.0 or later

#######################################################################################


my %opts = (
 	countertype => {
   		type => "=s",
      	help => "Counter type [cpu] \n      If nothing is specified, the utilization report will include all the counter types.",
      	required => 0,
	},
	date => {
   		type => "=s",
      	help => "Date in yyyy-mm-dd format\n      If no date is provided, the current date is assumed.",
      	required => 0,
   },
   entity => {
        type => "=s",
        help => "Specify ManagedEntity type [VirtualMachine | HostSystem]\n      Only HostSystem and VirtualMachine entity types are currently supported.",         
		default => 'HostSystem',
		required => 0,
    },
 	freq => {
   		type => "=s",
      	help => "Frequency [daily | weekly | monthly]\n      The start date for the report will be computed from the frequency.\n      If the frequency is daily, the start date will be one day less the 'date' value specified.\n      For weekly frequencies, the start date will be seven days less the 'date' value specified. ",
      	required => 0,
 	},
	name => {
   		type => "=s",
      	help => "Name of the host/virtual machine\n      If name is not specified, the utilization report will contain all host/vm data",
      	required => 0,
   },

);

Opts::add_options(%opts);

# Parse connection options and connect to the server
Opts::parse();
Opts::validate();

#Connect to the host or vc server
Util::connect();

my $perfmgr_view;
my $all_counters;
my $cpu_counters;
my $st_date;
my $end_date;
my $entity_type = Opts::get_option('entity');
my $counter_type = Opts::get_option('countertype');
my $frequency = Opts::get_option('freq');
my $name = Opts::get_option('name');
$end_date = Opts::get_option('date');

#Get date range on frequency and end_date
($st_date,$end_date) = get_date_range($frequency, $end_date);
print "Start date : $st_date \n";
print "End date : $end_date \n";
$end_date = $end_date."T00:00:00"; #-00:00";
$st_date = $st_date."T00:00:00"; #-00:00";

if(!defined ($counter_type))
{
	$counter_type='all'
}
my $entity_views;


#######################################################################################
#	Find all/specified virtual machine
#######################################################################################
if(defined $name)
{
	 $entity_views = Vim::find_entity_views(view_type => $entity_type, filter =>{'name' => $name});
}
else
{
	$entity_views = Vim::find_entity_views(view_type => $entity_type);
}

print "--------------------------------\n";
print "\nEntity Type : " .$entity_type ."\n";
print "--------------------------------\n\n";

init_perf_counter_info();

#Loop on the vms
foreach my $entity (sort {$a->name cmp $b->name} @$entity_views)
{
	#check if the vm is on to collect stats
	if($entity_type eq 'VirtualMachine' && $entity->runtime->powerState->val eq 'poweredOff')
	{
		print "\n------------------------------------------------------------\n";
		print "'" . $entity->name . "' is powered off. No stats available\n\n";
		print "------------------------------------------------------------\n\n";
		next;
	}
	my $perf_metric_ids = filter_metric_ids($counter_type,$perfmgr_view->QueryAvailablePerfMetric(entity => $entity));
	
	# performance data for the smallest interval in csv format
	my $interval = get_perf_interval($entity); 
    my $samples = 1;

	# Create performancequeryspec 
	my $perf_query_spec = PerfQuerySpec->new(entity => $entity,
                                                 metricId => $perf_metric_ids,
                                         	     format => 'csv',
                                                 maxSample => $samples,
                                                 intervalId => $interval
						);

	# get performance data
	my $perf_data = $perfmgr_view->QueryPerf(querySpec => $perf_query_spec);
	
	if(!defined ($perf_data) || !@$perf_data)
	{
		print "\n------------------------------------------------------------\n";
		print "'" . $entity->name . "' has no stats available for the given date range. Try different dates\n\n" ;
		print "------------------------------------------------------------\n\n";
		next;
	}
	foreach (@$perf_data) 
	{
		print "\n------------------------------------------------------------\n";
   	print "'" . $entity->name . "'\n";
		print "------------------------------------------------------------\n";
   	
	my $time_stamps = $_->sampleInfoCSV;
        print "$time_stamps \n";
   	
	my $values = $_->value;
        my @instlist;
		my @winstlist;
		my $counter = 0;
   	foreach (@$values) 
		{
                         my $id = $_->id->counterId;
                         my $instance = $_->id->instance;
                         my $val = $_->value;                             
                         if($_->id->instance ne ''){
						   my $rec = [ $id, $val ];
						   if( exists $instlist[$instance] ){
	             	           my $metriclist;
                               $metriclist = $instlist[$instance];
                               push @$metriclist, $rec;
                               $instlist[$instance] = $metriclist;
                           }else{
	             	         my @metriclist;
                     	     push @metriclist, $rec;
                    	     $instlist[$instance] = \@metriclist;
                           }  
                         }
						 else {
							 my $rec = [ $id, $val ];
							 $winstlist[$counter] = $rec;
							 $counter = $counter + 1;
						 }
   		}

#Print available counters for each instance of cpu

   print "\n\nInstance values for all the CPU instances\n";
   my $count=1;
   foreach(@instlist){
 		print "Instance : cpu$count\n";
 		$count += 1;
   		foreach(sort @$_){
   			my $counter = $all_counters->{@$_[0]};
   			print @$_[0]." ".$counter->nameInfo->label . " : ".@$_[1]."\n";
   	    }
    }
    print "\n\nAggregated statistics value for all the CPU instances\n";
    foreach(@winstlist){   
		my $counter = $all_counters->{$_->[0]};
   		print $_->[0]." ".$counter->nameInfo->label . " : ".$_->[1]."\n";	    
	}
	print "------------------------------------------------------------\n\n";
	}
}

# Date range process
#===================
sub get_date_range
{
	my ($freq,$end_date) = @_;
	my $st_date;
	my ($sec,$min,$hour,$day,$month,$year,$wday,$yday,$isdst);
	if(!defined ($freq))
	{
		$freq = "daily";
	}
	if (!defined($end_date))
	{
		($sec,$min,$hour,$day,$month,$year) = localtime(time);
		$year = 1900+$year;
		$month = $month+1;
		if($month<10) { $month = "0" . $month; } 
		if($day<10) { $day = "0" . $day; }
		$end_date = $year . "-" . $month . "-" . $day ; 
	}
	($year,$month,$day)= split(/-/,$end_date);
	my $end_time = timelocal(0,0,0,$day,$month-1,$year-1900);
	my $st_time;
	switch ($freq)
	{
		case "daily"	{ $st_time = $end_time - 86400; }
		case "weekly"	{ $st_time = $end_time - (7*86400); }
		case "monthly"	{ $st_time = $end_time - (30*86400); }
		else 				{ $st_time = $end_time - 86400; }
	}	
	($sec,$min,$hour,$day,$month,$year,$wday,$yday,$isdst)=localtime($st_time);
	$year = 1900+$year;
	$month = $month+1;
	if($month<10) { $month = "0" . $month; } 
	if($day<10) { $day = "0" . $day; }
	$st_date = $year . "-" . $month . "-" . $day ; 
	return ($st_date,$end_date);
}

sub get_perf_interval
{
   my $entity = shift;
   my $provider_summary = $perfmgr_view->QueryPerfProviderSummary(entity => $entity);
   my $interval = $provider_summary->refreshRate;
	print "Refresh rate interval : $interval \n";
	return $interval;
}

		
sub init_perf_counter_info 
{
   $perfmgr_view = Vim::get_view(mo_ref => Vim::get_service_content()->perfManager);
   my $perfCounterInfo = $perfmgr_view->perfCounter;
   foreach (@$perfCounterInfo) 
   {
      	my $key = $_->key;
      	my $group_info = $_->groupInfo;
		my $name_info = $_->nameInfo;
      	if ($group_info->key eq 'cpu') 
		{
         	$cpu_counters->{ $key } = $_;
      		$all_counters->{ $key } = $_;
	        print $key . " : " . $name_info->label . "\n  ";
      	} 
   }
}

sub filter_metric_ids 
{
   my ($type, $perf_metric_ids) = @_;
   if (! $all_counters) 
	{
      init();
   }
   my $counters;
   if ($type eq 'cpu') 
   {
      $counters = $cpu_counters;
   }
	else 
	{
      $counters = $all_counters;
   }
   my @filtered_list;
   foreach (@$perf_metric_ids) 
   {      
      if (exists $counters->{$_->counterId}) 
      {
		push @filtered_list, $_;
      }
   }
   return \@filtered_list;
}


# logout
Util::disconnect();

The sample code is provided "AS-IS" for use, modification, and redistribution in source and binary forms, provided that the copyright notice and this following list of conditions are retained and/or reproduced in your distribution. To the maximum extent permitted by law, VMware, Inc., its subsidiaries and affiliates hereby disclaim all express, implied and/or statutory warranties, including duties or conditions of merchantability, fitness for a particular purpose, and non-infringement of intellectual property rights. IN NO EVENT WILL VMWARE, ITS SUBSIDIARIES OR AFFILIATES BE LIABLE TO ANY OTHER PARTY FOR THE COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT, INDIRECT, OR SPECIAL DAMAGES, ARISING OUT OF THIS OR ANY OTHER AGREEMENT RELATING TO THE SAMPLE CODE.

You agree to defend, indemnify and hold harmless VMware, and any of its directors, officers, employees, agents, affiliates, or subsidiaries from and against all losses, damages, costs and liabilities arising from your use, modification and distribution of the sample code.

VMware does not certify or endorse your use of the sample code, nor is any support or other service provided in connection with the sample code.