#!/usr/bin/perl -w

use strict;
use warnings;
use vars qw($PROGNAME $VERSION $output $values $result);
use Nagios::Plugin;
use File::Basename;
my $perl_module_instructions="
Download the latest version of Perl Toolkit from VMware support page. 
In this example we use VMware-VIPerl-1.6.0-104313.i386.tar.gz, 
but the instructions should apply to newer versions as well.
  
Upload the file to your op5 Monitor server's /root dir and execute:

    cd /root
    tar xvzf VMware-VIPerl-1.6.0-104313.i386.tar.gz 
    cd vmware-viperl-distrib/
    ./vmware-install.pl
  
Follow the on screen instructions, described below:

  \"Creating a new VMware VIPerl Toolkit installer database using the tar4 format.
  Installing VMware VIPerl Toolkit.
  You must read and accept the VMware VIPerl Toolkit End User License Agreement to continue.
  Press enter to display it.\" 
  
    <ENTER>

  \"Read through the License Agreement\" 
  \"Do you accept? (yes/no) 
  
    yes

  \"In which directory do you want to install the executable files? [/usr/bin]\"

    <ENTER>

  \"The following Perl modules were found on the system but may be too old to work
  with VIPerl:
  
  Crypt::SSLeay
  Compress::Zlib
  
  The installation of VMware VIPerl Toolkit 1.6.0 build-104313 for Linux
  completed successfully. You can decide to remove this software from your system
  at any time by invoking the following command:
  \"/usr/bin/vmware-uninstall-viperl.pl\".
  
  Enjoy,
  
  --the VMware team\"

Note: \"Crypt::SSLeay\" and \"Compress::Zlib\" are not needed for check_esx3 to work.  
";


eval { 
	require VMware::VIRuntime
} or Nagios::Plugin::Functions::nagios_exit('UNKNOWN', "Missing perl module VMware::VIRuntime. Download and install \'VMware Infrastructure (VI) Perl Toolkit\', available at http://www.vmware.com/download/sdk/\n $perl_module_instructions");

$PROGNAME = basename($0);
$VERSION = '0.1.0';

my $np = Nagios::Plugin->new(
  usage => "Usage: %s -D <data_center> | -H <host_name> | -N <vm_name> [ -t <timeout> ]\n"
    . "    -u <user> -p <pass>  [ -w <warn_range> ] [ -c <crit_range> ]\n"
    . "    [ -l <command> ] [ -s <subcommand> ]\n"
    . '    [ -V ] [ -v ] [ -h ]',
  version => $VERSION,
  plugin  => $PROGNAME,
  shortname => uc($PROGNAME),
  blurb => 'VMWare Infrastructure plugin',
  extra   => "Supported commands(^ means blank or not specified parameter) :\n"
    . "    Host specific :\n"
    . "        * cpu - shows cpu info\n"
    . "            + usage - CPU usage in percentage\n"
    . "            + usagemhz - CPU usage in MHz\n"
    . "            ^ all cpu info\n"
    . "        * mem - shows mem info\n"
    . "            + usage - mem usage in percentage\n"
    . "            + usagemb - mem usage in MB\n"
    . "            + swap - swap mem usage in MB\n"
    . "            + overhead - additional mem used by VM Server in MB\n"
    . "            + overall - overall mem used by VM Server in MB\n"
    . "            ^ all mem info\n"
    . "        * net - shows net info\n"
    . "            + usage - overall network usage in KB/s \n"
    . "            + receive - receive in KB/s \n"
    . "            + send - send in KB/s \n"
    . "            ^ all net info\n"
    . "        * io - shows disk io info\n"
    . "            + aborted - aborted commands count\n"
    . "            + resets - bus resets count\n"
    . "            + read - read latency in ms\n"
    . "            + write - write latency in ms\n"
    . "            + kernel - kernel latency in ms\n"
    . "            + device - device latency in ms\n"
    . "            + queue - queue latency in ms\n"
    . "            ^ all disk io info\n"
    . "        * vmfs - shows Datastore info\n"
    . "            + (name) - info for datastore with name (name)\n"
    . "            ^ all datastore info\n"
    . "        * runtime - shows runtime info\n"
    . "            + con - connection state\n"
    . "            + maintenance - shows whether host is in maintenance mode\n"
    . "            + list - list of VMWare machines and their statuses\n"
    . "            + status - overall host status (gray/green/red/yellow)\n"
    . "            + issues - all issues for the host\n"
    . "            ^ connection state, maintance status, overall status, issues and working vm count info\n"
    . "    VM specific :\n"
    . "        * cpu - shows cpu info\n"
    . "            + usage - CPU usage in percentage\n"
    . "            + usagemhz - CPU usage in MHz\n"
    . "            + wait - CPU wait in ms\n"
    . "            ^ all cpu info\n"
    . "        * mem - shows mem info\n"
    . "            + usage - mem usage in percentage\n"
    . "            + usagemb - mem usage in MB\n"
    . "            + swap - swap mem usage in MB\n"
    . "            + swapin - swapin mem usage in MB\n"
    . "            + swapout - swapout mem usage in MB\n"
    . "            + active - active mem usage in MB\n"
    . "            + overhead - additional mem used by VM Server in MB\n"
    . "            + overall - overall mem used by VM Server in MB\n"
    . "            ^ all mem info\n"
    . "        * net - shows net info\n"
    . "            + usage - overall network usage in KB/s \n"
    . "            + receive - receive in KB/s \n"
    . "            + send - send in KB/s \n"
    . "            ^ all net info\n"
    . "        * io - shows disk I/O info\n"
    . "            + usage - overall disk usage in MB/s\n"
    . "            + read - amount of data read in MB/s\n"
    . "            + write - amount of data written in MB/s\n"
    . "            ^ all disk io info\n"
    . "        * runtime - shows runtime info\n"
    . "            + con - connection state\n"
    . "            + cpu - allocated CPU in MHz\n"
    . "            + mem - allocated mem in MB\n"
    . "            + status - overall host status (gray/green/red/yellow)\n"
    . "            + state - virtual machine state (UP, DOWN, SUSPENDED)\n"
    . "            + issues - all issues for the host\n"
    . "            + connections - console connections to VM\n"
    . "            + guest - guest OS status, needs VMware Tools\n"
    . "            + tools - VMWare Tools status\n"
    . "            ^ all runtime info\n"
    . "\n\nCopyright (c) 2008 op5",
  timeout => 30,
);

