#!/usr/bin/perl -w
##################################################################
# Author: William Lam
# Email: william2003[at]gmail[dot]com
# 02/14/2009
# http://www.engineering.ucsb.edu/~duonglt/vmware/
##################################################################
use strict;
use warnings;
use Math::BigInt;
use Tie::File;
use POSIX qw/mktime/;
use Getopt::Long;
use VMware::VIRuntime;
use VMware::VILib;
####################################
# resource consumption warnings
####################################
# yellow < 30 %
my $yellow_warn = 30;
# orange < 15 %
my $orange_warn = 15;
# red < 10%
my $red_warn = 10;
######################################
# vm snapshot age warnings
######################################
# yellow < 15 days
my $snap_yellow_warn = 15;
# orange < 30 days
my $snap_orange_warn = 30;
# red < 60 days+
my $snap_red_warn = 60;
########### DO NOT MODIFY PAST HERE ###########
################################
# VERSION
################################
my $version = "1.0";
$Util::script_version = $version;
################################
# DEMO MODE
# 0 = no, 1 = yes
################################
my $enable_demo_mode = 0;
################
#GLOBAL VARS
################
my $opt_type;
my $host_type;
my $host_view;
my $host_views;
my $cluster_view;
my $cluster_views;
my $cluster_count = 0;
my $report_name;
my @snapshot_vms = ();
my @connected_cdrom_vms = ();
my @connected_floppy_vms = ();
my @rdm_vms = ();
my @npiv_vms = ();
my %net_vms = ();
my %vms_storage = ();
my %vms_disks = ();
my $execute_flag = 0;
my $start_time;
my $end_time;
my $run_time;
my $my_time;
my @jump_tags = ();
my %cdp_enabled = ();
my @hba_list = ();
my @health_list = ();
my @nic_list = ();
my @hosts_seen = ();
my $datacenter_name;
my @vm_delta_warn = ();
my $hostd_log_print;
my $randomHostName;
my $content;
my %portgroup_row_info = ();
my $cdp_string = "";
my @dvs = ();
my %opts = (
cluster => {
type => "=s",
help => "The name of a vCenter cluster",
required => 0,
},
datacenter => {
type => "=s",
help => "The name of a vCenter datacenter",
required => 0,
},
type => {
type => "=s",
help => "Type: [vcenter|datacenter|cluster|host|detail-hosts]\n",
required => 1,
},
report => {
type => "=s",
help => "The name of the report to output. Please add \".html\" extension",
required => 0,
},
logcount => {
type => "=s",
help => "The number of lines to output from hostd logs",
required => 0,
},
);
# validate options, and connect to the server
Opts::add_options(%opts);
# validate options, and connect to the server
Opts::parse();
Opts::validate();
Util::connect();
############################
# PARSE COMMANDLINE OPTIONS
#############################
if (Opts::option_is_set ('type')) {
# get ServiceContent
$content = Vim::get_service_content();
$host_type = $content->about->apiType;
$opt_type = Opts::get_option('type');
####################
# SINGLE ESX HOST
####################
if( ($opt_type eq 'host') && (!Opts::option_is_set('cluster')) && ($host_type eq 'HostAgent') ) {
$host_view = Vim::find_entity_views(view_type => 'HostSystem');
if (!$host_view) {
die "ESX/ESXi host was not found\n";
}
}
#####################
# vCENTER + CLUSTER
#####################
elsif( ($opt_type eq 'cluster') && ($host_type eq 'VirtualCenter') ) {
if ( Opts::option_is_set('cluster') ) {
my $cluster_name = Opts::get_option('cluster');
$cluster_view = Vim::find_entity_view(view_type => 'ClusterComputeResource',filter => { name => $cluster_name });
if(!$cluster_view) {
die "Cluster: \"$cluster_name\" was not found\n";
}
}
else {
Fail("\n--cluster parameter required with the name of a valid vCenter Cluster\n\n");
}
}
########################
# vCENTER + DATACENTER
########################
elsif( ($opt_type eq 'datacenter') && ($host_type eq 'VirtualCenter') ) {
if ( Opts::option_is_set('datacenter') ) {
$datacenter_name = Opts::get_option('datacenter');
my $datacenter_view = Vim::find_entity_view(view_type => 'Datacenter',filter => { name => $datacenter_name});
if(!$datacenter_view) {
die "Datacenter: \"$datacenter_name\" was not found\n";
}
$cluster_views = Vim::find_entity_views(view_type => 'ClusterComputeResource',begin_entity => $datacenter_view);
if(!$cluster_views) {
die "No clusters were found in this datacenter\n";
}
}
else {
Fail("\n--datacenter parameter required with the name of a valid vCenter Datacenter\n\n");
}
}
#########################
# vCENTER HOST DETAIL
#########################
elsif( ($opt_type eq 'detail-hosts') && (!Opts::option_is_set('cluster')) && ($host_type eq 'VirtualCenter') ) {
$cluster_views = Vim::find_entity_views(view_type => 'ClusterComputeResource');
Fail ("No clusters found.\n") unless (@$cluster_views);
}
##################
# vCENTER ALL
##################
elsif( ($opt_type eq 'vcenter') && (!Opts::option_is_set('cluster')) && ($host_type eq 'VirtualCenter') ) {
$cluster_views = Vim::find_entity_views(view_type => 'ClusterComputeResource');
Fail ("No clusters found.\n") unless (@$cluster_views);
}
#######################################
# VM DISK INFO INDIVIDUAL HOSTS ONLY
######################################
elsif( ($opt_type eq 'vmfrag') && (!Opts::option_is_set('cluster')) && ($host_type eq 'HostAgent') ) {
$host_view = Vim::find_entity_views(view_type => 'HostSystem');
if (!$host_view) {
die "ESX/ESXi host was not found\n";
}
} else { die "Invalid Input, ensure your selection is one of the supported use cases on the VMTN Doc\n\n\tServer: vCenter => [vcenter|datacenter|cluster|detail-hosts]\n\tServer: ESX/ESXi Host => [host|vmfrag]\n"; }
#if report name is not specified, default output
if (Opts::option_is_set ('report')) {
$report_name = Opts::get_option('report');
}
else {
$report_name = "vmware_health_report.html";
}
#if use case is with hostd logs, set log count or default to 15
if( Opts::option_is_set('logcount') ) {
$hostd_log_print = Opts::get_option('logcount');
} else { $hostd_log_print = 15; }
}
### CODE START ###
#################################
# PRINT HTML HEADER/CSS
#################################
printStartHeader();
#########################################
# PRINT vCENTER or HOST BUILD/SUMMARY
#########################################
printBuildSummary();
#########################################
# PRINT vCENTER INFO
#########################################
if ($opt_type eq 'vcenter') {
foreach my $cluster (@$cluster_views) {
$cluster_count += 1;
printClusterSummary($cluster);
my $hosts = Vim::get_views (mo_ref_array => $cluster->host);
if(@$hosts) {
printHostHardwareInfo($hosts);
printHostLun($hosts);
printHostDatastoreInfo($hosts);
printPG();
printDVS();
printHostVM($hosts);
printVMDatastore();
printVMNetwork();
printVMSnapshot();
printVMSnapshotDeltaOlderThan();
printVMNPIV();
printVMRDM();
printVMCDrom();
printVMFloppy();
cleanUp();
}
}
}
#########################################
# PRINT SPECIFIC DATACENTER INFO
#########################################
elsif ($opt_type eq 'datacenter') {
printDatacenterName($datacenter_name);
foreach my $cluster (@$cluster_views) {
$cluster_count += 1;
printClusterSummary($cluster);
my $hosts = Vim::get_views (mo_ref_array => $cluster->host);
if(@$hosts) {
printHostHardwareInfo($hosts);
printHostLun($hosts);
printHostDatastoreInfo($hosts);
printPG();
printDVS();
printHostVM($hosts);
printVMDatastore();
printVMNetwork();
printVMSnapshot();
printVMSnapshotDeltaOlderThan();
printVMNPIV();
printVMRDM();
printVMCDrom();
printVMFloppy();
cleanUp();
}
}
}
#########################################
# PRINT SPECIFIC CLUSTER INFO
#########################################
elsif ($opt_type eq 'cluster') {
$cluster_count += 1;
printClusterSummary($cluster_view);
my $hosts = Vim::get_views (mo_ref_array => $cluster_view->host);
if(@$hosts) {
printHostHardwareInfo($hosts);
printHostLun($hosts);
printHostDatastoreInfo($hosts);
printPG();
printDVS();
printHostVM($hosts);
printVMDatastore();
printVMNetwork();
printVMSnapshot();
printVMSnapshotDeltaOlderThan();
printVMNPIV();
printVMRDM();
printVMCDrom();
printVMFloppy();
cleanUp();
}
}
#########################################
# PRINT SINGLE HOST INFO
#########################################
elsif ($opt_type eq 'host' ) {
printHostHardwareInfo($host_view);
printHostLun($host_view);
printHostDatastoreInfo($host_view);
printHostPortgroup($host_view);
printHostVM($host_view);
queryVMDisk($host_view);
printVMDatastore();
printVMNetwork();
printVMSnapshot();
printVMSnapshotDeltaOlderThan();
printVMNPIV();
printVMRDM();
printVMCDrom();
printVMFloppy();
cleanUp();
}
#########################################
# PRINT DETAIL HOSTS INFO
#########################################
elsif ($opt_type eq 'detail-hosts') {
foreach my $cluster (@$cluster_views) {
$cluster_count += 1;
printClusterSummary($cluster);
my $hosts = Vim::get_views (mo_ref_array => $cluster->host);
if(@$hosts) {
printHostHardwareInfo($hosts);
printHostLun($hosts);
printHostDatastoreInfo($hosts);
printPG();
printDVS();
printVMSnapshot();
printVMSnapshotDeltaOlderThan();
printVMNPIV();
printVMRDM();
printVMCDrom();
printVMFloppy();
cleanUp();
}
}
}
#########################################
# PRINT VM DISK INFO
#########################################
elsif ($opt_type eq 'vmfrag') {
queryVMDisk($host_view);
cleanUp();
}
#################################
# CLOSE HTML REPORT
#################################
printCloseHeader();
Util::disconnect();
### CODE END ###
###########################
#
# HELPER FUNCTIONS
#
###########################
sub queryVMDisk {
my ($host_view) = @_;
foreach my $host (@$host_view) {
my $vm_views = Vim::get_views (mo_ref_array => $host->vm);
if($opt_type eq 'vmfrag') {
push @jump_tags,"VM(s) VMDK Disk Information
\n";
} else {
push @jump_tags," VM(s) VMDK Disk Information
\n";
}
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "
VM(s) VMDK Disk Information:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM | FRAGMENTATION | VMDK | DISK CYLINDER | DISK HEAD | DISK SECTOR | UUID |
\n";
foreach my $vm (@$vm_views) {
#skip if vm is disconnected
next if(!defined($vm->layout));
my $disks = $vm->layout->disk;
my $vdm_mgr = Vim::get_view(mo_ref => Vim::get_service_content()->virtualDiskManager);
foreach(@$disks) {
my $disk_files = $_->diskFile;
my $disk_string = "";
foreach(@$disk_files) {
eval { $vdm_mgr->QueryVirtualDiskFragmentation(name => $_); };
if(!$@) {
my $disk_frag = $vdm_mgr->QueryVirtualDiskFragmentation(name => $_);
my $disk_geom = $vdm_mgr->QueryVirtualDiskGeometry(name => $_);
my $disk_uuid = $vdm_mgr->QueryVirtualDiskUuid(name => $_);
if(!defined($disk_frag)) { $disk_frag = "N/A"; }
print REPORT_OUTPUT "",$vm->config->name," | ".$disk_frag." | ".$_." | ".$disk_geom->cylinder." | ".$disk_geom->head." | ".$disk_geom->sector." | ".$disk_uuid." | ","
\n";
}
}
}
}
print REPORT_OUTPUT "
\n";
}
}
sub printVMNPIV {
###########################
# PRINT NPIV INFO
###########################
if(@npiv_vms) {
my $npiv_count = $#npiv_vms;
$npiv_count += 1;
if($opt_type eq 'detail-hosts') {
push @jump_tags,"VM(s) w/NPIV enabled
\n";
} else { push @jump_tags," VM(s) w/NPIV enabled
\n"; }
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "$npiv_count VM(s) w/NPIV enabled:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM | NPIV NODE WWN | NPIV PORT WWN | GENERATED FROM |
\n";
foreach (@npiv_vms) {
print REPORT_OUTPUT "",$_,"
\n";
}
print REPORT_OUTPUT "
\n";
}
@npiv_vms = ();
}
sub printVMSnapshotDeltaOlderThan {
###########################
# PRINT DELTA INFO
###########################
if(@vm_delta_warn) {
my $snap_delta_count = $#vm_delta_warn;
$snap_delta_count +=1;
if($opt_type eq 'detail-hosts') {
push @jump_tags,"VM(s) w/Snapshot Delta(s) Older Than $snap_yellow_warn+ days
\n";
} else { push @jump_tags," VM(s) w/Snapshot Delta(s) Older Than $snap_yellow_warn+ days
\n"; }
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "$snap_delta_count VM(s) w/Snapshot Delta(s) Older Than $snap_yellow_warn+ Days:
\n";
print REPORT_OUTPUT "COLOR LEGEND | YELLOW > $snap_yellow_warn days | ORANGE > $snap_orange_warn days | RED > $snap_red_warn days |
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "DATASTORE | VM DELTA | AGE | SIZE | CREATED |
\n";
foreach(@vm_delta_warn) {
print REPORT_OUTPUT "",$_,"
\n";
}
print REPORT_OUTPUT "
\n";
}
@vm_delta_warn = ();
}
sub printVMSnapshot {
###########################
# PRINT SNAPSHOT INFO
###########################
if(@snapshot_vms) {
my $snap_count = $#snapshot_vms;
$snap_count += 1;
if($opt_type eq 'detail-hosts') {
push @jump_tags,"VM(s) w/Snapshot(s)
\n";
} else { push @jump_tags," VM(s) w/Snapshot(s)
\n"; }
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "$snap_count VM(s) w/Snapshot(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM | SNAPSHOT NAME | SNAPSHOT DESC | CREATED | STATE | QUIESCED |
\n";
foreach (@snapshot_vms) {
print REPORT_OUTPUT "",$_,"
\n";
}
print REPORT_OUTPUT "
\n";
}
@snapshot_vms = ();
}
sub printVMRDM {
###########################
# PRINT RDM INFO
###########################
if(@rdm_vms) {
my $rdm_count = $#rdm_vms;
$rdm_count += 1;
if($opt_type eq 'detail-hosts') {
push @jump_tags,"VM(s) w/RDM(s)
\n";
} else { push @jump_tags," VM(s) w/RDM(s)
\n"; }
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "$rdm_count VM(s) w/RDM(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM | COMPAT MODE | DEVICE | DISK MODE | LUN UUID | VIRTUAL DISK UUID |
\n";
foreach (@rdm_vms) {
print REPORT_OUTPUT "",$_,"
\n";
}
print REPORT_OUTPUT "
\n";
}
@rdm_vms = ();
}
sub printVMCDrom {
###########################
# PRINT CDROM INFO
###########################
if(@connected_cdrom_vms) {
my $cdrom_count = $#connected_cdrom_vms;
$cdrom_count += 1;
if($opt_type eq 'detail-hosts') {
push @jump_tags,"VM(s) w/connected CD-ROM(s)
\n";
} else { push @jump_tags," VM(s) w/connected CD-ROM(s)
\n"; }
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "$cdrom_count VM(s) w/connected CD-ROM(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM |
\n";
foreach (@connected_cdrom_vms) {
print REPORT_OUTPUT "",$_," |
\n";
}
print REPORT_OUTPUT "
\n";
}
@connected_cdrom_vms = ();
}
sub printVMFloppy {
###########################
# PRINT FLOPPY INFO
###########################
if(@connected_floppy_vms) {
my $floppy_count = $#connected_floppy_vms;
$floppy_count += 1;
if($opt_type eq 'detail-hosts') {
push @jump_tags,"VM(s) w/connected Floppy(s)
\n";
} else {
push @jump_tags," VM(s) w/connected Floppy(s)
\n"; }
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "$floppy_count VM(s) w/connected Floppy(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM |
\n";
foreach (@connected_floppy_vms) {
print REPORT_OUTPUT "",$_," |
\n";
}
print REPORT_OUTPUT "
\n";
}
@connected_floppy_vms = ();
}
sub printVMNetwork {
####################################
# PRINT VM NETWORK SUMMARY
####################################
if(%net_vms) {
push @jump_tags," VM(s) Network Summary
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "VM(s) Network Summary:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM | IP(s) | MAC ADDRESS | PORTGROUP | CONNECTED |
\n";
foreach ( sort keys %net_vms ) {
my $vm_net = $net_vms{$_};
print REPORT_OUTPUT "",$_," | ",$vm_net,"
\n";
}
print REPORT_OUTPUT "
\n";
}
%net_vms = ();
}
sub printVMDatastore {
####################################
# PRINT VM DISK/DATASTORE SUMMARY
####################################
if(%vms_storage) {
push @jump_tags," VM(s) Storage Summary
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "VM(s) Storage Summary:
\n";
print REPORT_OUTPUT "COLOR LEGEND | YELLOW < $yellow_warn % | ORANGE < $orange_warn % | RED < $red_warn % |
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM | DATASTORE | DISK INFO | FREE SPACE | CAPACITY | % FREE |
|
\n";
foreach ( sort keys %vms_storage ) {
my $vm_ds = $vms_storage{$_};
my $vm_disk = $vms_disks{$_};
if(!$vm_disk) {
$vm_disk = "not available | ";
}
print REPORT_OUTPUT "",$_," | ",$vm_ds," | ",$vm_disk,"
\n";
}
print REPORT_OUTPUT "
\n";
}
%vms_storage = ();
}
sub printLimitedVMInfo {
my ($host) = @_;
my $hostName;
if($enable_demo_mode eq 1) { $hostName = $randomHostName;
} else { $hostName = $host->summary->config->name; }
###########################
# PRINT LIMITED VM SUMMARY
###########################
my $seen_vm = 0;
push @jump_tags," Virtual Machines
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "Virtual Machines:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VM | HOSTNAME | POWER STATE | # OF DISK(s) | # OF vCPU(s) | MEM | VMX LOCATION |
\n";
my $vm_views = Vim::get_views (mo_ref_array => $host->vm);
foreach my $vm (@$vm_views) {
#skip if vm is disconnected
next if(!defined($vm->config));
print REPORT_OUTPUT "";
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "",$vm->config->name," | ";
print REPORT_OUTPUT "HIDE ME! | ";
}
else {
print REPORT_OUTPUT "",$vm->config->name," | ";
if (defined($vm->guest->hostName)) {print REPORT_OUTPUT "",$vm->guest->hostName," | "; }
else { print REPORT_OUTPUT "UNKNOWN | "; }
}
$seen_vm = 1;
print REPORT_OUTPUT "",$vm->runtime->powerState->val," | ";
if (defined($vm->summary->config->numVirtualDisks)) {print REPORT_OUTPUT "",$vm->summary->config->numVirtualDisks," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->summary->config->numCpu)) {print REPORT_OUTPUT "",$vm->summary->config->numCpu," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->summary->config->memorySizeMB)) {print REPORT_OUTPUT "",prettyPrintData($vm->summary->config->memorySizeMB,'M')," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
print REPORT_OUTPUT "",$vm->config->files->vmPathName," | ";
print REPORT_OUTPUT "
\n";
#retrieve vms w/connected CDROM/FLOPPY
my $devices = $vm->config->hardware->device;
foreach my $device (@$devices) {
my $device_name = $device->deviceInfo->label;
if ( ($device->isa('VirtualCdrom')) && ($device->connectable->connected == 1) ) {
if($seen_vm eq 1) {
push @connected_cdrom_vms,$vm->config->name;
}
}
if ( ($device->isa('VirtualFloppy')) && ($device->connectable->connected == 1) ) {
if($seen_vm eq 1) {
push @connected_floppy_vms,$vm->config->name;
}
}
if ( ($device->isa('VirtualDisk')) && ($device->backing->isa('VirtualDiskRawDiskMappingVer1BackingInfo')) ) {
if($seen_vm eq 1) {
my $vm_name = $vm->config->name;
my $compat_mode = $device->backing->compatibilityMode;
my $vmhba = $device->backing->deviceName;
my $disk_mode = $device->backing->diskMode;
my $lun_uuid = $device->backing->lunUuid;
my $vm_uuid = $device->backing->uuid;
my $rdm_string = "";
if(!$vm_uuid) { $vm_uuid="N/A"; }
$rdm_string="$vm_name | $compat_mode | $vmhba | $disk_mode | $lun_uuid | $vm_uuid | ";
push @rdm_vms,$rdm_string;
}
}
}
#retrieve vms w/NPIV
my $nwwns = $vm->config->npivNodeWorldWideName;
my $pwwns = $vm->config->npivPortWorldWideName;
my $n_type = $vm->config->npivWorldWideNameType;
if( ($nwwns) && ($seen_vm eq 1) ) {
my $npiv_string = "";
my $n_vm = $vm->config->name;
$npiv_string .= "$n_vm | ";
$npiv_string .= "";
foreach (@$nwwns) {
my $nwwn = (Math::BigInt->new($_))->as_hex();
$nwwn =~ s/^..//;
$nwwn = join(':', unpack('A2' x 8, $nwwn));
if($enable_demo_mode eq 1) {
$npiv_string .= "XX:XX:XX:XX:XX:XX:XX:XX ";
}
else {
$npiv_string .= "$nwwn ";
}
}
$npiv_string .= " | ";
foreach (@$pwwns) {
my $pwwn = (Math::BigInt->new($_))->as_hex();
$pwwn =~ s/^..//;
$pwwn = join(':', unpack('A2' x 8, $pwwn));
if($enable_demo_mode eq 1) {
$npiv_string .= "XX:XX:XX:XX:XX:XX:XX:XX ";
}
else {
$npiv_string .= "$pwwn ";
}
}
if($n_type eq 'vc') { $n_type = "Virtual Center"; }
elsif($n_type eq 'external') { $n_type = "External Source"; }
elsif($n_type eq 'host') { $n_type = "ESX or ESXi"; }
$npiv_string .= " | $n_type | ";
push @npiv_vms,$npiv_string;
}
#retrieve vms w/snapshots
if(defined($vm->snapshot)) {
if($seen_vm eq 1) {
print_tree ($vm->config->name,$vm->snapshot->currentSnapshot, $vm->snapshot->rootSnapshotList);
}
}
}
print REPORT_OUTPUT "
\n";
}
sub printHostVM {
my ($local_hosts) = @_;
###########################
# PRINT VM SUMMARY
###########################
my $seen_vm = 0;
push @jump_tags," Virtual Machines
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "Virtual Machines:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "ESX/ESXi HOST | VM | HOSTNAME | VM STATUS | CONNECTION STATE | FT STATE | RECORD/REPLAY STATE | POWER STATE | # OF DISK(s) | # OF vCPU(s) | MEM | CPU USAGE | MEM USAGE | CPU RESRV | MEM RESRV | # OF vNIC(s) | VMware Tools Status | TIME SYNC w/HOST | TOOLS VER | TOOLS UPGRADE POLICY | TOOLS MOUNTED | GUEST OS | IS TEMPLATE | CLEAN LAST POWEROFF |
\n";
foreach my $host (@$local_hosts) {
my $vm_views = Vim::get_views (mo_ref_array => $host->vm);
#clear seen vms hash
foreach my $vm (@$vm_views) {
#skip if vm is disconnected
next if(!defined($vm->config));
print REPORT_OUTPUT "";
my $vm_host_view = Vim::get_view(mo_ref=>$vm->summary->runtime->host, properties => ['name']);
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "HIDE ME! | ";
print REPORT_OUTPUT "",$vm->config->name," | ";
print REPORT_OUTPUT "HIDE ME! | ";
}
else {
print REPORT_OUTPUT "",$vm_host_view->name," | ";
print REPORT_OUTPUT "",$vm->config->name," | ";
if (defined($vm->guest->hostName)) {print REPORT_OUTPUT "",$vm->guest->hostName," | "; }
else { print REPORT_OUTPUT "UNKNOWN | "; }
}
$seen_vm = 1;
my $vm_health = $vm->summary->overallStatus->val;
if ($vm_health eq 'green') { print REPORT_OUTPUT "VM is OK | "; }
elsif ($vm_health eq 'red') { print REPORT_OUTPUT "VM has a problem | "; }
elsif ($vm_health eq 'yellow') { print REPORT_OUTPUT "VM"; }
else { print REPORT_OUTPUT "UNKNOWN | "; }
print REPORT_OUTPUT "",$vm->runtime->connectionState->val," | ";
print REPORT_OUTPUT "",$vm->runtime->faultToleranceState->val," | ";
print REPORT_OUTPUT "",$vm->runtime->recordReplayState->val," | ";
print REPORT_OUTPUT "",$vm->runtime->powerState->val," | ";
if (defined($vm->summary->config->numVirtualDisks)) {print REPORT_OUTPUT "",$vm->summary->config->numVirtualDisks," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->summary->config->numCpu)) {print REPORT_OUTPUT "",$vm->summary->config->numCpu," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->summary->config->memorySizeMB)) {print REPORT_OUTPUT "",prettyPrintData($vm->summary->config->memorySizeMB,'M')," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
my $isTemplate = $vm->config->template;
if (!$isTemplate) {
if (defined($vm->summary->quickStats->overallCpuUsage)) {print REPORT_OUTPUT "",prettyPrintData($vm->summary->quickStats->overallCpuUsage,'MHZ')," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->summary->quickStats->guestMemoryUsage)) {print REPORT_OUTPUT "",prettyPrintData($vm->summary->quickStats->guestMemoryUsage,'M')," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->summary->config->cpuReservation)) {print REPORT_OUTPUT "",prettyPrintData($vm->summary->config->cpuReservation,'MHZ')," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->summary->config->memoryReservation)) {print REPORT_OUTPUT "",prettyPrintData($vm->summary->config->memoryReservation,'M')," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
}
else {
print REPORT_OUTPUT "N/A | ";
print REPORT_OUTPUT "N/A | ";
print REPORT_OUTPUT "N/A | ";
print REPORT_OUTPUT "N/A | ";
}
if (defined($vm->summary->config->numEthernetCards)) {print REPORT_OUTPUT "",$vm->summary->config->numEthernetCards," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (! $isTemplate) {
if (defined($vm->summary->guest->toolsVersionStatus)) {print REPORT_OUTPUT "",$vm->summary->guest->toolsVersionStatus," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->config->tools->syncTimeWithHost)) { print REPORT_OUTPUT "",($vm->config->tools->syncTimeWithHost) ? "YES" : "NO"," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->config->tools->toolsVersion)) {print REPORT_OUTPUT "",$vm->config->tools->toolsVersion," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
if (defined($vm->config->tools->toolsUpgradePolicy)) {print REPORT_OUTPUT "",$vm->config->tools-> toolsUpgradePolicy," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
print REPORT_OUTPUT "",($vm->runtime->toolsInstallerMounted) ? "YES" : "NO" ," | ";
if (defined($vm->summary->guest->guestFullName)) {print REPORT_OUTPUT "",$vm->summary->guest->guestFullName," | "; }
else {print REPORT_OUTPUT "UNKNOWN | "; }
}
else {
print REPORT_OUTPUT "N/A | ";
print REPORT_OUTPUT "N/A | ";
print REPORT_OUTPUT "N/A | ";
print REPORT_OUTPUT "N/A | ";
print REPORT_OUTPUT "N/A | ";
print REPORT_OUTPUT "N/A | ";
}
print REPORT_OUTPUT "",($isTemplate) ? "YES" : "NO" ," | ";
print REPORT_OUTPUT "",($vm->summary->runtime->cleanPowerOff) ? "YES" : "NO" ," | ";
print REPORT_OUTPUT " |
\n";
#retrieve vms w/connected CDROM/FLOPPY
my $devices = $vm->config->hardware->device;
foreach my $device (@$devices) {
my $device_name = $device->deviceInfo->label;
if ( ($device->isa('VirtualCdrom')) && ($device->connectable->connected == 1) ) {
if($seen_vm eq 1) {
push @connected_cdrom_vms,$vm->config->name;
}
}
if ( ($device->isa('VirtualFloppy')) && ($device->connectable->connected == 1) ) {
if($seen_vm eq 1) {
push @connected_floppy_vms,$vm->config->name;
}
}
if ( ($device->isa('VirtualDisk')) && ($device->backing->isa('VirtualDiskRawDiskMappingVer1BackingInfo')) ) {
if($seen_vm eq 1) {
my $vm_name = $vm->config->name;
my $compat_mode = $device->backing->compatibilityMode;
my $vmhba = $device->backing->deviceName;
my $disk_mode = $device->backing->diskMode;
my $lun_uuid = $device->backing->lunUuid;
my $vm_uuid = $device->backing->uuid;
my $rdm_string = "";
if(!$vm_uuid) { $vm_uuid="N/A"; }
$rdm_string="$vm_name | $compat_mode | $vmhba | $disk_mode | $lun_uuid | $vm_uuid | ";
push @rdm_vms,$rdm_string;
}
}
}
#retrieve vms w/NPIV
my $nwwns = $vm->config->npivNodeWorldWideName;
my $pwwns = $vm->config->npivPortWorldWideName;
my $n_type = $vm->config->npivWorldWideNameType;
if( ($nwwns) && ($seen_vm eq 1) ) {
my $npiv_string = "";
my $n_vm = $vm->config->name;
$npiv_string .= "$n_vm | ";
$npiv_string .= "";
foreach (@$nwwns) {
my $nwwn = (Math::BigInt->new($_))->as_hex();
$nwwn =~ s/^..//;
$nwwn = join(':', unpack('A2' x 8, $nwwn));
if($enable_demo_mode eq 1) {
$npiv_string .= "XX:XX:XX:XX:XX:XX:XX:XX ";
}
else {
$npiv_string .= "$nwwn ";
}
}
$npiv_string .= " | ";
foreach (@$pwwns) {
my $pwwn = (Math::BigInt->new($_))->as_hex();
$pwwn =~ s/^..//;
$pwwn = join(':', unpack('A2' x 8, $pwwn));
if($enable_demo_mode eq 1) {
$npiv_string .= "XX:XX:XX:XX:XX:XX:XX:XX ";
}
else {
$npiv_string .= "$pwwn ";
}
}
if($n_type eq 'vc') { $n_type = "Virtual Center"; }
elsif($n_type eq 'external') { $n_type = "External Source"; }
elsif($n_type eq 'host') { $n_type = "ESX or ESXi"; }
$npiv_string .= " | $n_type | ";
push @npiv_vms,$npiv_string;
}
#retrieve vms w/snapshots
if(defined($vm->snapshot)) {
if($seen_vm eq 1) {
print_tree ($vm->config->name,$vm->snapshot->currentSnapshot, $vm->snapshot->rootSnapshotList);
}
}
#retrieve datastore summary from VM
my $vm_datastore_view = $vm->datastore;
foreach (@$vm_datastore_view) {
if($seen_vm eq 1) {
my $ds = Vim::get_view(mo_ref => $_, properties => ['summary.name']);
$vms_storage{$vm->config->name} = $ds->{'summary.name'};
}
}
#retrieve disk summary from VM
my $disks = $vm->guest->disk;
my $vm_name;
my $disk_string = "";
foreach my $disk (@$disks) {
if($seen_vm eq 1) {
$vm_name = $vm->config->name;
my $vm_disk_path = $disk->diskPath;
my $vm_disk_free = prettyPrintData($disk->freeSpace,'B');
my $vm_disk_cap = prettyPrintData($disk->capacity,'B');
my $vm_perc_free = &restrict_num_decimal_digits((($disk->freeSpace / $disk->capacity) * 100),2);
my $perc_string = getColor($vm_perc_free);
$disk_string .= "$vm_disk_path | $vm_disk_free | $vm_disk_cap | $perc_string
| ";
}
}
if(defined($vm_name)) {
$vms_disks{$vm_name} = $disk_string;
}
#retrieve network summary from VM
my $vm_nets = $vm->guest->net;
my $vm_conn_string = "";
my $vm_ip_string = "";
my $vm_mac_string = "";
my $vm_pg_string = "";
foreach my $vm_net (@$vm_nets) {
if($seen_vm eq 1) {
$execute_flag = 1;
my $net_conn = $vm_net->connected;
if($net_conn eq '1') { $net_conn = "YES"; } else { $net_conn = "NO"; }
$vm_conn_string .= $net_conn."
";
my $ip_arr = $vm_net->ipAddress;
foreach (@$ip_arr) {
if($enable_demo_mode eq 1) {
$vm_ip_string .= "HIDE ME!
";
}
else {
$vm_ip_string .= $_."
";
}
}
my $net_mac = $vm_net->macAddress;
my $net_pg = $vm_net->network;
if($enable_demo_mode eq 1) {
$net_mac .= "HIDE MY MAC!
";
$vm_pg_string .= "HIDE MY PG!
";
}
else {
$vm_mac_string .= $net_mac."
";
$vm_pg_string .= $net_pg."
";
}
if($vm_ip_string eq '') { $vm_ip_string="UNKNOWN
"; }
if($vm_mac_string eq '') { $vm_mac_string="UNKNOWN
"; }
if($vm_pg_string eq '') { $vm_pg_string="UNKNOWN
"; }
if($vm_conn_string eq '') { $vm_conn_string="UNKNOWN
"; }
}
}
#could not retrieve network info (no VMware tools or not online)
if(!@$vm_nets) {
$vm_ip_string="UNKNOWN
";
$vm_mac_string="UNKNOWN
";
$vm_pg_string="UNKNOWN
";
$vm_conn_string="UNKNOWN
";
}
if($execute_flag eq 1) {
$net_vms{$vm->config->name} = "".$vm_ip_string." | ".$vm_mac_string." | ".$vm_pg_string." | ".$vm_conn_string." | ";
$execute_flag = 0;
}
$seen_vm = 0;
}
}
print REPORT_OUTPUT "
\n";
}
sub printHostDatastoreInfo {
my ($local_hosts) = @_;
###########################
# PRINT DATASTORE SUMMARY
###########################
push @jump_tags," ESX/ESXi Datastore(s)
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi Datastore(s):
\n";
print REPORT_OUTPUT "COLOR LEGEND | YELLOW < $yellow_warn % | ORANGE < $orange_warn % | RED < $red_warn % |
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "DATASTORE | CAPACITY | CONSUMED | FREE | % FREE | UNCOMMITTED | DS TYPE | HOST(s) NOT ACCESSIBLE TO DATASTORE |
\n";
my @datastores_seen = ();
my %datastores = ();
my %datastore_row_info = ();
my $ctr = 0;
foreach my $host (@$local_hosts) {
my $ds_views = Vim::get_views (mo_ref_array => $host->datastore);
foreach my $ds (sort {$a->info->name cmp $b->info->name} @$ds_views) {
my $ds_row = "";
if($ds->summary->accessible) {
#capture unique datastores seen in cluster
if (!grep {$_ eq $ds->info->name} @datastores_seen) {
push @datastores_seen,$ds->info->name;
my $perc_free;
my $perc_string = "";
my $ds_used;
my $ds_free;
my $ds_cap;
my $ds_uncommit;
if ( ($ds->summary->freeSpace gt 0) || ($ds->summary->capacity gt 0) ) {
$ds_cap = &restrict_num_decimal_digits($ds->summary->capacity/1024/1000,2);
$ds_used = prettyPrintData(($ds->summary->capacity - $ds->summary->freeSpace),'B');
$ds_free = &restrict_num_decimal_digits(($ds->summary->freeSpace/1024/1000),2);
if($ds->summary->uncommitted) {
$ds_uncommit = prettyPrintData(($ds->summary->uncommitted),'B');
} else { $ds_uncommit = "N/A"; }
$perc_free = &restrict_num_decimal_digits(( 100 * $ds_free / $ds_cap),2);
$perc_string = getColor($perc_free);
}
else {
$perc_free = "UNKNOWN";
$ds_used = "UNKNOWN";
$ds_free = "UNKNOWN";
$ds_uncommit = "UNKNOWN";
}
$ds_row = "".(prettyPrintData($ds->summary->capacity,'B'))." | ".$ds_used." | ".prettyPrintData($ds->summary->freeSpace,'B')." | $perc_string$ds_uncommit | ".$ds->summary->type." | ";
$datastore_row_info{$ds->info->name} = $ds_row;
#capture VM dir contents w/delta files
my $browser = Vim::get_view (mo_ref => $ds->browser);
my $ds_path = "[" . $ds->info->name . "]";
my $file_query = FileQueryFlags->new(fileOwner => 0, fileSize => 1,fileType => 0,modification => 1);
my $searchSpec = HostDatastoreBrowserSearchSpec->new(details => $file_query,matchPattern => ["*.vmsn", "*-delta.vmdk"]);
my $search_res = $browser->SearchDatastoreSubFolders(datastorePath => $ds_path,searchSpec => $searchSpec);
if ($search_res) {
foreach my $result (@$search_res) {
my $files = $result->file;
if ($files) {
foreach my $file (@$files) {
if($file->path =~ /-delta.vmdk/ ) {
my ($vm_snapshot_date,$vm_snapshot_time) = split('T',$file->modification);
#my $todays_date =`date +\%Y-\%m-\%d`;
my $todays_date = giveMeDate('YMD');
chomp($todays_date);
my $diff = days_between($vm_snapshot_date, $todays_date);
my $snap_time = $vm_snapshot_date." ".$vm_snapshot_time;
setSnapColor($diff,$result->folderPath,$file->path,$file->fileSize,$snap_time);
}
}
}
}
}
}
$datastores{$ds->info->name} .= $host->summary->config->name. "_" . $ctr++ .",";
}
}
}
#logic to check which hosts can see all datastores
while ( my ($ds, $value) = each(%datastores) ) {
my @pairs = split(',',$value);
my $pair_count = @pairs;
my @hosts_to_datastores = ();
for (my $x=0;$x < $pair_count;$x++) {
(my $hostname,my $count) = split('_',$pairs[$x],2);
push @hosts_to_datastores, $hostname;
}
#logic to figure out which hosts can not see this datastore
my @intersection = ();
my @difference = ();
my %count = ();
foreach my $element (@hosts_to_datastores, @hosts_seen) { $count{$element}++ }
foreach my $element (keys %count) {
push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
}
my $print_string = "";
if(@difference) {
foreach (@difference) {
$print_string .= $_." ";
}
}
if($print_string eq '') {
$print_string = "Accessible by all hosts in this cluster | ";
} else {
if($enable_demo_mode eq 1) {
$print_string .= "HIDE ME! | ";
}
else {
$print_string = "".$print_string." | ";
}
}
$datastore_row_info{$ds} .= $print_string;
@hosts_to_datastores = ();
}
#final print of datastore summary
for my $datastore ( sort keys %datastore_row_info ) {
my $value = $datastore_row_info{$datastore};
print REPORT_OUTPUT "",$datastore," | ",$value,"
\n";
}
print REPORT_OUTPUT "
\n";
}
#http://www.perlmonks.org/?node_id=17057
sub days_between {
my ($start, $end) = @_;
my ($y1, $m1, $d1) = split ("-", $start);
my ($y2, $m2, $d2) = split ("-", $end);
my $diff = mktime(0,0,0, $d2-1, $m2-1, $y2 - 1900) - mktime(0,0,0, $d1-1, $m1-1, $y1 - 1900);
return $diff / (60*60*24);
}
sub printHostLun {
my ($local_hosts) = @_;
my %lun_row_info = ();
my %luns = ();
foreach my $host (@$local_hosts) {
my $luns = $host->config->storageDevice->scsiLun;
foreach (sort {$a->canonicalName cmp $b->canonicalName} @$luns) {
my $lun_row = "";
if($_->isa('HostScsiDisk')) {
$luns{$_->uuid} .= $host->summary->config->name . "_" . $_->canonicalName . "," ;
$lun_row .= "".$_->canonicalName." | ";
if($_->queueDepth) { $lun_row .= "".$_->queueDepth." | N/A"; }
my $state_string = "";
my $states = $_->operationalState;
foreach (@$states) {
$state_string .= $_." ";
}
$lun_row .= "".$state_string." | ".$_->vendor." | ";
$lun_row_info{$_->uuid} = $lun_row;
}
}
}
#logic to check which hosts can see all luns
while ( my ($uuid, $value) = each(%luns) ) {
my @pairs = split(',',$value);
my $pair_count = @pairs;
my @hosts_to_luns = ();
for (my $x=0;$x < $pair_count;$x++) {
(my $hostname,my $vmhba) = split('_',$pairs[$x],2);
push @hosts_to_luns, $hostname;
}
#logic to figure out which hosts can not see this datastore
my @intersection = ();
my @difference = ();
my %count = ();
foreach my $element (@hosts_to_luns, @hosts_seen) { $count{$element}++ }
foreach my $element (keys %count) {
push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
}
my $print_string = "";
if(@difference) {
foreach (@difference) {
$print_string .= $_." ";
}
}
if($print_string eq '') {
$print_string = "Accessible by all hosts in this cluster | ";
} else {
if($enable_demo_mode eq 1) {
$print_string .= "HIDE ME! | ";
}
else {
$print_string = "".$print_string." | ";
}
}
$lun_row_info{$uuid} .= $print_string;
@hosts_to_luns = ();
}
###########################
# PRINT LUN SUMMARY
###########################
push @jump_tags," ESX/ESXi LUN(s)
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi LUN(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "UUID | LUN | QUEUE DEPTH | STATUS | VENDOR | HOST(s) NOT ACCESSIBLE TO LUN |
\n";
for my $lun ( sort keys %lun_row_info ) {
my $value = $lun_row_info{$lun};
print REPORT_OUTPUT "",$lun," | ",$value,"
\n";
}
print REPORT_OUTPUT "
\n";
}
sub printMultipathing {
my ($host) = @_;
my $hostName;
if($enable_demo_mode eq 1) { $hostName = $randomHostName;
} else { $hostName = $host->summary->config->name; }
###########################
# PRINT MULTIPATH SUMMARY
###########################
if($opt_type eq 'detail-hosts') {
push @jump_tags," Disk Multipathing Info
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "Disk Multipathing Info:
\n";
} else { push @jump_tags," ESX/ESXi Disk Multipathing Info
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi Disk Multipathing Info:
\n"; }
print REPORT_OUTPUT "\n";
my $ss = Vim::get_view (mo_ref => $host->configManager->storageSystem);
my $verbose;
my $luns = $ss->storageDeviceInfo->scsiLun;
my $hbas = $ss->storageDeviceInfo->hostBusAdapter;
my $mpLuns = $ss->storageDeviceInfo->multipathInfo->lun;
foreach my $mpLun (@$mpLuns) {
my $paths = $mpLun->path;
my $numPaths = scalar(@$paths);
my $lun = find_by_key($luns, $mpLun->lun);
my $pol = $mpLun->policy;
my $polPrefer;
if (defined($pol) && defined($pol->{prefer})) {
$polPrefer = $pol->prefer;
}
my $cap = $lun->{capacity};
my $deviceUuidPath = defined($lun->{uuid}) ? ("vml." . $lun->uuid) : "";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "",(defined($lun->{lunType}) ? $lun->lunType : "")," ",(defined($lun->{canonicalName}) ? $lun->canonicalName : ""),($verbose ? " $deviceUuidPath" : "")," ",(defined($cap) ? " ( " . int($cap->block * $cap->blockSize / (1024*1024)) . " MB )" : " ( 0 MB )")," == # of Paths: ",$numPaths," Policy: ",((defined($pol) && defined($pol->{policy})) ? $pol->policy : "")," |
\n";
foreach my $path (@$paths) {
my $hba = find_by_key($hbas, $path->adapter);
my $isFC = $hba->isa("HostFibreChannelHba");
my $state = ($path->{pathState} ?
(($path->pathState eq "active") ? "On active" : $path->pathState) : "");
my $pciString = get_pci_string($hba);
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "",($isFC ? "FC" : "Local")," ",$pciString," ","HIDE MY NWWN <-> HIDE MY PWWN"," ",$path->name," ",$state," ",((defined($polPrefer) && ($path->name eq $polPrefer)) ? "preferred" : "")," |
\n";
} else {
print REPORT_OUTPUT "",($isFC ? "FC" : "Local")," ",$pciString," ",($isFC ? $hba->nodeWorldWideName . "<->" . $hba->portWorldWideName : "")," ",$path->name," ",$state," ",((defined($polPrefer) && ($path->name eq $polPrefer)) ? "preferred" : "")," |
\n";
}
}
print REPORT_OUTPUT "
\n";
}
print REPORT_OUTPUT "
\n";
}
sub get_pci_string {
my $hba = shift;
my $pciString = defined($hba) ? $hba->pci : "";
# defect 173631
if ($pciString =~ /([a-fA-F0-9]+):([a-fA-F0-9]+)\.([a-fA-F0-9]+)$/) {
$pciString = hexstr_to_int($1)
. ":" . hexstr_to_int($2)
. "." . hexstr_to_int($3);
}
return $pciString
}
sub hexstr_to_int {
my ($hexstr) = @_;
die "Invalid hex string: $hexstr"
if $hexstr !~ /^[0-9A-Fa-f]{1,8}$/;
my $num = hex($hexstr);
return $num >> 31 ? $num - 2 ** 32 : $num;
}
sub find_by_key {
my ($list, $key) = @_;
foreach my $item (@$list) {
if ($key eq $item->key) {
return $item;
}
}
return undef;
}
sub printHostPortgroup {
my ($local_hosts) = @_;
my @hosts_to_portgroups = ();
my %portgroup_row_info = ();
foreach my $host (@$local_hosts) {
my $portgroup_views = Vim::get_views (mo_ref_array => $host->network);
foreach my $portgroup (sort {$a->summary->name cmp $b->summary->name} @$portgroup_views) {
my $pg_row = "";
if($portgroup->summary->accessible) {
my $host_mounts = $portgroup->host;
foreach (@$host_mounts) {
push @hosts_to_portgroups,$host->name;
}
#logic to figure out which hosts can not see this portgroup
my @intersection = ();
my @difference = ();
my %count = ();
foreach my $element (@hosts_to_portgroups, @hosts_seen) { $count{$element}++ }
foreach my $element (keys %count) {
push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
}
if(@difference) {
my $hosts_not_accessible = "";
foreach (@difference) {
$hosts_not_accessible .= $_." ";
}
if($enable_demo_mode eq 1) {
$pg_row .= "HIDE ME! | ";
} else {
$pg_row .= "$hosts_not_accessible | ";
}
}
else {
$pg_row .= "Accessible by all hosts in this cluster | ";
}
$portgroup_row_info{$portgroup->name} = $pg_row;
}
}
}
@hosts_to_portgroups = ();
#final print of portgroup summary
###########################
# PRINT PORTGROUP SUMMARY
###########################
push @jump_tags," ESX/ESXi Portroup(s)
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "ESX/ESXi Portroup(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "PORTGROUP | HOST(s) NOT ACCESSIBLE TO PORTGROUP |
\n";
for my $portgroup ( sort keys %portgroup_row_info ) {
my $value = $portgroup_row_info{$portgroup};
if($enable_demo_mode eq 1) {
$portgroup = "HIDE MY PG!";
}
print REPORT_OUTPUT "",$portgroup," | ",$value,"
\n";
}
print REPORT_OUTPUT "
\n";
}
sub clusterPG {
my ($cluster) = @_;
my @hosts_in_cluster = ();
my @hosts_in_portgroup = ();
my $pg_row = "";
my $pg_name;
my $hic = Vim::get_views(mo_ref_array => $cluster->host, properties => ['name']);
foreach(@$hic) {
push @hosts_in_cluster,$_->{'name'};
}
my $pg = Vim::get_views(mo_ref_array => $cluster->network);
foreach(@$pg) {
my $hosts = Vim::get_views(mo_ref_array => $_->host, properties => ['name']);
$pg_name = $_->name;
foreach(@$hosts) {
push @hosts_in_portgroup,$_->{'name'};
}
#logic to figure out which hosts can not see this portgroup
my @intersection = ();
my @difference = ();
my %count = ();
foreach my $element (@hosts_in_portgroup, @hosts_in_cluster) { $count{$element}++ }
foreach my $element (keys %count) {
push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
}
my @hosts_not_prop_configured = ();
my @difference_2 = ();
%count = ();
foreach my $element (@difference, @hosts_in_cluster) { $count{$element}++ }
foreach my $element (keys %count) {
push @{ $count{$element} > 1 ? \@hosts_not_prop_configured : \@difference_2 }, $element;
}
if(@hosts_not_prop_configured) {
my $hosts_not_accessible = "";
foreach (@hosts_not_prop_configured) {
$hosts_not_accessible .= $_." ";
}
if($enable_demo_mode eq 1) {
$pg_row .= "HIDE ME! | ";
} else {
$pg_row .= "$hosts_not_accessible | ";
}
} else {
$pg_row .= "Accessible by all hosts in this cluster | ";
}
$portgroup_row_info{$pg_name} = $pg_row;
$pg_row = "";
@hosts_in_portgroup = ();
}
@hosts_in_cluster = ();
}
sub printPG {
#final print of portgroup summary
###########################
# PRINT PORTGROUP SUMMARY
###########################
push @jump_tags," ESX/ESXi Portroup(s)
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "ESX/ESXi Portroup(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "PORTGROUP | HOST(s) NOT ACCESSIBLE TO PORTGROUP |
\n";
for my $portgroup ( sort keys %portgroup_row_info ) {
my $value = $portgroup_row_info{$portgroup};
if($enable_demo_mode eq 1) {
$portgroup = "HIDE MY PG!";
}
print REPORT_OUTPUT "",$portgroup," | ",$value,"
\n";
}
print REPORT_OUTPUT "
\n";
%portgroup_row_info = ();
}
sub getDVS {
my ($cluster) = @_;
my %seen_dvs = ();
my $dvs_target;
my $dvs_string = "";
my $dvs_mgr = Vim::get_view(mo_ref => $content->dvSwitchManager);
if ($content->about->apiType eq 'VirtualCenter') {
my $hosts = Vim::get_views(mo_ref_array => $cluster->host);
foreach my $host (@$hosts) {
$dvs_target = $dvs_mgr->DVSManagerQueryDvsConfigTarget(host => $host);
my $dvs = $dvs_target->distributedVirtualSwitch;
if($dvs) {
foreach(@$dvs) {
my $sName = defined $_->switchName ? $_->switchName : "N/A";
$seen_dvs{$sName} = 1;
if($seen_dvs{$sName} eq 1 ) {
my $sUuid = defined $_->switchUuid ? $_->switchUuid : "N/A";
my $dv_switch = Vim::get_view(mo_ref => $_->distributedVirtualSwitch);
my $desc = defined $dv_switch->summary->description ? $dv_switch->summary->description : "N/A";
my $contact_name = defined $dv_switch->summary->contact->name ? $dv_switch->summary->contact->name : "N/A";
my $contact_con = defined $dv_switch->summary->contact->contact ? $dv_switch->summary->contact->contact : "";
my $contact_info = $contact_name . " " . $contact_con;
my $build = defined $dv_switch->summary->productInfo->build ? $dv_switch->summary->productInfo->build : "N/A";
my $bid = defined $dv_switch->summary->productInfo->bundleId ? $dv_switch->summary->productInfo->bundleId : "N/A";
my $burl = defined $dv_switch->summary->productInfo->bundleUrl ? $dv_switch->summary->productInfo->bundleUrl : "N/A";
my $fclass = defined $dv_switch->summary->productInfo->forwardingClass ? $dv_switch->summary->productInfo->forwardingClass : "N/A";
my $vendor = defined $dv_switch->summary->productInfo->vendor ? $dv_switch->summary->productInfo->vendor : "N/A";
my $version = defined $dv_switch->summary->productInfo->version ? $dv_switch->summary->productInfo->version : "N/A";
my $ports = defined $dv_switch->summary->numPorts ? $dv_switch->summary->numPorts : "N/A";
$dvs_string = "".$sName." | ".$desc." | ".$contact_info." | ".$vendor." | ".$version." | ".$sUuid." | ".$build." | ".$bid." | ".$build." | ".$burl." | ".$fclass." | ".$ports." |
\n";
push @dvs, $dvs_string;
}
}
}
}
}
}
sub printDVS {
###########################
# PRINT DVS SUMMARY
###########################
if(@dvs) {
push @jump_tags," ESX/ESXi Distributed vSwitch(s)
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "ESX/ESXi Distributed vSwitch(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "NAME | DESCRIPTION | CONTACT INFO | VENDOR | VERSION | UUID | BUILD | BUNDLE ID | BUNDLE BUILD | BUNDLE URL | FORWARDING CLASS | PORTS |
\n";
foreach(@dvs) {
print REPORT_OUTPUT $_;
}
print REPORT_OUTPUT "
\n";
}
@dvs = ();
}
sub printHostHardwareInfo {
my ($local_hosts) = @_;
###########################
# PRINT HOST HARDWARE
###########################
push @jump_tags," ESX/ESXi hardware configuration
\n";
print REPORT_OUTPUT "
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "HOSTNAME | VENDOR | ADDITIONAL VENDOR INFO | CPU INFO | HT AVAILABLE/ENABLED | CPU SPEED | CPU USAGE | CPU PACKAGE(s) | CPU CORE(s) | CPU THREAD(s) | MEMORY | MEMORY USAGE | NIC(s) | HBA(s) |
\n";
print REPORT_OUTPUT "ESX/ESXi hardware configuration:
\n";
foreach my $local_host (sort {$a->summary->config->name cmp $b->summary->config->name} @$local_hosts) {
print REPORT_OUTPUT "";
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "HIDE ME! | ";
}
else {
print REPORT_OUTPUT "",$local_host->summary->config->name," | ";
}
print REPORT_OUTPUT "",$local_host->summary->hardware->vendor," | ";
my $additional_vendor_info = "";
if($local_host->summary->hardware->otherIdentifyingInfo) {
my $add_info = $local_host->summary->hardware->otherIdentifyingInfo;
foreach (@$add_info) {
$additional_vendor_info .= $_->identifierType->key.": ".$_->identifierValue." ";
}
if($additional_vendor_info eq '') {
$additional_vendor_info = "UNKNOWN";
}
}
print REPORT_OUTPUT "",$additional_vendor_info," | ";
print REPORT_OUTPUT "",$local_host->summary->hardware->cpuModel," | ";
print REPORT_OUTPUT "",($local_host->config->hyperThread->available) ? "YES" : "NO"," / ";
print REPORT_OUTPUT ($local_host->config->hyperThread->active) ? "YES" : "NO"," | ";
print REPORT_OUTPUT "",prettyPrintData($local_host->summary->hardware->numCpuCores*$local_host->summary->hardware->cpuMhz,'MHZ')," | ";
print REPORT_OUTPUT "",prettyPrintData($local_host->summary->quickStats->overallCpuUsage,'MHZ')," | ";
print REPORT_OUTPUT "",$local_host->summary->hardware->numCpuPkgs," | ";
print REPORT_OUTPUT "",$local_host->summary->hardware->numCpuCores," | ";
print REPORT_OUTPUT "",$local_host->summary->hardware->numCpuThreads," | ";
print REPORT_OUTPUT "",prettyPrintData($local_host->summary->hardware->memorySize,'B')," | ";
print REPORT_OUTPUT "",prettyPrintData($local_host->summary->quickStats->overallMemoryUsage,'M')," | ";
print REPORT_OUTPUT "",$local_host->summary->hardware->numNics," | ";
print REPORT_OUTPUT "",$local_host->summary->hardware->numHBAs," | ";
print REPORT_OUTPUT "
\n";
#capture unique hosts for later use
push @hosts_seen,$local_host->summary->config->name;
#get health
getHealthInfo($local_host);
#get nic
getNICInfo($local_host);
#get hba
getHBAInfo($local_host);
}
print REPORT_OUTPUT "
\n";
###########################
# PRINT HEALTH STATUS
###########################
printHealth();
###########################
# PRINT NIC INFO
###########################
printNIC();
###########################
# PRINT HBA INFO
###########################
printHBA();
###########################
# PRINT HOST STATE
###########################
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi state:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "HOSTNAME | OVERALL STATUS | POWER STATE | CONNECTION STATE | MAINTENANCE MODE | VMOTION ENABLED | VERSION |
\n";
foreach my $local_host (sort {$a->summary->config->name cmp $b->summary->config->name} @$local_hosts) {
print REPORT_OUTPUT "";
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "HIDE ME! | ";
}
else {
print REPORT_OUTPUT "",$local_host->summary->config->name," | ";
}
my $host_health = $local_host->overallStatus->val;
if ($host_health eq 'green') { print REPORT_OUTPUT "HOST is OK | "; }
elsif ($host_health eq 'red') { print REPORT_OUTPUT "HOST has a problem | "; }
elsif ($host_health eq 'yellow') { print REPORT_OUTPUT "HOST might have a problem | "; }
else { print REPORT_OUTPUT "UNKNOWN | "; }
print REPORT_OUTPUT "",$local_host->runtime->powerState->val," | ";
print REPORT_OUTPUT "",$local_host->runtime->connectionState->val," | ";
print REPORT_OUTPUT "",($local_host->summary->runtime->inMaintenanceMode) ? "YES" : "NO" ," | ";
print REPORT_OUTPUT "",($local_host->summary->config->vmotionEnabled) ? "YES" : "NO" ," | ";
print REPORT_OUTPUT "",${$local_host->summary->config->product}{'fullName'}," | ";
print REPORT_OUTPUT "
\n";
}
print REPORT_OUTPUT "
\n";
###########################
# PRINT HOST CONFIG
###########################
if($opt_type ne 'detail-hosts') {
print REPORT_OUTPUT "\n";
push @jump_tags," ESX/ESXi Configurations
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi Configurations:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "HOSTNAME | UUID | SERVICE CONSOLE MEMORY | AUTOSTART MANAGER | Disk.UseDeviceReset | Disk.UseLunReset | Disk.SchedNumReqOutstanding |
\n";
}
foreach my $local_host (sort {$a->summary->config->name cmp $b->summary->config->name} @$local_hosts) {
if($enable_demo_mode eq 1) { $randomHostName = "ESX-DEV-HOST-".int(rand(100)).".primp-industries.com"; }
if($opt_type eq 'detail-hosts') {
my $hostName;
if($enable_demo_mode eq 1) { $hostName = $randomHostName;
} else { $hostName = $local_host->summary->config->name; }
print REPORT_OUTPUT "
\n";
push @jump_tags," $hostName configurations
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "$hostName configurations:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "HOSTNAME | UUID | SERVICE CONSOLE MEMORY | AUTOSTART MANAGER | Disk.UseDeviceReset | Disk.UseLunReset | Disk.SchedNumReqOutstanding |
\n";
}
print REPORT_OUTPUT "";
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "HIDE ME! | ";
}
else {
print REPORT_OUTPUT "",$local_host->summary->config->name," | ";
}
print REPORT_OUTPUT "",$local_host->summary->hardware->uuid," | ";
if(defined($local_host->config->consoleReservation)) {
print REPORT_OUTPUT "",prettyPrintData($local_host->config->consoleReservation->serviceConsoleReserved,'B')," | ";
}
else {
print REPORT_OUTPUT "UNKNOWN | ";
}
print REPORT_OUTPUT "",($local_host->config->autoStart->defaults->enabled) ? "YES" : "NO"," | ";
#advconfigs
my $advconfigs = Vim::get_view (mo_ref => $local_host->configManager->advancedOption);
my $options_ref = $advconfigs->setting;
my $d_udr = "UNKNOWN";
my $d_ulr = "UNKNOWN";
my $d_snro = "UNKNOWN";
foreach my $option (@$options_ref) {
my $key = $option->key;
my $value = $option->value;
if($key eq 'Disk.UseDeviceReset') { $d_udr = $value; }
if($key eq 'Disk.UseLunReset') { $d_ulr = $value; }
if($key eq 'Disk.SchedNumReqOutstanding') { $d_snro = $value; }
}
print REPORT_OUTPUT "",$d_udr," | ",$d_ulr," | ",$d_snro," | ";
if($opt_type eq 'detail-hosts') {
print REPORT_OUTPUT "
\n";
print REPORT_OUTPUT "
\n";
printDetailHostConfigurations($local_host);
printLimitedVMInfo($local_host);
}
elsif($opt_type eq 'host') {
printDetailHostConfigurations($local_host);
}
}
if($opt_type ne 'detail-hosts') {
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "\n";
}
}
sub printDetailHostConfigurations {
my ($host) = @_;
print REPORT_OUTPUT "
\n";
## SERVICE CONSOLE / VMOTION ##
if ($host->summary->config->vmotionEnabled) {
print REPORT_OUTPUT "VMOTION ENABLED | YES |
\n";
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "IP ADDRESS | X.X.X.X |
\n";
print REPORT_OUTPUT "NETMASK | X.X.X.X |
\n";
} else {
print REPORT_OUTPUT "IP ADDRESS | ",$host->config->vmotion->ipConfig->ipAddress," => ",$host->summary->config->name," |
\n";
print REPORT_OUTPUT "NETMASK | ",$host->config->vmotion->ipConfig->subnetMask," |
\n";
}
}
## GATEWAY ##
my $network_system;
eval { $network_system = Vim::get_view(mo_ref => $host->configManager->networkSystem); };
if(!$@) {
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "GATEWAY | X.X.X.X |
\n";
} else {
if($network_system->consoleIpRouteConfig->defaultGateway) {
print REPORT_OUTPUT "GATEWAY | ",$network_system->consoleIpRouteConfig->defaultGateway," |
\n";
} else { print REPORT_OUTPUT "GATEWAY | 0.0.0.0 |
\n"; }
if($network_system->consoleIpRouteConfig->ipV6DefaultGateway) {
print REPORT_OUTPUT "IPv6 GATEWAY | ",$network_system->consoleIpRouteConfig->ipV6DefaultGateway," |
\n";
} else { print REPORT_OUTPUT "IPv6 GATEWAY | 0.0.0.0 |
\n"; }
if($network_system->ipRouteConfig->defaultGateway) {
print REPORT_OUTPUT "VMKERNEL GATEWAY | ",$network_system->ipRouteConfig->defaultGateway," |
\n";
} else { print REPORT_OUTPUT "VMKERNEL GATEWAY | 0.0.0.0 |
\n"; }
if($network_system->ipRouteConfig->ipV6DefaultGateway) {
print REPORT_OUTPUT "VMKERNEL IPv6 GATEWAY | ",$network_system->ipRouteConfig->ipV6DefaultGateway," |
\n";
} else { print REPORT_OUTPUT "VMKERNEL IPv6 GATEWAY | 0.0.0.0 |
\n"; }
}
}
## SOFTWARE iSCSI ##
print REPORT_OUTPUT "SOFTWAE iSCSI ENABLED | ",($host->config->storageDevice->softwareInternetScsiEnabled ? "YES" : "NO")," |
\n";
## IPV6 ENABLED ##
print REPORT_OUTPUT "IPv6 ENABLED | ",($host->config->network->ipV6Enabled ? "YES" : "NO")," |
\n";
## FT ENABLED ##
print REPORT_OUTPUT "FT ENABLED | ",($host->summary->config->faultToleranceEnabled ? "YES" : "NO")," |
\n";
## SSL THUMBPRINT ##
my $sslprint = defined $host->summary->config->sslThumbprint ? $host->summary->config->sslThumbprint : "N/A";
print REPORT_OUTPUT "SSL THUMBPRINT | ",$sslprint," |
\n";
## DNS ##
my $s_domains = $host->config->network->dnsConfig->searchDomain;
my $s_string = "";
foreach(@$s_domains) {
$s_string .= "search ".$_."
";
}
my $dns_add = $host->config->network->dnsConfig->address;
my $dns_string = "";
foreach(@$dns_add) {
$dns_string .= "nameserver ".$_."
";
}
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "DNS | domain X.domain.com search Y.domain.com nameserver Z.domain.com |
\n";
} else {
print REPORT_OUTPUT "DNS | ","domain ", $host->config->network->dnsConfig->domainName," ",$s_string,$dns_string," |
\n";
}
## UPTIME ##
my ($host_date,$host_time) = split('T',$host->runtime->bootTime);
my $todays_date = giveMeDate('YMD');
chomp($todays_date);
my $up_time = days_between($host_date, $todays_date);
print REPORT_OUTPUT "UPTIME | ",$up_time," Days - ",$host->runtime->bootTime," |
\n";
## OFFLOAD CAPABILITIES ##
my $offload_string = "";
$offload_string .= "".($host->config->offloadCapabilities->csumOffload ? "YES" : "NO")." | ".($host->config->offloadCapabilities->tcpSegmentation ? "YES" : "NO")." | ".($host->config->offloadCapabilities->zeroCopyXmit ? "YES" : "NO")." |
";
print REPORT_OUTPUT "OFFLOAD CAPABILITIES | CHECKSUM | TCP SEGMENTATION | ZERO COPY TRANSMIT | ",$offload_string,"
|
\n";
## DIAGONISTIC PARITION ##
if($host->config->activeDiagnosticPartition) {
my $diag_string = "";
$diag_string .= "".$host->config->activeDiagnosticPartition->diagnosticType." | ".$host->config->activeDiagnosticPartition->id->diskName.$host->config->activeDiagnosticPartition->id->partition." | ".$host->config->activeDiagnosticPartition->storageType." |
";
print REPORT_OUTPUT "DIAGNOSTIC PARTITION | TYPE | PARITION | STORAGE TYPE | ",$diag_string,"
|
\n";
}
## SERVICES ##
my $services = $host->config->service->service;
my $service_string = "";
foreach(@$services) {
$service_string .= "".$_->label." | ".$_->policy." | ".(($_->running) ? "YES" : "NO")." |
";
}
print REPORT_OUTPUT "SERVICE(s) | NAME | POLICY TYPE | RUNNING | ",$service_string,"
|
\n";
## NTP ##
if($host->config->dateTimeInfo) {
my $ntps = $host->config->dateTimeInfo->ntpConfig->server;
my $ntp_string = "";
if($ntps) {
foreach (@$ntps) {
$ntp_string .= "$_
";
}
} else { $ntp_string = "NONE CONFIGURED"; }
$ntp_string = "".$ntp_string." | ";
$ntp_string .= "".$host->config->dateTimeInfo->timeZone->description." | ".$host->config->dateTimeInfo->timeZone->gmtOffset." | ".$host->config->dateTimeInfo->timeZone->name." |
";
print REPORT_OUTPUT "NTP | NTP SERVERS | TIME ZONE | GMT OFFSET | LOCATION | ",$ntp_string,"
|
\n";
}
## VSWIF ##
if($host->config->network->consoleVnic) {
my $vswif_string = "";
my $console_vnics = $host->config->network->consoleVnic;
foreach(@$console_vnics) {
if($enable_demo_mode eq 1) {
$vswif_string .= "".$_->device." | HIDE MY PG | X.X.X.X | ".$_->spec->ip->subnetMask." | ".$_->spec->mac." | ".(($_->spec->ip->dhcp) ? "YES" : "NO")." |
";
} else {
$vswif_string .= "".$_->device." | ".$_->portgroup." | ".$_->spec->ip->ipAddress." | ".$_->spec->ip->subnetMask." | ".$_->spec->mac." | ".(($_->spec->ip->dhcp) ? "YES" : "NO")." |
";
}
}
print REPORT_OUTPUT "VSWIF(s) | NAME | PORTGROUP | IP ADDRESS | NETMASK | MAC | DHCP | ",$vswif_string,"
|
\n";
}
## VMKERNEL ##
if($host->config->network->vnic) {
my $vmk_string = "";
my $vmks = $host->config->network->vnic;
foreach(@$vmks) {
if($enable_demo_mode eq 1) {
$vmk_string .= "".$_->device." | HIDE MY PG | X.X.X.X | ".$_->spec->ip->subnetMask." | ".$_->spec->mac." | ".(($_->spec->ip->dhcp) ? "YES" : "NO")." |
";
} else {
$vmk_string .= "".$_->device." | ".$_->portgroup." | ".$_->spec->ip->ipAddress." | ".$_->spec->ip->subnetMask." | ".$_->spec->mac." | ".(($_->spec->ip->dhcp) ? "YES" : "NO")." |
";
}
}
print REPORT_OUTPUT "VMKERNEL(s) | INTERFACE | PORTGROUP | IP ADDRESS | NETMASK | MAC | DHCP | ",$vmk_string,"
|
\n";
}
## VSWITCH ##
getVswitchInfo($host);
## SNMP ##
my $snmp_system;
eval { $snmp_system = Vim::get_view (mo_ref => $host->configManager->snmpSystem); };
if(!$@) {
if($snmp_system->configuration->enabled) {
my $snmp_string = "";
$snmp_string .= "".$snmp_system->configuration->port." | ".$snmp_system->configuration->readOnlyCommunities." |
";
my $snmp_traps = $snmp_system->configuration->trapTargets;
foreach(@$snmp_traps) {
print "Community: ", $_->commmunity, " Hostname: ", $_->hostName, " Port: ",$_->port,"\n";
}
print REPORT_OUTPUT "SNMP | SNMP PORT | RO COMMUNITIES | TARGETS | ",$snmp_string,"
|
\n";
}
}
## FIREWALL ##
if($host->config->firewall) {
my $fw_sys = $host->config->firewall;
my $fw_rules = $fw_sys->ruleset;
my $fw_known_string = "";
my $fw_rule_string = "";
foreach(@$fw_rules) {
if($_->enabled) {
$fw_known_string .= "".$_->label." |
";
}
}
print REPORT_OUTPUT "FIREWALL KNOWN SERVICES ENABLED | |
\n";
print REPORT_OUTPUT "FIREWALL DEFAULT INCOMING ENABLED | ",($fw_sys->defaultPolicy->incomingBlocked ? "YES" : "NO")," |
\n";
print REPORT_OUTPUT "FIREWALL DEFAULT OUTGOING ENABLED | ",($fw_sys->defaultPolicy->outgoingBlocked ? "YES" : "NO")," |
\n";
}
## CPU POWER MANAGMENT ##
if($host->hardware->cpuPowerManagementInfo) {
my $cpu_power_info = "";
$cpu_power_info .= "".($host->hardware->cpuPowerManagementInfo->currentPolicy)." | ".($host->hardware->cpuPowerManagementInfo->hardwareSupport)." |
";
print REPORT_OUTPUT "CPU POWER MGMT INFO | CURRENT POLICY | HARDWARE SUPPORT | ",$cpu_power_info,"
|
\n";
}
## END OF CUSTOME DETAIL INFO ##
print REPORT_OUTPUT "
\n";
## CDP ##
printCDPInfo($host->name);
## MULTI-PATHING ##
printMultipathing($host);
## HOSTD LOGS ##
printHostdLogs($host);
## LATEST TASK ##
printTasks($host);
}
sub printCDPInfo {
my ($hostName) = @_;
if($cdp_string ne "") {
if($opt_type eq 'detail-hosts') {
push @jump_tags," CDP Info
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "CDP Info:
\n";
} else { push @jump_tags," ESX/ESXi CDP Info
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi CDP Info:
\n"; }
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "DEVICE | MGMT ADDRESS | DEVICE ADDRESS | IP PREFIX | LOCATION | SYSTEM NAME | SYSTEM VERSION | SYSTEM OID | PLATFORM | DEVICE ID | CDP VER | FULL DUPLEX | MTU | TIMEOUT | TTL | VLAN ID | SAMPLES |
\n";
print REPORT_OUTPUT $cdp_string;
print REPORT_OUTPUT "
\n";
}
$cdp_string = "";
}
sub printHostdLogs {
my ($host) = @_;
my $hostName;
if($enable_demo_mode eq 1) { $hostName = $randomHostName;
} else { $hostName = $host->summary->config->name; }
my $logData;
my $logKey = "hostd";
my $diagmgr_view = Vim::get_view(mo_ref => Vim::get_service_content()->diagnosticManager);
if($opt_type eq 'detail-hosts') {
$logData = $diagmgr_view->BrowseDiagnosticLog(key => $logKey, host => $host, start => "999999999");
} else {
$logData = $diagmgr_view->BrowseDiagnosticLog(key => $logKey,start => "999999999");
}
my $lineEnd = $logData->lineEnd;
my $start = $lineEnd - $hostd_log_print;
if($opt_type eq 'detail-hosts') {
$logData = $diagmgr_view->BrowseDiagnosticLog(key => $logKey,host => $host, start => $start,lines => $hostd_log_print);
} else {
$logData = $diagmgr_view->BrowseDiagnosticLog(key => $logKey,start => $start,lines => $hostd_log_print);
}
if ($logData->lineStart != 0) {
if($opt_type eq 'detail-hosts') {
push @jump_tags," Hostd Logs - Last $hostd_log_print lines
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "Hostd Logs - Last $hostd_log_print lines:
\n";
} else { push @jump_tags," ESX/ESXi Hostd Logs - Last $hostd_log_print lines
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi Hostd Logs - Last $hostd_log_print lines:
\n"; }
print REPORT_OUTPUT "\n";
my $hostd_string = "";
foreach my $line (@{$logData->lineText}) {
$hostd_string .= $line."
\n";
}
if($enable_demo_mode eq 1) { $hostd_string = "HIDE MY IMPORTANT LOGS"; }
print REPORT_OUTPUT "",$hostd_string," |
\n";
print REPORT_OUTPUT "
\n";
}
}
sub printTasks {
my ($host) = @_;
my $hostName;
my $task_string;
if($enable_demo_mode eq 1) { $hostName = $randomHostName;
} else { $hostName = $host->summary->config->name; }
my $task_view = Vim::get_view(mo_ref => Vim::get_service_content()->taskManager);
my $tasks = Vim::get_views(mo_ref_array => $task_view->recentTask);
$task_string = "";
foreach(@$tasks) {
my $progress = $_->info->progress;
if(!defined($progress)) {
$progress = "COMPLETED";
}
$task_string .= "".$_->info->descriptionId." | ".$_->info->queueTime." | ".$_->info->startTime." | ".$_->info->completeTime." | ".$progress." | ".$_->info->state->val." |
\n";
}
if($task_string ne "") {
if($opt_type eq 'detail-hosts') {
push @jump_tags," Recent Tasks
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "Recent Tasks:
\n";
} else { push @jump_tags," ESX/ESXi Recent Tasks
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi Recent Tasks:
\n"; }
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "DESCRIPTION | QUEUE TIME | START TIME | COMPLETION TIME | PROGRESS | STATE |
\n";
}
if($task_string ne "") {
if($enable_demo_mode eq 1) { $task_string = "HIDE MY RECENT TASKS"; }
print REPORT_OUTPUT $task_string;
print REPORT_OUTPUT "
\n";
}
}
sub printHBA {
if(@hba_list) {
push @jump_tags," ESX/ESXi HBA(s)
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi HBA(s)
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "HOST | HBA TYPE | DEVICE | PCI | MODEL | DRIVER | STATUS | ADDITIONAL INFO |
\n";
foreach (@hba_list) {
print REPORT_OUTPUT "",$_,"
\n";
}
print REPORT_OUTPUT "
\n";
}
@hba_list = ();
}
sub printNIC {
if(@nic_list) {
push @jump_tags," ESX/ESXi NIC(s)
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi NIC(s)
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "HOST | DEVICE | PCI | DRIVER | DUPLEX | SPEED | WOL ENABLED | MAC |
\n";
foreach (@nic_list) {
print REPORT_OUTPUT "",$_,"
\n";
}
print REPORT_OUTPUT "
\n";
}
@nic_list = ();
}
sub printHealth {
if(@health_list) {
push @jump_tags," ESX/ESXi Health Status
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "ESX/ESXi Health Status
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "SENSOR NAME | READING | STATUS |
\n";
foreach (@health_list) {
print REPORT_OUTPUT $_;
}
print REPORT_OUTPUT "
\n";
}
@health_list = ();
}
sub getHealthInfo {
my ($host) = @_;
if(defined($host->runtime->healthSystemRuntime)) {
if(defined($host->runtime->healthSystemRuntime->systemHealthInfo)) {
my $health_string = "";
$health_string .= "".$host->name." |
\n";
my $sensors = $host->runtime->healthSystemRuntime->systemHealthInfo->numericSensorInfo;
my $sensor_health_color = "";
foreach(sort {$a->name cmp $b->name} @$sensors) {
my $sensor_health = $_->healthState->key;
if ($sensor_health eq 'Green' || $sensor_health eq 'green') { $sensor_health_color="OK | "; }
elsif ($sensor_health_color eq 'Red' || $sensor_health_color eq 'red') { $sensor_health_color="PROBLEM | "; }
elsif ($sensor_health_color eq 'Yellow' || $sensor_health_color eq 'yellow') { $sensor_health_color="WARNING | "; }
else { $sensor_health_color="UNKNOWN | "; }
my $reading;
if(defined($_->rateUnits)) {
$reading = $_->currentReading . " " . $_->baseUnits . "/" . $_->rateUnits;
} else {
$reading = $_->currentReading . " " . $_->baseUnits;
}
$health_string .= "".$_->name." | ".$reading." | ".$sensor_health_color."
\n";
}
push @health_list,$health_string;
}
}
}
sub getNICInfo {
my ($host) = @_;
my $nics = $host->config->network->pnic;
foreach my $nic (@$nics) {
my $nic_string = "";
if($enable_demo_mode eq 1) {
$nic_string = "HIDE ME! | ";
}
else {
$nic_string = "".$host->name." | ";
}
$nic_string .= "".$nic->device." | ".$nic->pci." | ".$nic->driver." | ";
if($nic->linkSpeed) {
$nic_string .= "".(($nic->linkSpeed->duplex) ? "FULL DUPLEX" : "HALF-DUPLEX")." | ".$nic->linkSpeed->speedMb." MB | ";
}
else {
$nic_string .= "UNKNOWN | UNKNOWN | ";
}
$nic_string .= "".(($nic->wakeOnLanSupported) ? "YES" : "NO")." | ";
if($enable_demo_mode eq 1) {
$nic_string .= "XX:XX:XX:XX:XX:XX | ";
}
else {
$nic_string .= "".$nic->mac." | ";
}
push @nic_list,$nic_string;
}
}
sub getHBAInfo {
my ($host) = @_;
my $hbas = $host->config->storageDevice->hostBusAdapter;
foreach my $hba (@$hbas) {
my $hba_string = "";
if($enable_demo_mode eq 1) {
$hba_string = "HIDE ME! | ";
}
else {
$hba_string = "".$host->name." | ";
}
if ($hba->isa("HostFibreChannelHba")) {
my $nwwn = (Math::BigInt->new($hba->nodeWorldWideName))->as_hex();
my $pwwn = (Math::BigInt->new($hba->portWorldWideName))->as_hex();
$nwwn =~ s/^..//;
$pwwn =~ s/^..//;
$nwwn = join(':', unpack('A2' x 8, $nwwn));
$pwwn = join(':', unpack('A2' x 8, $pwwn));
if($enable_demo_mode eq 1) {
$nwwn = "XX:XX:XX:XX:XX:XX:XX:XX";
$pwwn = "XX:XX:XX:XX:XX:XX:XX:XX";
}
$hba_string .= "FC | ".$hba->device." | ".$hba->pci." | ".$hba->model." | ".$hba->driver." | ".$hba->status." | NWWN ".$nwwn." | PWWN ".$pwwn." | PORT TYPE ".$hba->portType->val." | SPEED ".$hba->speed." | ";
} elsif ($hba->isa("HostInternetScsiHba")) {
$hba_string .= "iSCSI | ".$hba->device." | ".$hba->pci." | ".$hba->model." | ".$hba->driver." | ".$hba->status." | ".(($hba->authenticationProperties->chapAuthEnabled) ? "CHAP ENABLED" : "CHAP DISABLED")." | ";
}
elsif ($hba->isa("HostParallelScsiHba")) {
$hba_string .= "SCSI | ".$hba->device." | ".$hba->pci." | ".$hba->model." | ".$hba->driver." | ".$hba->status." | ";
}
elsif ($hba->isa("HostBlockHba")) {
$hba_string .= " | BLOCK | ".$hba->device." | ".$hba->pci." | ".$hba->model." | ".$hba->driver." | ".$hba->status." | ";
}
push @hba_list,$hba_string;
}
}
sub getVswitchInfo {
my ($host) = @_;
my %cdp_blob = ();
my $netMgr = Vim::get_view(mo_ref => $host->configManager->networkSystem);
my @physicalNicHintInfo = $netMgr->QueryNetworkHint();
foreach (@physicalNicHintInfo){
foreach ( @{$_} ){
if(defined($_->connectedSwitchPort)) {
my $device = $_->device;
my $port = $_->connectedSwitchPort->portId;
my $address = defined $_->connectedSwitchPort->address ? $_->connectedSwitchPort->address : "N/A";
my $cdp_ver = defined $_->connectedSwitchPort->cdpVersion ? $_->connectedSwitchPort->cdpVersion : "N/A";
my $devid = defined $_->connectedSwitchPort->devId ? $_->connectedSwitchPort->devId : "N/A";
my $duplex = defined $_->connectedSwitchPort->fullDuplex ? ($_->connectedSwitchPort->fullDuplex ? "YES" : "NO") : "N/A";
my $platform = defined $_->connectedSwitchPort->hardwarePlatform ? $_->connectedSwitchPort->hardwarePlatform : "N/A";
my $prefix = defined $_->connectedSwitchPort->ipPrefix ? $_->connectedSwitchPort->ipPrefix : "N/A";
my $location = defined $_->connectedSwitchPort->location ? $_->connectedSwitchPort->location : "N/A";
my $mgmt_addr = defined $_->connectedSwitchPort->mgmtAddr ? $_->connectedSwitchPort->mgmtAddr : "N/A";
my $d_mtu = defined $_->connectedSwitchPort->mtu ? $_->connectedSwitchPort->mtu : "N/A";
my $samples = defined $_->connectedSwitchPort->samples ? $_->connectedSwitchPort->samples : "N/A";
my $sys_ver = defined $_->connectedSwitchPort->softwareVersion ? $_->connectedSwitchPort->softwareVersion : "N/A";
my $sys_name = defined $_->connectedSwitchPort->systemName ? $_->connectedSwitchPort->systemName : "N/A";
my $sys_oid = defined $_->connectedSwitchPort->systemOID ? $_->connectedSwitchPort->systemOID : "N/A";
my $timeout = defined $_->connectedSwitchPort->timeout ? $_->connectedSwitchPort->timeout : "N/A";
my $ttl = defined $_->connectedSwitchPort->ttl ? $_->connectedSwitchPort->ttl : "N/A";
my $vlan = defined $_->connectedSwitchPort->vlan ? $_->connectedSwitchPort->vlan : "N/A";
if($enable_demo_mode eq 1) {
$address = "HIDE MY DEVICE IP!";
$prefix = "HIDE MY IP PREFIX!";
$mgmt_addr = "HIDE MY MGMT IP!";
$vlan = "HIDE MY VLAN ID!";
$devid = "HIDE MY DEVICE ID!";
$sys_name = "HIDE MY SYSTEM NAME!";
$sys_ver = "HIDE MY SYSTEM VERSION!";
$platform = "HIDE MY PLATFORM!";
}
my $blob .= " | ".$device." | ".$mgmt_addr." | ".$address." | ".$prefix." | ".$location." | ".$sys_name." | ".$sys_ver." | ".$sys_oid." | ".$platform." | ".$devid." | ".$cdp_ver." | ".$duplex." | ".$d_mtu." | ".$timeout." | ".$ttl." | ".$vlan." | ".$samples." |
\n";
$cdp_blob{$device} = $blob;
$cdp_enabled{$device} = $port;
}
}
}
my $vswitches = $host->config->network->vswitch;
my $vswitch_string = "";
foreach my $vSwitch (@$vswitches) {
my $pNicName = "";
my $mtu = "";
my $cdp_vswitch = "";
my $pNics = $vSwitch->pnic;
my $pNicKey = "";
foreach (@$pNics) {
$pNicKey = $_;
if ($pNicKey ne "") {
$pNics = $netMgr->networkInfo->pnic;
foreach my $pNic (@$pNics) {
if ($pNic->key eq $pNicKey) {
$pNicName = $pNicName ? ("$pNicName," . $pNic->device) : $pNic->device;
if($cdp_enabled{$pNic->device}) {
$cdp_vswitch = $cdp_enabled{$pNic->device};
}
else {
$cdp_vswitch = "";
}
}
}
}
}
$mtu = $vSwitch->{mtu} if defined($vSwitch->{mtu});
$vswitch_string .= "VSWITCH NAME | NUM OF PORTS | USED PORTS | MTU | UPLINKS | CDP ENABLED |
---|
".$vSwitch->name." | ".$vSwitch->numPorts." | ".($vSwitch->numPorts - $vSwitch->numPortsAvailable)." | ".$vSwitch->{mtu}." | ".$pNicName." | ".$cdp_vswitch." |
";
$vswitch_string .= "PORTGROUP NAME | VLAN ID | USED PORTS | UPLINKS |
";
my $portGroups = $vSwitch->portgroup;
foreach my $port (@$portGroups) {
my $pg = FindPortGroupbyKey ($netMgr, $vSwitch->key, $port);
next unless (defined $pg);
my $usedPorts = (defined $pg->port) ? $#{$pg->port} + 1 : 0;
if($enable_demo_mode eq 1) {
$vswitch_string .= "HIDE MY PG | HIDE MY VLAN ID | ".$usedPorts." | ".$pNicName." |
";
} else {
$vswitch_string .= "".$pg->spec->name." | ".$pg->spec->vlanId." | ".$usedPorts." | ".$pNicName." |
";
}
}
}
print REPORT_OUTPUT "VSWITCH(s) | |
\n";
for my $key ( keys %cdp_blob ) {
my $value = $cdp_blob{$key};
$cdp_string .= $value;
}
}
sub FindPortGroupbyKey {
my ($network, $vSwitch, $key) = @_;
my $portGroups = $network->networkInfo->portgroup;
foreach my $pg (@$portGroups) {
return $pg if (($pg->vswitch eq $vSwitch) && ($key eq $pg->key));
}
return undef;
}
sub printClusterSummary {
my ($local_cluster) = @_;
my $cluster_name = $local_cluster->name;
my $cluster_health = $local_cluster->overallStatus->val;
my $cluster_host_cnt = $local_cluster->summary->numHosts;
my $cluster_avail_host = $local_cluster->summary->numEffectiveHosts;
my $cluster_cpu_cnt = prettyPrintData($local_cluster->summary->totalCpu,'MHZ');
my $cluster_mem_cnt = prettyPrintData($local_cluster->summary->totalMemory,'B');
my $cluster_avail_cpu = prettyPrintData($local_cluster->summary->effectiveCpu,'MHZ');
my $cluster_avail_mem = prettyPrintData($local_cluster->summary->effectiveMemory,'M');
my $cluster_drs = $local_cluster->configuration->drsConfig->enabled;
my $cluster_ha = $local_cluster->configuration->dasConfig->enabled;
my $cluster_dpm = $local_cluster->configurationEx->dpmConfigInfo->enabled;
my $cluster_vm_mon = $local_cluster->configuration->dasConfig->vmMonitoring;
my $cluster_host_mon = $local_cluster->configuration->dasConfig->hostMonitoring;
my $cpu_perc_string = "";
my $mem_perc_string = "";
my $evc;
if($local_cluster->summary->currentEVCModeKey) { $evc = $local_cluster->summary->currentEVCModeKey; } else { $evc = "DISABLED"; }
my $vmotions = $local_cluster->summary->numVmotions;
clusterPG($local_cluster);
getDVS($local_cluster);
print REPORT_OUTPUT "
\n";
###########################
# PRINT CLUSTER SUMMARY
###########################
push @jump_tags,"CLCluster: $cluster_name
\n";
print REPORT_OUTPUT "\n\n";
print REPORT_OUTPUT "Cluster: $cluster_name
\n";
print REPORT_OUTPUT "Cluster Statistics:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "CLUSTER HEALTH | AVAILABLE HOST(s) | AVAILABLE CPU | AVAILABLE MEM | DRS ENABLED | HA ENABLED | DPM ENABLED | EVC ENABLED | VM MONITORING | HOST MONITORING | # OF vMOTIONS |
\n";
print REPORT_OUTPUT "";
if($cluster_health eq 'gray' ) { print REPORT_OUTPUT "UNKNOWN"; }
if($cluster_health eq 'green' ) { print REPORT_OUTPUT " | CLUSTER OK"; }
if($cluster_health eq 'red' ) { print REPORT_OUTPUT " | CLUSTER HAS PROBLEM"; }
if($cluster_health eq 'yellow' ) { print REPORT_OUTPUT " | CLUSTER MIGHT HAVE PROBLEM"; }
print REPORT_OUTPUT " | ",$cluster_avail_host,"/",$cluster_host_cnt," | ";
print REPORT_OUTPUT "",$cluster_avail_cpu," | ";
print REPORT_OUTPUT "",$cluster_avail_mem," | ";
print REPORT_OUTPUT "",($cluster_drs) ? "YES" : "NO"," | ";
print REPORT_OUTPUT "",($cluster_ha) ? "YES" : "NO" ," | ";
print REPORT_OUTPUT "",($cluster_dpm) ? "YES" : "NO" ," | ";
print REPORT_OUTPUT "",$evc," | ";
print REPORT_OUTPUT "",$cluster_vm_mon," | ";
print REPORT_OUTPUT "",$cluster_host_mon," | ";
print REPORT_OUTPUT "",$vmotions," | ";
print REPORT_OUTPUT "
\n";
print REPORT_OUTPUT "
\n";
###########################
# PRINT HA INFO
###########################
if($cluster_ha) {
print REPORT_OUTPUT "\nHA CONFIGURATIONS:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "FAILOVER LEVEL | ADMISSION CONTROLED ENABLED | ISOLATION RESPONSE | RESTART PRIORITY |
\n";
print REPORT_OUTPUT "",$local_cluster->configuration->dasConfig->failoverLevel," | ";
print REPORT_OUTPUT "",($local_cluster->configuration->dasConfig->admissionControlEnabled) ? "YES" : "NO"," | ";
print REPORT_OUTPUT "",$local_cluster->configuration->dasConfig->defaultVmSettings->isolationResponse," | ";
print REPORT_OUTPUT "",$local_cluster->configuration->dasConfig->defaultVmSettings->restartPriority," | ";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "
\n";
}
###########################
# PRINT DRS INFO
###########################
if($cluster_drs) {
print REPORT_OUTPUT "\nDRS CONFIGURATIONS:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "DRS BEHAVIOR | VMOTION RATE |
\n";
print REPORT_OUTPUT "",$local_cluster->configuration->drsConfig->defaultVmBehavior->val," | ";
print REPORT_OUTPUT "",$local_cluster->configuration->drsConfig->vmotionRate," | ";
print REPORT_OUTPUT "
\n";
print REPORT_OUTPUT "
\n";
}
###########################
# PRINT DPM INFO
###########################
if($cluster_dpm) {
print REPORT_OUTPUT "\nDRS CONFIGURATIONS:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "DPM BEHAVIOR |
\n";
print REPORT_OUTPUT "",$local_cluster->configurationEx->dpmConfigInfo->defaultDpmBehavior->val," | ";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "
\n";
}
###########################
# PRINT CLUSTER RULES
###########################
my $rules = $local_cluster->configurationEx->rule;
if($rules) {
print REPORT_OUTPUT "\nCluster Rules:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "RULE NAME | RULE TYPE | ENABLED |
\n";
foreach (@$rules) {
my $rule = $_;
my $is_enabled = $rule->enabled;
my $rule_name = $rule->name;
my $rule_type;
if(ref($rule) eq 'ClusterAffinityRuleSpec') {
$rule_type = "AFFINITY";
}
elsif (ref($rule) eq 'ClusterAntiAffinityRuleSpec') {
$rule_type = "ANTI-AFFINITY";
}
print REPORT_OUTPUT "",$rule_name," | ",$rule_type," | ",($is_enabled) ? "YES" : "NO"," |
\n";
}
print REPORT_OUTPUT "
\n";
}
###########################
# PRINT RPS INFO
###########################
my $root_rp = Vim::get_view (mo_ref => $local_cluster->resourcePool);
my $rps = Vim::get_views (mo_ref_array => $root_rp->resourcePool);
my $resource_pool_string = "";
my $vapp_string = "";
if(@$rps > 0) {
foreach(@$rps) {
if($_->isa('VirtualApp')) {
my $vapp_name = $_->name;
my $anno = defined $_->vAppConfig->annotation ? $_->vAppConfig->annotation : "N/A";
my $ec = $_->vAppConfig->entityConfig;
my $vm_vapp_string = "";
foreach(@$ec) {
my $order = $_->startOrder;
my $tag = $_->tag;
$vm_vapp_string .= "".$tag." | ".$order." |
\n";
}
$vapp_string .= "".$vapp_name." |
---|
\n";
$vapp_string .= "
VM | START ORDER |
\n";
$vapp_string .= $vm_vapp_string." |
\n";
} else {
my $rp_name = $_->name;
my $rp_status = $_->summary->runtime->overallStatus->val;
if($rp_status eq 'gray') { $rp_status = "UNKNOWN | "; }
elsif($rp_status eq 'green') { $rp_status = "UNDERCOMMITTED | "; }
elsif($rp_status eq 'red') { $rp_status = "INCONSISTENT | "; }
elsif($rp_status eq 'yellow') { $rp_status = "OVERCOMMITTED | "; }
my $rp_cpu_use = prettyPrintData($_->summary->runtime->cpu->overallUsage,'MHZ');
my $rp_cpu_max = prettyPrintData($_->summary->runtime->cpu->maxUsage,'MHZ');
my $rp_cpu_lim = prettyPrintData($_->summary->config->cpuAllocation->limit,'MHZ');
my $rp_cpu_rsv = prettyPrintData($_->summary->config->cpuAllocation->reservation,'MHZ');
my $rp_mem_use = prettyPrintData($_->summary->runtime->memory->overallUsage,'B');
my $rp_mem_max = prettyPrintData($_->summary->runtime->memory->maxUsage,'B');
my $rp_mem_lim = prettyPrintData($_->summary->config->cpuAllocation->limit,'M');
my $rp_mem_rsv = prettyPrintData($_->summary->config->cpuAllocation->reservation,'M');
$resource_pool_string .= "".$rp_name." | ".$rp_status."".$rp_cpu_lim." | ".$rp_cpu_rsv." | ".$rp_mem_lim." | ".$rp_mem_rsv." | ".$rp_cpu_use." | ".$rp_cpu_max." | ".$rp_mem_use." | ".$rp_mem_max." |
\n";
}
}
}
if($resource_pool_string ne "") {
print REPORT_OUTPUT "\nRoot Resource Pool(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "POOL NAME | STATUS | CPU LIMIT | CPU RESERVATION | MEM LIMIT | MEM RESERVATION | CPU USAGE | CPU MAX | MEM USAGE | MEM MAX |
\n";
print REPORT_OUTPUT $resource_pool_string;
print REPORT_OUTPUT "
\n";
}
###########################
# PRINT VAPP INFO
###########################
if($vapp_string ne "") {
print REPORT_OUTPUT "\nvApp(s):
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT $vapp_string;
print REPORT_OUTPUT "
\n";
}
}
sub printBuildSummary {
my $print_type;
if ($content->about->apiType eq 'VirtualCenter') {
$print_type = "VMware vCenter";
}
else {
$print_type = "VMware ESX/ESXi";
}
print REPORT_OUTPUT "$print_type:
\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "BUILD | VERSION | FULL NAME | \n";
print REPORT_OUTPUT "
---|
";
print REPORT_OUTPUT "",$content->about->build," | ",$content->about->version," | ",$content->about->fullName," | \n";
print REPORT_OUTPUT "
";
print REPORT_OUTPUT "
\n";
###########################
# LICENSES
###########################
my $lic_mgr = Vim::get_view (mo_ref => $content->licenseManager);
my $feature_info_string = "";
my $features = "";
my $feature_string = "";
print REPORT_OUTPUT "Licenses:
\n";
print REPORT_OUTPUT "\n";
if($content->about->apiType eq 'HostAgent' || $content->about->apiType eq 'VirtualCenter') {
print REPORT_OUTPUT "NAME | EDITION | LICENSE | COST UNIT | TOTAL | CONSUMED | AVAILABLE |
\n";
my $licenses = $lic_mgr->licenses;
foreach(@$licenses) {
if($enable_demo_mode eq 1) {
print REPORT_OUTPUT "CONFIDENTIAL | CONFIDENTIAL | CONFIDENTIAL | CONFIDENTIAL | CONFIDENTIAL | CONFIDENTIAL | CONFIDENTIAL |
\n";
} else {
print REPORT_OUTPUT "",$_->name," | ",$_->editionKey," | ",$_->licenseKey," | ",$_->costUnit," | ",$_->total," | ",$_->used," | ",($_->total - $_->used)," |
\n";
my $prop = $_->properties;
if($prop) {
$feature_info_string .= "EDITION w/FEATURES | EXPIRATION (HOURS) | EXPIRATION (MINS) | EXPIRATION DATE |
\n";
$feature_info_string .= "".$_->editionKey." | \n";
}
foreach(@$prop) {
if($_->key ne 'feature') {
if($_->key eq 'expirationHours' ) { $feature_info_string .= "".$_->value." | "; }
if($_->key eq 'expirationMinutes' ) { $feature_info_string .= "".$_->value." | "; }
if($_->key eq 'expirationDate' ) { $feature_info_string .= "".$_->value." |
\n"; }
} else {
my $feature = $_->value;
$features .= "".$feature->value." |
\n";
}
}
}
$feature_string .= $feature_info_string . $features;
$feature_info_string = "";
$features = "";
}
print REPORT_OUTPUT "
\n";
}
###########################
# FEATURES
###########################
print REPORT_OUTPUT "Features:
\n";
print REPORT_OUTPUT "\n";
if(!$enable_demo_mode eq 1) {
print REPORT_OUTPUT $feature_string;
} else { print REPORT_OUTPUT "CONFIDENTIAL |
\n"; }
print REPORT_OUTPUT "
\n";
###########################
# SESSIONS
###########################
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "Active Session(s):
\n";
print REPORT_OUTPUT "USERNAME | FULL NAME | LOGON TIME | LAST ACTIVE |
\n";
if(!$enable_demo_mode eq 1) {
my $sess_mgr = Vim::get_view (mo_ref => $content->sessionManager);
my $sess_list = $sess_mgr->sessionList;
foreach(@$sess_list) {
print REPORT_OUTPUT "",$_->userName," | ",$_->fullName," | ",$_->loginTime," | ",$_->lastActiveTime," |
\n";
}
} else { print REPORT_OUTPUT "USER X | X | TIME Y | TIME Z |
\n"; }
print REPORT_OUTPUT "
\n";
###########################
# HOST PROFILES
###########################
my $hp_mgr;
eval { $hp_mgr = Vim::get_view (mo_ref => $content->hostProfileManager); };
my $hp_string = "";
if(!$@) {
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "Host Profile(s):
\n";
print REPORT_OUTPUT "PROFILE NAME | DESCRIPTION | CREATION TIME | LAST MODIFIED | ENABLED | COMPLIANCE STATUS |
\n";
my $profiles = Vim::get_views (mo_ref_array => $hp_mgr->profile);
foreach(@$profiles) {
my $description = "N/A";
if($_->config->annotation) { $description = $_->config->annotation; }
print REPORT_OUTPUT "",$_->name," | ",$description," | ",$_->createdTime," | ",$_->modifiedTime," | ",($_->config->enabled) ? "YES" : "NO"," | ",$_->complianceStatus," |
\n";
}
print REPORT_OUTPUT "
\n";
}
#please do not touch this, else the jump tags will break
print REPORT_OUTPUT "\n//\n";
}
sub printDatacenterName {
my ($dc) = @_;
print REPORT_OUTPUT "\n
\nDatacenter: $dc
\n";
}
sub printStartHeader {
print "Generating VMware vSphere Health Report $version \"$report_name\" ...\n\n";
print "This can take a few minutes depending on environment size. \nGet a cup of coffee/tea and check out http://www.engineering.ucsb.edu/~duonglt/vmware/\n";
$my_time = "Date: ".giveMeDate('MDYHMS');
$start_time = time();
open(REPORT_OUTPUT, ">$report_name");
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "VMware vSphere Health Check Report $version - $my_time\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "\n";
print REPORT_OUTPUT "\nVMware vSphere Health Check Report $version
\n";
print REPORT_OUTPUT "$my_time\n";
}
sub giveMeDate {
my ($date_format) = @_;
my %dttime = ();
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
### begin_: initialize DateTime number formats
$dttime{year } = sprintf "%04d",($year + 1900); ## four digits to specify the year
$dttime{mon } = sprintf "%02d",($mon + 1); ## zeropad months
$dttime{mday } = sprintf "%02d",$mday; ## zeropad day of the month
$dttime{wday } = sprintf "%02d",$wday + 1; ## zeropad day of week; sunday = 1;
$dttime{yday } = sprintf "%02d",$yday; ## zeropad nth day of the year
$dttime{hour } = sprintf "%02d",$hour; ## zeropad hour
$dttime{min } = sprintf "%02d",$min; ## zeropad minutes
$dttime{sec } = sprintf "%02d",$sec; ## zeropad seconds
$dttime{isdst} = $isdst;
if($date_format eq 'MDYHMS') {
$my_time = "$dttime{mon}-$dttime{mday}-$dttime{year} $dttime{hour}:$dttime{min}:$dttime{sec}";
}
elsif ($date_format eq 'YMD') {
$my_time = "$dttime{year}-$dttime{mon}-$dttime{mday}";
}
return $my_time;
}
sub printCloseHeader {
print REPORT_OUTPUT "
\n";
print REPORT_OUTPUT "Author: William Lam\n";
print REPORT_OUTPUT "http://engineering.ucsb.edu/~duonglt/vmware\n";
print REPORT_OUTPUT "Generated using: vmwareHealthCheck.pl\n";
print REPORT_OUTPUT "Primp Industries\n";
close(REPORT_OUTPUT);
my @lines;
my $jump_string = "";
tie @lines, 'Tie::File', $report_name or die;
for (@lines) {
if (//) {
foreach (@jump_tags) {
if( ($_ =~ /^CL/) ) {
my $tmp_string = substr($_,2);
$jump_string .= $tmp_string;
}
else {
$jump_string .= $_;
}
}
$_ = "\n$jump_string";
last;
}
}
untie @lines;
$end_time = time();
$run_time = $end_time - $start_time;
print "\nStart Time: ",&formatTime(str => scalar localtime($start_time)),"\n";
print "End Time: ",&formatTime(str => scalar localtime($end_time)),"\n";
if ($run_time < 60) {
print "Duration : ",$run_time," Seconds\n\n";
}
else {
print "Duration : ",&restrict_num_decimal_digits($run_time/60,2)," Minutes\n\n";
}
}
sub cleanUp {
@hosts_seen = ();
}
sub Fail {
my ($msg) = @_;
Util::disconnect();
die ($msg);
exit ();
}
sub getColor {
my ($val) = @_;
my $color_string = "";
if($val < $red_warn) { $color_string = "".$val." % | "; }
elsif($val < $orange_warn) { $color_string = "".$val." % | "; }
elsif($val < $yellow_warn) { $color_string = "".$val." % | "; }
else { $color_string = "".$val." % | "; }
return $color_string;
}
sub setSnapColor {
my ($val,$datastore,$snapshot,$size,$date) = @_;
$size = prettyPrintData($size,'B');
my $snap_color_string = "";
if($val > $snap_red_warn) { $snap_color_string = "".$datastore." | ".$snapshot." | ".$val." days old | ".$size." | ".$date." | "; }
elsif($val > $snap_orange_warn) { $snap_color_string = "".$datastore." | ".$snapshot." | ".$val." days old | ".$size." | ".$date." | "; }
elsif($val > $snap_yellow_warn) { $snap_color_string = "".$datastore." | ".$snapshot." | ".$val." days old | ".$size." | ".$date." | "; }
if(!$snap_color_string eq '') {
push @vm_delta_warn,$snap_color_string;
}
}
#http://www.bryantmcgill.com/Shazam_Perl_Module/Subroutines/utils_convert_bytes_to_optimal_unit.html
sub prettyPrintData{
my($bytes,$type) = @_;
return '' if ($bytes eq '' || $type eq '');
return 0 if ($bytes <= 0);
my($size);
if($type eq 'B') {
$size = $bytes . ' Bytes' if ($bytes < 1024);
$size = sprintf("%.2f", ($bytes/1024)) . ' KB' if ($bytes >= 1024 && $bytes < 1048576);
$size = sprintf("%.2f", ($bytes/1048576)) . ' MB' if ($bytes >= 1048576 && $bytes < 1073741824);
$size = sprintf("%.2f", ($bytes/1073741824)) . ' GB' if ($bytes >= 1073741824 && $bytes < 1099511627776);
$size = sprintf("%.2f", ($bytes/1099511627776)) . ' TB' if ($bytes >= 1099511627776);
}
elsif($type eq 'M') {
$bytes = $bytes * (1048576);
$size = sprintf("%.2f", ($bytes/1048576)) . ' MB' if ($bytes >= 1048576 && $bytes < 1073741824);
$size = sprintf("%.2f", ($bytes/1073741824)) . ' GB' if ($bytes >= 1073741824 && $bytes < 1099511627776);
$size = sprintf("%.2f", ($bytes/1099511627776)) . ' TB' if ($bytes >= 1099511627776);
}
elsif($type eq 'G') {
$bytes = $bytes * (1073741824);
$size = sprintf("%.2f", ($bytes/1073741824)) . ' GB' if ($bytes >= 1073741824 && $bytes < 1099511627776);
$size = sprintf("%.2f", ($bytes/1099511627776)) . ' TB' if ($bytes >= 1099511627776);
}
elsif($type eq 'MHZ') {
$size = sprintf("%.2f", ($bytes/1e-06)) . ' MHz' if ($bytes >= 1e-06 && $bytes < 0.001);
$size = sprintf("%.2f", ($bytes*0.001)) . ' GHz' if ($bytes >= 0.001);
}
return $size;
}
# restrict the number of digits after the decimal point
#http://guymal.com/mycode/perl_restrict_digits.shtml
sub restrict_num_decimal_digits {
my $num=shift;#the number to work on
my $digs_to_cut=shift;# the number of digits after
if ($num=~/\d+\.(\d){$digs_to_cut,}/) {
$num=sprintf("%.".($digs_to_cut-1)."f", $num);
}
return $num;
}
#http://www.infocopter.com/perl/format-time.html
sub formatTime(%) {
my %args = @_;
$args{'str'} ||= ''; # e.g. Mon Jul 3 12:59:28 2006
my @elems = ();
foreach (split / /, $args{'str'}) {
next unless $_;
push(@elems, $_);
}
my ($weekday, $month, $mday, $time, $yyyy) = split / /, join(' ', @elems);
my %months = ( Jan => 1, Feb => 2, Mar => 3, Apr => 4, May => 5, Jun => 6,
Jul => 7, Aug => 8, Sep => 9, Oct => 10, Nov => 11, Dec => 12 );
my $s = substr($time, 6,2);
my $m = substr($time, 3,2);
my $h = substr($time, 0, 2);
my $dd = sprintf('%02d', $mday);
my $mm_num = sprintf('%02d', $months{$month});
my $formatted = "$mm_num\-$dd\-$yyyy $h:$m:$s";
#my $formatted = "$yyyy$mm_num$dd$h$m$s";
$formatted;
}
sub print_tree {
my ($vm, $ref, $tree) = @_;
my $head = " ";
foreach my $node (@$tree) {
$head = ($ref->value eq $node->snapshot->value) ? " " : " " if (defined $ref);
my $quiesced = ($node->quiesced) ? "YES" : "NO";
my $desc = $node->description;
if($desc eq "" ) { $desc = "NO DESCRIPTION"; }
push @snapshot_vms,"".$vm." | ".$node->name." | ".$desc." | ".$node->createTime." | ".$node->state->val." | ".$quiesced." | ";
print_tree ($vm, $ref, $node->childSnapshotList);
}
return;
}