$np->add_arg(
  spec => 'host|H=s',
  help => "-H, --host=<hostname>\n"
    . '   ESX or ESXi hostname.',
  required => 0,
);

$np->add_arg(
  spec => 'datacenter|D=s',
  help => "-D, --datacenter=<DCname>\n"
    . '   Datacenter hostname.',
  required => 0,
);

$np->add_arg(
  spec => 'name|N=s',
  help => "-N, --name=<vmname>\n"
    . '   Virtual machine name.',
  required => 0,
);

$np->add_arg(
  spec => 'username|u=s',
  help => "-u, --username=<username>\n"
    . '   Username to connect with.',
  required => 1,
);

$np->add_arg(
  spec => 'password|p=s',
  help => "-p, --password=<password>\n"
    . '   Password to use with the username.',
  required => 1,
);

$np->add_arg(
  spec => 'warning|w=s',
  help => "-w, --warning=THRESHOLD\n"
    . "   Warning threshold. See\n"
    . "   http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT\n"
    . '   for the threshold format.',
  required => 0,
);

$np->add_arg(
  spec => 'critical|c=s',
  help => "-c, --critical=THRESHOLD\n"
    . "   Critical threshold. See\n"
    . "   http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT\n"
    . '   for the threshold format.',
  required => 0,
);

$np->add_arg(
  spec => 'command|l=s',
  help => "-l, --command=COMMAND\n"
    . '   Specify command type (CPU, MEM, NET, IO, VMFS, RUNTIME, ...)\n',
  required => 1,
);

$np->add_arg(
  spec => 'subcommand|s=s',
  help => "-s, --subcommand=SUBCOMMAND\n"
    . '   Specify subcommand\n',
  required => 0,
);

$np->getopts;

my $host = $np->opts->host;
my $datacenter = $np->opts->datacenter;
my $vmname = $np->opts->name;
my $username = $np->opts->username;
my $password = $np->opts->password;
my $warning = $np->opts->warning;
my $critical = $np->opts->critical;
my $command = $np->opts->command;
my $subcommand = $np->opts->subcommand;
$output = "Unknown ERROR!";
$result = 'CRITICAL';

if (defined($subcommand))
{
	$subcommand = undef if ($subcommand eq '');
}

if (defined($critical))
{
	$critical = undef if ($critical eq '');
}

if (defined($warning))
{
	$warning = undef if ($warning eq '');
}

$np->set_thresholds(critical => $critical, warning => $warning);

if (defined($datacenter))
{
	$datacenter = "https://" . $datacenter . "/sdk/webService";
	eval
	{
		Util::connect($datacenter, $username, $password);
	};

	$np->nagios_exit('CRITICAL', $@) if ($@);

	if (defined($host))
	{
		if (defined($vmname))
		{
			$output = "DATACENTER-HOST-VM";
			$result = 'UNKNOWN';
		}
		else
		{
			$output = "DATACENTER-HOST";
			$result = 'UNKNOWN';
		}
	}
	else
	{
		if (defined($vmname))
		{
			$output = "DATACENTER-VM";
			$result = 'UNKNOWN';
		}
		else
		{
			$output = "DATACENTER";
			$result = 'UNKNOWN';
		}
	}
}
elsif (defined($host))
{
	$host = "https://" . $np->opts->host . "/sdk/webService";
	eval
	{
		Util::connect($host, $username, $password);
	};

	$np->nagios_exit('CRITICAL', $@) if ($@);

	if (defined($vmname))
	{
		if ($command =~ /^CPU$/i)
		{
			($result, $output) = vm_cpu_info($vmname, $np, $subcommand);
		}
		elsif ($command =~ /^MEM$/i)
		{
			($result, $output) = vm_mem_info($vmname, $np, $subcommand);
		}
		elsif ($command =~ /^NET$/i)
		{
			($result, $output) = vm_net_info($vmname, $np, $subcommand);
		}
		elsif ($command =~ /^IO$/i)
		{
			($result, $output) = vm_disk_io_info($vmname, $np, $subcommand);
		}
		elsif ($command =~ /^RUNTIME$/i)
		{
			($result, $output) = vm_runtime_info($vmname, $np, $subcommand);
		}
		else
		{
			$output = "Unknown HOST-VM command\n" . $np->opts->_help;
			$result = 'CRITICAL';
		}
	}
	else
	{
		if ($command =~ /^CPU$/i)
		{
			($result, $output) = host_cpu_info($np, $subcommand);
		}
		elsif ($command =~ /^MEM$/i)
		{
			($result, $output) = host_mem_info($np, $subcommand);
		}
		elsif ($command =~ /^NET$/i)
		{
			($result, $output) = host_net_info($np, $subcommand);
		}
		elsif ($command =~ /^IO$/i)
		{
			($result, $output) = host_disk_io_info($np, $subcommand);
		}
		elsif ($command =~ /^VMFS$/i)
		{
			($result, $output) = host_list_vm_volumes_info($np, $subcommand);
		}
		elsif ($command =~ /^RUNTIME$/i)
		{
			($result, $output) = host_runtime_info($np, $subcommand);
		}
		else
		{
			$output = "Unknown HOST command\n" . $np->opts->_help;
			$result = 'CRITICAL';
		}
	}
}
else
{
	$np->nagios_exit('ERROR', 'Incorrect arguments');
}

Util::disconnect();
$np->nagios_exit($result, $output);

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

sub get_key_metrices {
	my ($perfmgr_view, $group, @names) = @_;

	my $perfCounterInfo = $perfmgr_view->perfCounter;
	my @counters;

	foreach (@$perfCounterInfo) {
		if ($_->groupInfo->key eq $group) {
			my $cur_name = $_->nameInfo->key . "." . $_->rollupType->val;
			foreach my $index (0..@names-1)
			{
				if ($names[$index] =~ /$cur_name/)
				{
					$names[$index] =~ /(\w+).(\w+):*(.*)/;
					$counters[$index] = PerfMetricId->new(counterId => $_->key, instance => $3);
				}
			}
		}
	}

	return \@counters;
}

sub generic_performance_values {
	my ($view, $group, @list) = @_;
	my $counter = 0;
	my @values;
	eval
	{
		my $perfMgr = Vim::get_view(mo_ref => Vim::get_service_content()->perfManager);
		my $metrices = get_key_metrices($perfMgr, $group, @list);

		my $perf_query_spec = PerfQuerySpec->new(entity => $view, metricId => $metrices, format => 'csv', intervalId => 20, maxSample => 1);
		my $perf_data = $perfMgr->QueryPerf(querySpec => $perf_query_spec);
		my $unsorted = shift(@$perf_data)->value;

		foreach my $id (@$unsorted)
		{
			foreach my $index (0..@$metrices-1)
			{
				if ($id->id->counterId == $$metrices[$index]->counterId)
				{
					$counter++ if (!defined($values[$index]));
					$values[$index] = $id;
				}
			}
		}
		
	};
	return undef if ($@ || $counter != @list);
	return \@values;
}

sub return_host_performance_values {
	my $values;

	eval
	{
		my $host_view = Vim::find_entity_view(view_type => 'HostSystem');
		$host_view->update_view_data();
		$values = generic_performance_values($host_view, @_);
	};

	return undef if ($@);
	return $values;
}

sub return_host_vmware_performance_values {
	my $values;

	eval
	{
		my $vmname = shift(@_);
		my $vm_view = Vim::find_entity_view(view_type => 'VirtualMachine', filter => {name => $vmname});
		die "VMware machine \"" . $vmname . "\" does not exist.\n" if (!defined($vm_view));
		die "VMware machine \"" . $vmname . "\" is not running. Current state is \"" . $vm_view->runtime->powerState->val . "\".\n" if ($vm_view->runtime->powerState->val ne "poweredOn");
		$vm_view->update_view_data();
		$values = generic_performance_values($vm_view, @_);
	};
	return $@ if ($@);
	return $values;
}

sub return_dc_vmware_performance_values {
	my ($host) = shift(@_);
	my ($vm_name) = shift(@_);
	my $values;

	eval
	{
		my $host_view = Vim::find_entity_view(view_type => 'HostSystem', filter => {name => $host});

		foreach (@$host_view->vm)
		{
			my $vm_view = Vim::get_view(mo_ref => $_);
			$vm_view->update_view_data();
			if ($vm_view->name eq $vm_name)
			{
				$values = generic_performance_values($vm_view, @_);
				return;
			}
		}
	};

	return undef if ($@);
	return $values;
}

sub simplify_number
{
	my ($number, $cnt) = @_;
	$cnt = 2 if (!defined($cnt));
	return sprintf("%.${cnt}f", "$number");
}

sub convert_number
{
	my ($number) = shift(@_);
	$number =~ s/\,/\./;
	return $number;
}

#=====================================================================| HOST |============================================================================#

sub host_cpu_info
{
	my ($np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST CPU Unknown error';
	
	if (defined($subcommand))
	{
		if ($subcommand =~ /^USAGE$/i)
		{
			$values = return_host_performance_values('cpu', ('usage.average'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value) * 0.01);
				$np->add_perfdata(label => "cpu_usage", value => $value, uom => '%', threshold => $np->threshold);
				$output = "cpu usage=" . $value . " %"; 
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^USAGEMHZ$/i)
		{
			$values = return_host_performance_values('cpu', ('usagemhz.average'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value));
				$np->add_perfdata(label => "cpu_usagemhz", value => $value, uom => 'Mhz', threshold => $np->threshold);
				$output = "cpu usagemhz=" . $value . " MHz";
				$res = $np->check_threshold(check => $value);
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST CPU - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		$values = return_host_performance_values('cpu', ('usagemhz.average', 'usage.average'));
		if (defined($values))
		{
			my $value1 = simplify_number(convert_number($$values[0]->value));
			my $value2 = simplify_number(convert_number($$values[1]->value) * 0.01);
			$np->add_perfdata(label => "cpu_usagemhz", value => $value1, uom => 'Mhz', threshold => $np->threshold);
			$np->add_perfdata(label => "cpu_usage", value => $value2, uom => '%', threshold => $np->threshold);
			$res = 'OK';
			$output = "cpu usage=" . $value1 . " MHz(" . $value2 . "%)";
		}
	}

	return ($res, $output);
}

sub host_mem_info
{
	my ($np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST MEM Unknown error';
	
	if (defined($subcommand))
	{
		if ($subcommand =~ /^USAGE$/i)
		{
			$values = return_host_performance_values('mem', ('usage.average'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value) * 0.01);
				$np->add_perfdata(label => "mem_usage", value => $value, uom => '%', threshold => $np->threshold);
				$output = "nem usage=" . $value . " %"; 
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^USAGEMB$/i)
		{
			$values = return_host_performance_values('mem', ('consumed.average'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value) / 1024);
				$np->add_perfdata(label => "mem_usagemb", value => $value, uom => 'MB', threshold => $np->threshold);
				$output = "mem usage=" . $value . " MB";
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^SWAP$/i)
		{
			$values = return_host_performance_values('mem', ('swapused.average'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value) / 1024);
				$np->add_perfdata(label => "mem_swap", value => $value, uom => 'MB', threshold => $np->threshold);
				$output = "swap usage=" . $value . " MB";
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^OVERHEAD$/i)
		{
			$values = return_host_performance_values('mem', ('overhead.average'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value) / 1024);
				$np->add_perfdata(label => "mem_overhead", value => $value, uom => 'MB', threshold => $np->threshold);
				$output = "overhead=" . $value . " MB";
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^OVERALL$/i)
		{
			$values = return_host_performance_values('mem', ('consumed.average', 'overhead.average'));
			if (defined($values))
			{
				my $value = simplify_number((convert_number($$values[0]->value) + convert_number($$values[1]->value)) / 1024);
				$np->add_perfdata(label => "mem_overhead", value =>  $value, uom => 'MB', threshold => $np->threshold);
				$output = "overall=" . $value . " MB";
				$res = $np->check_threshold(check => $value);
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST MEM - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		$values = return_host_performance_values('mem', ('consumed.average', 'usage.average', 'overhead.average', 'swapused.average'));
		if (defined($values))
		{
			my $value1 = simplify_number(convert_number($$values[0]->value) / 1024);
			my $value2 = simplify_number(convert_number($$values[1]->value) * 0.01);
			my $value3 = simplify_number(convert_number($$values[2]->value) / 1024);
			my $value4 = simplify_number(convert_number($$values[3]->value) / 1024);
			$np->add_perfdata(label => "mem_usagemb", value => $value1, uom => 'MB', threshold => $np->threshold);
			$np->add_perfdata(label => "mem_usage", value => $value2, uom => '%', threshold => $np->threshold);
			$np->add_perfdata(label => "mem_overhead", value => $value3, uom => 'MB', threshold => $np->threshold);
			$np->add_perfdata(label => "mem_swap", value => $value4, uom => 'MB', threshold => $np->threshold);
			$res = 'OK';
			$output = "mem usage=" . $value1 . " MB(" . $value2 . "%), overhead=" . $value3 . " MB, swapped=" . $value4 . " MB";
		}
	}

	return ($res, $output);
}

sub host_net_info
{
	my ($np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST NET Unknown error';
	
	if (defined($subcommand))
	{
		if ($subcommand =~ /^USAGE$/i)
		{
			$values = return_host_performance_values('net', ('usage.average:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value));
				$np->add_perfdata(label => "net_usage", value => $value, uom => 'KB', threshold => $np->threshold);
				$output = "net usage=" . $value . " KB/s"; 
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^RECEIVE$/i)
		{
			$values = return_host_performance_values('net', ('received.average:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value));
				$np->add_perfdata(label => "net_receive", value => $value, uom => 'KB', threshold => $np->threshold);
				$output = "net recive=" . $value . " KB/s"; 
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^SEND$/i)
		{
			$values = return_host_performance_values('net', ('transmitted.average:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value));
				$np->add_perfdata(label => "net_send", value => $value, uom => 'KB', threshold => $np->threshold);
				$output = "net send=" . $value . " KB/s"; 
				$res = $np->check_threshold(check => $value);
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST NET - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		$values = return_host_performance_values('net', ('received.average:*', 'transmitted.average:*'));
		if (defined($values))
		{
			my $value1 = simplify_number(convert_number($$values[0]->value));
			my $value2 = simplify_number(convert_number($$values[1]->value));
			$np->add_perfdata(label => "net_receive", value => $value1, uom => 'KB', threshold => $np->threshold);
			$np->add_perfdata(label => "net_send", value => $value2, uom => 'KB', threshold => $np->threshold);
			$res = 'OK';
			$output = "net receive=" . $value1 . " KB/s, send=" . $value2 . " KB/s";
		}
	}

	return ($res, $output);
}

sub host_disk_io_info
{
	my ($np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST IO Unknown error';
	
	if (defined($subcommand))
	{
		if ($subcommand =~ /^ABORTED$/i)
		{
			$values = return_host_performance_values('disk', ('commandsAborted.summation:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value), 0);
				$np->add_perfdata(label => "io_aborted", value => $value, threshold => $np->threshold);
				$output = "io commands aborted=" . $value;
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^RESETS$/i)
		{
			$values = return_host_performance_values('disk', ('busResets.summation:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value), 0);
				$np->add_perfdata(label => "io_busresets", value => $value, threshold => $np->threshold);
				$output = "io bus resets=" . $value;
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^READ$/i)
		{
			$values = return_host_performance_values('disk', ('totalReadLatency.average:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value), 0);
				$np->add_perfdata(label => "io_read", value => $value, uom => 'ms', threshold => $np->threshold);
				$output = "io read latency=" . $value . " ms";
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^WRITE$/i)
		{
			$values = return_host_performance_values('disk', ('totalWriteLatency.average:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value), 0);
				$np->add_perfdata(label => "io_write", value => $value, uom => 'ms', threshold => $np->threshold);
				$output = "io write latency=" . $value . " ms";
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^KERNEL$/i)
		{
			$values = return_host_performance_values('disk', ('kernelLatency.average:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value), 0);
				$np->add_perfdata(label => "io_kernel", value => $value, uom => 'ms', threshold => $np->threshold);
				$output = "io kernel latency=" . $value . " ms";
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^DEVICE$/i)
		{
			$values = return_host_performance_values('disk', ('deviceLatency.average:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value), 0);
				$np->add_perfdata(label => "io_device", value => $value, uom => 'ms', threshold => $np->threshold);
				$output = "io device latency=" . $value . " ms";
				$res = $np->check_threshold(check => $value);
			}
		}
		elsif ($subcommand =~ /^QUEUE$/i)
		{
			$values = return_host_performance_values('disk', ('queueLatency.average:*'));
			if (defined($values))
			{
				my $value = simplify_number(convert_number($$values[0]->value), 0);
				$np->add_perfdata(label => "io_queue", value => $value, uom => 'ms', threshold => $np->threshold);
				$output = "io queue latency=" . $value . " ms";
				$res = $np->check_threshold(check => $value);
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST IO - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		$values = return_host_performance_values('disk', ('commandsAborted.summation:*', 'busResets.summation:*', 'totalReadLatency.average:*', 'totalWriteLatency.average:*', 'kernelLatency.average:*', 'deviceLatency.average:*', 'queueLatency.average:*'));
		if (defined($values))
		{
			my $value1 = simplify_number(convert_number($$values[0]->value), 0);
			my $value2 = simplify_number(convert_number($$values[1]->value), 0);
			my $value3 = simplify_number(convert_number($$values[2]->value), 0);
			my $value4 = simplify_number(convert_number($$values[3]->value), 0);
			my $value5 = simplify_number(convert_number($$values[4]->value), 0);
			my $value6 = simplify_number(convert_number($$values[5]->value), 0);
			my $value7 = simplify_number(convert_number($$values[6]->value), 0);
			$np->add_perfdata(label => "io_aborted", value => $value1, threshold => $np->threshold);
			$np->add_perfdata(label => "io_busresets", value => $value2, threshold => $np->threshold);
			$np->add_perfdata(label => "io_read", value => $value3, uom => 'ms', threshold => $np->threshold);
			$np->add_perfdata(label => "io_write", value => $value4, uom => 'ms', threshold => $np->threshold);
			$np->add_perfdata(label => "io_kernel", value => $value5, uom => 'ms', threshold => $np->threshold);
			$np->add_perfdata(label => "io_device", value => $value6, uom => 'ms', threshold => $np->threshold);
			$np->add_perfdata(label => "io_queue", value => $value7, uom => 'ms', threshold => $np->threshold);
			$res = 'OK';
			$output = "io commands aborted=" . $value1 . ", io bus resets=" . $value2 . ", io read latency=" . $value3 . " ms, write latency=" . $value4 . " ms, kernel latency=" . $value5 . " ms, device latency=" . $value6 . " ms, queue latency=" . $value7 ." ms";
		}
	}

	return ($res, $output);
}

sub host_list_vm_volumes_info
{
	my ($np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST VM VOLUMES Unknown error';

	if (defined($subcommand))
	{
		$output = "No volume named $subcommand found";
		my $host_views = Vim::find_entity_views(view_type => 'HostSystem');
		foreach my $host (@$host_views) {
			foreach my $ref_store (@{$host->datastore})
			{
				my $store = Vim::get_view(mo_ref => $ref_store);
				$store->update_view_data();
				if ($store->summary->name eq $subcommand)
				{
					$res = 'OK';
					$output = $store->summary->name . "=". simplify_number(convert_number($store->summary->freeSpace) / 1024 / 1024) . " MB (" . simplify_number(convert_number($store->info->freeSpace) / convert_number($store->summary->capacity) * 100) . "%)";
				}
			}
		}
	}
	else
	{
		$output = '';
		my $host_views = Vim::find_entity_views(view_type => 'HostSystem');
		foreach my $host (@$host_views) {
			foreach my $ref_store (@{$host->datastore})
			{
				my $store = Vim::get_view(mo_ref => $ref_store);
				$store->update_view_data();
				$output .= $store->summary->name . "=". simplify_number(convert_number($store->summary->freeSpace) / 1024 / 1024) . " MB (" . simplify_number(convert_number($store->info->freeSpace) / convert_number($store->summary->capacity) * 100) . "%), ";
			}
		}

		chop($output);
		chop($output);
		$res = 'OK';
		$output = "storages : " . $output;
	}

	return ($res, $output);
}

sub host_runtime_info
{
	my ($np, $subcommand) = @_;

	my $res = 'CRITICAL';
	my $output = 'HOST RUNTIME Unknown error';
	my $runtime;
	my $host_view;

	eval
	{
		$host_view = Vim::find_entity_view(view_type => 'HostSystem');
		$host_view->update_view_data();
		$runtime = $host_view->runtime;
	};
	return ($res, $output) if ($@);

	if (defined($subcommand))
	{
		if ($subcommand =~ /^CON$/i)
		{
			$output =  "connection state=" . $runtime->connectionState->val;
			$res = 'OK' if ($runtime->connectionState->val eq "connected");
		}
		elsif ($subcommand =~ /^MAINTENANCE$/i)
		{
			my %host_maintenance_state = (0 => "no", 1 => "yes");
			$output = "maintenance=" . $host_maintenance_state{$runtime->inMaintenanceMode};
			$res = 'OK';
		}
		elsif ($subcommand =~ /^LIST$/i)
		{
			my %vm_state_strings = ("poweredOn" => "UP", "poweredOff" => "DOWN", "suspended" => "SUSPENDED");
			my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine');
			my $up = 0;
			$output = '';

			foreach my $vm (@$vm_views) {
				$vm->update_view_data();
				my $vm_state = $vm->runtime->powerState->val;
				$up += $vm_state eq "poweredOn";
				$output .= $vm->name . "(" . $vm_state_strings{$vm_state} . "), ";
			}

			chop($output);
			chop($output);
			$res = 'OK';
			$output = $up .  "/" . @$vm_views . " VMs up: " . $output;
			$np->add_perfdata(label => "vmcount", value => $up, uom => 'units', threshold => $np->threshold);
			$res = $np->check_threshold(check => $up) if (defined($np->threshold));
		}
		elsif ($subcommand =~ /^STATUS$/i)
		{
			$output =  "overall status=" . $host_view->overallStatus->val;
			$res = 'OK' if ($host_view->overallStatus->val eq "green");
		}
		elsif ($subcommand =~ /^ISSUES$/i)
		{
			my $issues = $host_view->configIssue;

			if (defined($issues))
			{
				$output = '';
				foreach (@$issues)
				{
					$output .= $_->vm->name . ": " . $_->fullFormattedMessage . "(caused by " . $_->userName . "); ";
				}
			}
			else
			{
				$res = 'OK';
				$output = 'No issues';
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST RUNTIME - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		my %host_maintenance_state = (0 => "no", 1 => "yes");
		my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine');
		my $up = 0;

		foreach my $vm (@$vm_views) {
			$vm->update_view_data();
			$up += $vm->runtime->powerState->val eq "poweredOn";
		}

		$output =  $up . "/" . @$vm_views . " VMs up, overall status=" . $host_view->overallStatus->val . ", connection state=" . $runtime->connectionState->val . ", maintenance=" . $host_maintenance_state{$runtime->inMaintenanceMode};
		$res = 'OK';
	}

	return ($res, $output);
}

#==========================================================================| VM |============================================================================#

sub vm_cpu_info
{
	my ($vmname, $np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST-VM CPU Unknown error';
	
	if (defined($subcommand))
	{
		if ($subcommand =~ /^USAGE$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'cpu', ('usage.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) * 0.01);
					$np->add_perfdata(label => "cpu_usage", value => $value, uom => '%', threshold => $np->threshold);
					$output = "$vmname cpu usage=" . $value . " %"; 
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^USAGEMHZ$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'cpu', ('usagemhz.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value));
					$np->add_perfdata(label => "cpu_usagemhz", value => $value, uom => 'Mhz', threshold => $np->threshold);
					$output = "$vmname cpu usage=" . $value . " MHz";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^WAIT$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'cpu', ('wait.summation:*'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value));
					$np->add_perfdata(label => "cpu_wait", value => $value, uom => 'ms', threshold => $np->threshold);
					$output = "$vmname cpu wait=" . $value . " ms";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST-VM CPU - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		$values = return_host_vmware_performance_values($vmname, 'cpu', ('usagemhz.average', 'usage.average', 'wait.summation:*'));
		if (defined($values))
		{
			if (ref($values))
			{
				my $value1 = simplify_number(convert_number($$values[0]->value));
				my $value2 = simplify_number(convert_number($$values[1]->value) * 0.01);
				my $value3 = simplify_number(convert_number($$values[2]->value));
				$np->add_perfdata(label => "cpu_usagemhz", value => $value1, uom => 'Mhz', threshold => $np->threshold);
				$np->add_perfdata(label => "cpu_usage", value => $value2, uom => '%', threshold => $np->threshold);
				$np->add_perfdata(label => "cpu_wait", value => $value3, uom => 'ms', threshold => $np->threshold);
				$res = 'OK';
				$output = "$vmname cpu usage=" . $value1 . " MHz(" . $value2 . "%) wait=" . $value3 . " ms";
			}
			else
			{
				$output = $values;
			}
		}
	}

	return ($res, $output);
}

sub vm_mem_info
{
	my ($vmname, $np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST-VM MEM Unknown error';
	
	if (defined($subcommand))
	{
		if ($subcommand =~ /^USAGE$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'mem', ('usage.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) * 0.01);
					$np->add_perfdata(label => "mem_usage", value => $value, uom => '%', threshold => $np->threshold);
					$output = "$vmname nem usage=" . $value . " %"; 
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^USAGEMB$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'mem', ('consumed.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "mem_usagemb", value => $value, uom => 'MB', threshold => $np->threshold);
					$output = "$vmname mem usage=" . $value . " MB";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^SWAP$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'mem', ('swapped.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "mem_swap", value => $value, uom => 'MB', threshold => $np->threshold);
					$output = "$vmname swap usage=" . $value . " MB";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^SWAPIN$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'mem', ('swapin.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "mem_swapin", value => $value, uom => 'MB', threshold => $np->threshold);
					$output = "$vmname swapin=" . $value . " MB";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^SWAPOUT$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'mem', ('swapout.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "mem_swapout", value => $value, uom => 'MB', threshold => $np->threshold);
					$output = "$vmname swapout=" . $value . " MB";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^OVERHEAD$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'mem', ('overhead.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "mem_overhead", value => $value, uom => 'MB', threshold => $np->threshold);
					$output = "$vmname mem overhead=" . $value . " MB";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^OVERALL$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'mem', ('consumed.average', 'overhead.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number((convert_number($$values[0]->value) + convert_number($$values[1]->value)) / 1024);
					$np->add_perfdata(label => "mem_overall", value =>  $value, uom => 'MB', threshold => $np->threshold);
					$output = "$vmname mem overall=" . $value . " MB";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^ACTIVE$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'mem', ('active.average'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "mem_active", value =>  $value, uom => 'MB', threshold => $np->threshold);
					$output = "$vmname mem active=" . $value . " MB";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST-VM MEM - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		$values = return_host_vmware_performance_values($vmname, 'mem', ('consumed.average', 'usage.average', 'overhead.average', 'active.average', 'swapped.average', 'swapin.average', 'swapout.average'));
		if (defined($values))
		{
			if (ref($values))
			{
				my $value1 = simplify_number(convert_number($$values[0]->value) / 1024);
				my $value2 = simplify_number(convert_number($$values[1]->value) * 0.01);
				my $value3 = simplify_number(convert_number($$values[2]->value) / 1024);
				my $value4 = simplify_number(convert_number($$values[3]->value) / 1024);
				my $value5 = simplify_number(convert_number($$values[4]->value) / 1024);
				my $value6 = simplify_number(convert_number($$values[5]->value) / 1024);
				my $value7 = simplify_number(convert_number($$values[6]->value) / 1024);
				$np->add_perfdata(label => "mem_usagemb", value => $value1, uom => 'MB', threshold => $np->threshold);
				$np->add_perfdata(label => "mem_usage", value => $value2, uom => '%', threshold => $np->threshold);
				$np->add_perfdata(label => "mem_overhead", value => $value3, uom => 'MB', threshold => $np->threshold);
				$np->add_perfdata(label => "mem_active", value => $value4, uom => 'MB', threshold => $np->threshold);
				$np->add_perfdata(label => "mem_swap", value => $value5, uom => 'MB', threshold => $np->threshold);
				$res = 'OK';
				$output =  "$vmname mem usage=" . $value1 . " MB(" . $value2 . "%), overhead=" . $value3 . " MB, active=" . $value4 . " MB, swapped=" . $value5 . " MB, swapin=" . $value6 . " MB, swapout=" . $value7 . " MB";
			}
			else
			{
				$output = $values;
			}
		}
	}

	return ($res, $output);
}

sub vm_net_info
{
	my ($vmname, $np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST-VM NET Unknown error';
	
	if (defined($subcommand))
	{
		if ($subcommand =~ /^USAGE$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'net', ('usage.average:*'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value));
					$np->add_perfdata(label => "net_usage", value => $value, uom => 'KB', threshold => $np->threshold);
					$output = "$vmname net usage=" . $value . " KB/s"; 
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^RECEIVE$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'net', ('received.average:*'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value));
					$np->add_perfdata(label => "net_receive", value => $value, uom => 'KB', threshold => $np->threshold);
					$output = "$vmname net recive=" . $value . " KB/s"; 
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^SEND$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'net', ('transmitted.average:*'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value));
					$np->add_perfdata(label => "net_send", value => $value, uom => 'KB', threshold => $np->threshold);
					$output = "$vmname net send=" . $value . " KB/s"; 
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST-VM NET - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		$values = return_host_vmware_performance_values($vmname, 'net', ('received.average:*', 'transmitted.average:*'));
		if (defined($values))
		{
			if (ref($values))
			{
				my $value1 = simplify_number(convert_number($$values[0]->value));
				my $value2 = simplify_number(convert_number($$values[1]->value));
				$np->add_perfdata(label => "net_receive", value => $value1, uom => 'KB', threshold => $np->threshold);
				$np->add_perfdata(label => "net_send", value => $value2, uom => 'KB', threshold => $np->threshold);
				$res = 'OK';
				$output = "$vmname net receive=" . $value1 . " KB/s, send=" . $value2 . " KB/s";
			}
			else
			{
				$output = $values;
			}
		}
	}

	return ($res, $output);
}

sub vm_disk_io_info
{
	my ($vmname, $np, $subcommand) = @_;
	 
	my $res = 'CRITICAL';
	my $output = 'HOST-VM IO Unknown error';
	
	if (defined($subcommand))
	{
		if ($subcommand =~ /^USAGE$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'disk', ('usage.average:*'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "io_usage", value => $value, uom => 'MB', threshold => $np->threshold);
					$output = "$vmname io usage=" . $value . " MB";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^READ$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'disk', ('read.average:*'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "io_read", value => $value, uom => 'MB/s', threshold => $np->threshold);
					$output = "$vmname io read=" . $value . " MB/s";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		elsif ($subcommand =~ /^WRITE$/i)
		{
			$values = return_host_vmware_performance_values($vmname, 'disk', ('write.average:*'));
			if (defined($values))
			{
				if (ref($values))
				{
					my $value = simplify_number(convert_number($$values[0]->value) / 1024);
					$np->add_perfdata(label => "io_write", value => $value, uom => 'MB/s', threshold => $np->threshold);
					$output = "$vmname io write=" . $value . " MB/s";
					$res = $np->check_threshold(check => $value);
				}
				else
				{
					$output = $values;
				}
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST IO - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		$values = return_host_vmware_performance_values($vmname, 'disk', ('usage.average:*', 'read.average:*', 'write.average:*'));
		if (defined($values))
		{
			if (ref($values))
			{
				my $value1 = simplify_number(convert_number($$values[0]->value) / 1024);
				my $value2 = simplify_number(convert_number($$values[1]->value) / 1024);
				my $value3 = simplify_number(convert_number($$values[2]->value) / 1024);
				$np->add_perfdata(label => "io_usage", value => $value1, uom => 'MB', threshold => $np->threshold);
				$np->add_perfdata(label => "io_read", value => $value2, uom => 'MB/s', threshold => $np->threshold);
				$np->add_perfdata(label => "io_write", value => $value3, uom => 'MB/s', threshold => $np->threshold);
				$res = 'OK';
				$output = "$vmname io usage=" . $value1 . " MB, read=" . $value2 . " MB/s, write=" . $value3 . " MB/s";
			}
			else
			{
				$output = $values;
			}
		}
	}

	return ($res, $output);
}

sub vm_runtime_info
{
	my ($vmname, $np, $subcommand) = @_;

	my $res = 'CRITICAL';
	my $output = 'HOST-VM RUNTIME Unknown error';
	my $runtime;
	my $vm_view;

	eval
	{
		$vm_view = Vim::find_entity_view(view_type => 'VirtualMachine', filter => {name => $vmname});
		$output = "VMware machine \"" . $vmname . "\" does not exist.\n" if (!defined($vm_view));
		$vm_view->update_view_data();
		$runtime = $vm_view->runtime;
	};
	return ($res, $output) if ($@);

	if (defined($subcommand))
	{
		if ($subcommand =~ /^CON$/i)
		{
			$output = "$vmname connection state=" . $runtime->connectionState->val;
			$res = 'OK' if ($runtime->connectionState->val eq "connected");
		}
		elsif ($subcommand =~ /^CPU$/i)
		{
			$output = "$vmname max cpu=" . $runtime->maxCpuUsage . " MHz";
			$res = 'OK';
		}
		elsif ($subcommand =~ /^MEM$/i)
		{
			$output = "$vmname max mem=" . $runtime->maxMemoryUsage . " MB";
			$res = 'OK';
		}
		elsif ($subcommand =~ /^STATE$/i)
		{
			my %vm_state_strings = ("poweredOn" => "UP", "poweredOff" => "DOWN", "suspended" => "SUSPENDED");
			$output = "$vmname run state=" . $vm_state_strings{$runtime->powerState->val};
			$res = 'OK' if ($runtime->powerState->val eq "poweredOn");
		}
		elsif ($subcommand =~ /^STATUS$/i)
		{
			$output = "$vmname overall status=" . $vm_view->overallStatus->val;
			$res = 'OK' if ($vm_view->overallStatus->val eq "green");
		}
		elsif ($subcommand =~ /^CONNECTIONS$/i)
		{
			$output = "$vmname connections=" . $runtime->numMksConnections;
			$res = $np->check_threshold(check => $runtime->numMksConnections);
		}
		elsif ($subcommand =~ /^GUEST$/i)
		{
			my %vm_guest_state = ("running" => "Running", "notRunning" => "Not running", "shuttingDown" => "Shutting down", "resetting" => "Resetting", "standby" => "Standby", "unknown" => "Unknown");
			$output = "$vmname guest state=" . $vm_guest_state{$vm_view->guest->guestState};
			$res = 'OK' if ($vm_view->guest->guestState eq "running");
		}
		elsif ($subcommand =~ /^TOOLS$/i)
		{
			my %vm_tools_status = ("toolsNotInstalled" => "Not installed", "toolsNotRunning" => "Not running", "toolsOk" => "OK", "toolsOld" => "Old");
			$output = "$vmname tools status=" . $vm_tools_status{$vm_view->guest->toolsStatus->val};
			$res = 'OK' if ($vm_view->guest->toolsStatus->val eq "toolsOk");
		}
		elsif ($subcommand =~ /^ISSUES$/i)
		{
			my $issues = $vm_view->configIssue;

			if (defined($issues))
			{
				$output = $_->vm->name . ': ';
				foreach (@$issues)
				{
					$output .=  $_->fullFormattedMessage . "(caused by " . $_->userName . "); ";
				}
			}
			else
			{
				$res = 'OK';
				$output = 'No issues';
			}
		}
		else
		{
			$res = 'CRITICAL';
			$output = "HOST-VM RUNTIME - unknown subcommand\n" . $np->opts->_help;
		}
	}
	else
	{
		my %vm_state_strings = ("poweredOn" => "UP", "poweredOff" => "DOWN", "suspended" => "SUSPENDED");
		my %vm_tools_status = ("toolsNotInstalled" => "Not installed", "toolsNotRunning" => "Not running", "toolsOk" => "OK", "toolsOld" => "Old");
		my %vm_guest_state = ("running" => "Running", "notRunning" => "Not running", "shuttingDown" => "Shutting down", "resetting" => "Resetting", "standby" => "Standby", "unknown" => "Unknown");
		$res = 'OK';
		$output = "$vmname status=" . $vm_view->overallStatus->val . ", run state=" . $vm_state_strings{$runtime->powerState->val} . ", guest state=" . $vm_guest_state{$vm_view->guest->guestState} . ", max cpu=" . $runtime->maxCpuUsage . " MHz, max mem=" . $runtime->maxMemoryUsage . " MB, connections=" . $runtime->numMksConnections . ", tools status=" . $vm_tools_status{$vm_view->guest->toolsStatus->val};
	}

	return ($res, $output);
}

#TODO
#
# 1) human readable output for values convert them to nearest units

