#!/usr/bin/perl -w ################################################################## # Author: William Lam # Email: william2003[at]gmail[dot]com # 01/26/2009 # http://www.engineering.ucsb.edu/~duonglt/vmware/ ################################################################## use strict; use warnings; use Math::BigInt; use Tie::File; use Getopt::Long; use VMware::VIRuntime; use VMware::VILib; ################################ # disk consumption warnings ################################ # yellow < 30 % my $yellow_warn = 30; # orange < 15 % my $orange_warn = 15; # red < 10% my $red_warn = 10; ########### DO NOT MODIFY PAST HERE ########### ################################ # VERSION ################################ my $version = "v0.4"; ################################ # DEMO MODE # 0 = no, 1 = yes ################################ my $enable_demo_mode = 0; ################ #GLOBAL VARS ################ 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 @nic_list = (); my @hosts_seen = (); my %opts = ( cluster => { type => "=s", help => "The name of a vCenter cluster", required => 0, }, type => { type => "=s", help => "Type: [vcenter|cluster|host]\n", required => 1, }, report => { type => "=s", help => "The name of the report to output", 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')) { $host_type = Opts::get_option('type'); #################### # SINGLE ESX HOST #################### if( ($host_type eq "host") && (!Opts::option_is_set('cluster')) ) { $host_view = Vim::find_entity_views(view_type => 'HostSystem'); if (!$host_view) { die "ESX/ESXi host was not found\n"; } } ##################### # vCENTER + CLUSTER ##################### elsif( $host_type eq "cluster" ) { 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_name\" was not found\n"; } } else { Fail("\n--cluster parameter required with the name of a valid vCenter Cluster\n\n"); } } ################## # vCENTER ALL ################## elsif( ($host_type eq "vcenter") && (!Opts::option_is_set('cluster')) ) { $cluster_views = Vim::find_entity_views(view_type => 'ClusterComputeResource'); Fail ("No clusters found.\n") unless (@$cluster_views); } #if report name is not specified, default output if (Opts::option_is_set ('report')) { $report_name = Opts::get_option('report'); } else { $report_name = "report.html"; } } ### CODE START ### ################################# # PRINT HTML HEADER/CSS ################################# printStartHeader(); ######################################### # PRINT vCENTER or HOST BUILD/SUMMARY ######################################### printBuildSummary(); ######################################### # PRINT vCENTER INFO ######################################### if ($host_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); printHostPortgroup($hosts); printHostVM($hosts); printVMDatastore(); printVMNetwork(); printVMSnapshot(); printVMNPIV(); printVMRDM(); printVMCDrom(); printVMFloppy(); cleanUp(); } } } ######################################### # PRINT SPECIFIC CLUSTER INFO ######################################### elsif ($host_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); printHostPortgroup($hosts); printHostVM($hosts); printVMDatastore(); printVMNetwork(); printVMSnapshot(); printVMNPIV(); printVMRDM(); printVMCDrom(); printVMFloppy(); cleanUp(); } } ######################################### # PRINT SINGLE HOST INFO ######################################### else { printHostHardwareInfo($host_view); printHostLun($host_view); printHostDatastoreInfo($host_view); printHostPortgroup($host_view); printHostVM($host_view); printVMDatastore(); printVMNetwork(); printVMSnapshot(); printVMNPIV(); printVMRDM(); printVMCDrom(); printVMFloppy(); cleanUp(); } ################################# # CLOSE HTML REPORT ################################# printCloseHeader(); Util::disconnect(); ### CODE END ### ########################### # # HELPER FUNCTIONS # ########################### sub printVMNPIV { ########################### # PRINT NPIV INFO ########################### if(@npiv_vms) { my $npiv_count = $#npiv_vms; $npiv_count += 1; push @jump_tags,"                VM(s) w/NPIV enabled
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

$npiv_count VM(s) w/NPIV enabled:

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach (@npiv_vms) { print REPORT_OUTPUT "",$_,""; } print REPORT_OUTPUT "
VMNPIV NODE WWNNPIV PORT WWNGENERATED FROM
\n"; } @npiv_vms = (); } sub printVMSnapshot { ########################### # PRINT SNAPSHOT INFO ########################### if(@snapshot_vms) { my $snap_count = $#snapshot_vms; $snap_count += 1; push @jump_tags,"                VM(s) w/Snapshot(s)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

$snap_count VM(s) w/Snapshot(s):

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach (@snapshot_vms) { print REPORT_OUTPUT "",$_,""; } print REPORT_OUTPUT "
VMSNAPSHOT NAMESNAPSHOT DESCCREATEDSTATEQUIESCED
\n"; } @snapshot_vms = (); } sub printVMRDM { ########################### # PRINT RDM INFO ########################### if(@rdm_vms) { my $rdm_count = $#rdm_vms; $rdm_count += 1; push @jump_tags,"                VM(s) w/RDM(s)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

$rdm_count VM(s) w/RDM(s):

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach (@rdm_vms) { print REPORT_OUTPUT "",$_,""; } print REPORT_OUTPUT "
VMCOMPAT MODEDEVICEDISK MODELUN UUIDVIRTUAL DISK UUID
\n"; } @rdm_vms = (); } sub printVMCDrom { ########################### # PRINT CDROM INFO ########################### if(@connected_cdrom_vms) { my $cdrom_count = $#connected_cdrom_vms; $cdrom_count += 1; push @jump_tags,"                VM(s) w/connected CD-ROM(s)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

$cdrom_count VM(s) w/connected CD-ROM(s):

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach (@connected_cdrom_vms) { print REPORT_OUTPUT ""; } print REPORT_OUTPUT "
VM
",$_,"
\n"; } @connected_cdrom_vms = (); } sub printVMFloppy { ########################### # PRINT FLOPPY INFO ########################### if(@connected_floppy_vms) { my $floppy_count = $#connected_floppy_vms; $floppy_count += 1; push @jump_tags,"                VM(s) w/connected Floppy(s)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

$floppy_count VM(s) w/connected Floppy(s):

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach (@connected_floppy_vms) { print REPORT_OUTPUT ""; } print REPORT_OUTPUT "
VM
",$_,"
\n"; } @connected_floppy_vms = (); } sub printVMNetwork { #################################### # PRINT VM NETWORK SUMMARY #################################### if(%net_vms) { push @jump_tags,"                VM(s) Network Summary
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

VM(s) Network Summary:

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach ( sort keys %net_vms ) { my $vm_net = $net_vms{$_}; print REPORT_OUTPUT "",$vm_net,"\n"; } print REPORT_OUTPUT "
VMIP(s)MAC ADDRESSPORTGROUPCONNECTED
",$_,"
\n"; } %net_vms = (); } sub printVMDatastore { #################################### # PRINT VM DISK/DATASTORE SUMMARY #################################### if(%vms_storage) { push @jump_tags,"                VM(s) Storage Summary
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

VM(s) Storage Summary:

\n"; print REPORT_OUTPUT "
COLOR LEGENDYELLOW < $yellow_warn %ORANGE < $orange_warn %RED < $red_warn %
"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach ( sort keys %vms_storage ) { my $vm_ds = $vms_storage{$_}; my $vm_disk = $vms_disks{$_}; if(!$vm_disk) { $vm_disk = ""; } print REPORT_OUTPUT "",$vm_disk,"\n"; } print REPORT_OUTPUT "
VMDATASTORE
DISK INFOFREE SPACECAPACITY% FREE
not available
",$_,"",$vm_ds,"
\n"; } %vms_storage = (); } sub printHostVM { my ($local_hosts) = @_; ########################### # PRINT VM SUMMARY ########################### my $seen_vm = 0; push @jump_tags,"        Virtual Machines
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

Virtual Machines:

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\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) { print REPORT_OUTPUT "\n"; my $vm_host_view = Vim::get_view (mo_ref => $vm->runtime->host); if($enable_demo_mode eq 1) { print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; } else { print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; if (defined($vm->guest->hostName)) {print REPORT_OUTPUT ""; } else { print REPORT_OUTPUT ""; } } $seen_vm = 1; my $vm_health = $vm->summary->overallStatus->val; if ($vm_health eq 'green') { print REPORT_OUTPUT ""; } elsif ($vm_health eq 'red') { print REPORT_OUTPUT ""; } elsif ($vm_health eq 'yellow') { print REPORT_OUTPUT ""; } print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; if (defined($vm->summary->config->numVirtualDisks)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (defined($vm->summary->config->numCpu)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (defined($vm->summary->config->memorySizeMB)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } my $isTemplate = $vm->config->template; if (! $isTemplate) { if (defined($vm->summary->quickStats->overallCpuUsage)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (defined($vm->summary->quickStats->guestMemoryUsage)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (defined($vm->summary->config->cpuReservation)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (defined($vm->summary->config->memoryReservation)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } } else { print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; } if (defined($vm->summary->config->numEthernetCards)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (! $isTemplate) { if (defined($vm->summary->guest->toolsStatus->val)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (defined($vm->config->tools->syncTimeWithHost)) { print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (defined($vm->config->tools->toolsVersion)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } if (defined($vm->config->tools->toolsUpgradePolicy)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } print REPORT_OUTPUT ""; if (defined($vm->summary->guest->guestFullName)) {print REPORT_OUTPUT ""; } else {print REPORT_OUTPUT ""; } } else { print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; } print REPORT_OUTPUT ""; 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=""; 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 .= ""; $npiv_string .= ""; 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 => $_); $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 = ""; if($vm_perc_free < $red_warn) { $perc_string = ""; } elsif ($vm_perc_free < $orange_warn) { $perc_string = ""; } elsif ($vm_perc_free < $yellow_warn) { $perc_string = ""; } else { $perc_string = ""; } $disk_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} = ""; $execute_flag = 0; } $seen_vm = 0; } } print REPORT_OUTPUT "
ESX/ESXi HOSTVMHOSTNAMEVM STATUSCONNECTION STATEPOWER STATE# OF DISK(s)# OF vCPU(s)MEMCPU USAGEMEM USAGECPU RESRVMEM RESRV# OF vNIC(s)VMware Tools StatusTIME SYNC w/HOSTTOOLS VERTOOLS UPGRADE POLICYTOOLS MOUNTEDGUEST OSIS TEMPLATE
HIDE ME!",$vm->config->name,"HIDE ME!",$vm_host_view->summary->config->name,"",$vm->config->name,"",$vm->guest->hostName,"UNKNOWNVM is OKVM has a problemVM"; } else { print REPORT_OUTPUT "UNKNOWN",$vm->runtime->connectionState->val,"",$vm->runtime->powerState->val,"",$vm->summary->config->numVirtualDisks,"UNKNOWN",$vm->summary->config->numCpu,"UNKNOWN",prettyPrintData($vm->summary->config->memorySizeMB,'M'),"UNKNOWN",prettyPrintData($vm->summary->quickStats->overallCpuUsage,'MHZ'),"UNKNOWN",prettyPrintData($vm->summary->quickStats->guestMemoryUsage,'M'),"UNKNOWN",prettyPrintData($vm->summary->config->cpuReservation,'MHZ'),"UNKNOWN",prettyPrintData($vm->summary->config->memoryReservation,'M'),"UNKNOWNN/AN/AN/AN/A",$vm->summary->config->numEthernetCards,"UNKNOWN",$vm->summary->guest->toolsStatus->val,"UNKNOWN",($vm->config->tools->syncTimeWithHost) ? "YES" : "NO","UNKNOWN",$vm->config->tools->toolsVersion,"UNKNOWN",$vm->config->tools-> toolsUpgradePolicy,"UNKNOWN",($vm->runtime->toolsInstallerMounted) ? "YES" : "NO" ,"",$vm->summary->guest->guestFullName,"UNKNOWNN/AN/AN/AN/AN/AN/A",($isTemplate) ? "YES" : "NO" ,"
$vm_name$compat_mode$vmhba$disk_mode$lun_uuid$vm_uuid$n_vm"; 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".$vm_perc_free." %".$vm_perc_free." %".$vm_perc_free." %".$vm_perc_free." %$perc_string
$vm_disk_path$vm_disk_free$vm_disk_cap
".$vm_ip_string."".$vm_mac_string."".$vm_pg_string."".$vm_conn_string."
\n"; } sub printHostDatastoreInfo { my ($local_hosts) = @_; ########################### # PRINT DATASTORE SUMMARY ########################### push @jump_tags,"        ESX/ESXi Datastore(s)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

ESX/ESXi Datastore(s):

\n"; print REPORT_OUTPUT "
COLOR LEGENDYELLOW < $yellow_warn %ORANGE < $orange_warn %RED < $red_warn %
"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; my @datastores_seen = (); my @hosts_to_datastores = (); my %datastore_row_info = (); 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 = ""; #capture unique datastores seen in cluster if (!grep {$_ eq $ds->info->name} @datastores_seen) { push @datastores_seen,$ds->info->name; my $perc_free; my $ds_used; my $ds_free; my $ds_cap; my $perc_string = ""; 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); $perc_free = &restrict_num_decimal_digits(( 100 * $ds_free / $ds_cap),2); if($perc_free < $red_warn) { $perc_string = ""; } elsif ($perc_free < $orange_warn) { $perc_string = ""; } elsif ($perc_free < $yellow_warn) { $perc_string = ""; } else { $perc_string = ""; } } else { $perc_free = "UNKNOWN"; $ds_used = "UNKNOWN"; $ds_free = "UNKNOWN"; } $ds_row = "$perc_string"; #get all hosts attached to this datastore my $host_mounts = $ds->host; foreach (@$host_mounts) { my $host_on_datastore = Vim::get_view (mo_ref => $_->key); if($_->mountInfo->accessible) { push @hosts_to_datastores,$host_on_datastore->summary->config->name; } } #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; } #only check if its shared storage #if($ds->summary->multipleHostAccess) { if(@difference) { my $hosts_not_accessible = ""; foreach (@difference) { $hosts_not_accessible .= $_." "; } if($enable_demo_mode eq 1) { $ds_row .= ""; } else { $ds_row .= ""; } } else { $ds_row .= ""; } #} else { $ds_row .= ""; } $datastore_row_info{$ds->info->name} = $ds_row; @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 "",$value,""; } print REPORT_OUTPUT "
DATASTORECAPACITYCONSUMEDFREE% FREEDS TYPEHOST(s) NOT ACCESSIBLE TO DATASTORE
".$perc_free." %".$perc_free." %".$perc_free." %".$perc_free." %".(prettyPrintData($ds->summary->capacity,'B'))."".$ds_used."".prettyPrintData($ds->summary->freeSpace,'B')."".$ds->summary->type."HIDE ME!$hosts_not_accessibleAccessible by all hosts in this clusterN/A
",$datastore,"
\n"; } 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."queueDepth) { $lun_row .= "".$_->queueDepth."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)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

ESX/ESXi LUN(s):

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; for my $lun ( sort keys %lun_row_info ) { my $value = $lun_row_info{$lun}; print REPORT_OUTPUT "",$value,""; } print REPORT_OUTPUT "
UUIDLUNQUEUE DEPTHSTATUSVENDORHOST(s) NOT ACCESSIBLE TO LUN
",$lun,"
\n"; } 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) { my $host_on_portgroup = Vim::get_view (mo_ref => $_); push @hosts_to_portgroups,$host_on_portgroup->summary->config->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)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "

ESX/ESXi Portroup(s):

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; 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 "",$value,""; } print REPORT_OUTPUT "
PORTGROUPHOST(s) NOT ACCESSIBLE TO PORTGROUP
",$portgroup,"
\n"; } sub printHostHardwareInfo { my ($local_hosts) = @_; ########################### # PRINT HOST HARDWARE ########################### push @jump_tags,"        ESX/ESXi hardware configuration
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\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 "\n"; if($enable_demo_mode eq 1) { print REPORT_OUTPUT ""; } else { print REPORT_OUTPUT ""; } print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT "\n"; #capture unique hosts for later use push @hosts_seen,$local_host->summary->config->name; #get vswitch/cdp info #getVswitchInfo($local_host); #get nic getNICInfo($local_host); #get hba getHBAInfo($local_host); } print REPORT_OUTPUT "
HOSTNAMEVENDORCPU INFOHT AVAILABLE/ENABLEDCPU SPEEDCPU USAGECPU PACKAGE(s)CPU CORE(s)CPU THREAD(s)MEMORYMEMORY USAGENIC(s)HBA(s)
HIDE ME!",$local_host->summary->config->name,"",$local_host->summary->hardware->vendor,"",$local_host->summary->hardware->cpuModel,"",($local_host->config->hyperThread->available) ? "YES" : "NO"," / "; print REPORT_OUTPUT ($local_host->config->hyperThread->active) ? "YES" : "NO","",prettyPrintData($local_host->summary->hardware->numCpuCores*$local_host->summary->hardware->cpuMhz,'MHZ'),"",prettyPrintData($local_host->summary->quickStats->overallCpuUsage,'MHZ'),"",$local_host->summary->hardware->numCpuPkgs,"",$local_host->summary->hardware->numCpuCores,"",$local_host->summary->hardware->numCpuThreads,"",prettyPrintData($local_host->summary->hardware->memorySize,'B'),"",prettyPrintData($local_host->summary->quickStats->overallMemoryUsage,'M'),"",$local_host->summary->hardware->numNics,"",$local_host->summary->hardware->numHBAs,"
\n"; #print nic ########################### # PRINT NIC INFO ########################### printNIC(); ########################### # PRINT HBA INFO ########################### printHBA(); #print cdp ########################### # PRINT HOST STATE ########################### print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "

ESX/ESXi state:

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\n"; foreach my $local_host (sort {$a->summary->config->name cmp $b->summary->config->name} @$local_hosts) { print REPORT_OUTPUT "\n"; if($enable_demo_mode eq 1) { print REPORT_OUTPUT ""; } else { print REPORT_OUTPUT ""; } my $host_health = $local_host->overallStatus->val; if ($host_health eq 'green') { print REPORT_OUTPUT ""; } elsif ($host_health eq 'red') { print REPORT_OUTPUT ""; } elsif ($host_health eq 'yellow') { print REPORT_OUTPUT ""; } else { print REPORT_OUTPUT ""; } print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT "\n"; } print REPORT_OUTPUT "
HOSTNAMEOVERALL STATUSPOWER STATECONNECTION STATEMAINTENANCE MODEVMOTION ENABLEDVERSION
HIDE ME!",$local_host->summary->config->name,"HOST is OKHOST has a problemHOST might have a problemUNKNOWN",$local_host->runtime->powerState->val,"",$local_host->runtime->connectionState->val,"",($local_host->summary->runtime->inMaintenanceMode) ? "YES" : "NO" ,"",($local_host->summary->config->vmotionEnabled) ? "YES" : "NO" ,"",${$local_host->summary->config->product}{'fullName'},"
\n"; ########################### # PRINT HOST CONFIG ########################### print REPORT_OUTPUT "\n"; push @jump_tags,"        ESX/ESXi Config (WIP)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

ESX/ESXi Config (WIP):

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\n"; foreach my $local_host (sort {$a->summary->config->name cmp $b->summary->config->name} @$local_hosts) { print REPORT_OUTPUT "\n"; if($enable_demo_mode eq 1) { print REPORT_OUTPUT ""; } else { print REPORT_OUTPUT ""; } if(defined($local_host->config->consoleReservation)) { print REPORT_OUTPUT ""; } else { print REPORT_OUTPUT ""; } my $ntps = $local_host->config->dateTimeInfo->ntpConfig->server; my $ntp_string = ""; if($ntps) { print REPORT_OUTPUT "\n"; } else { print REPORT_OUTPUT ""; } print REPORT_OUTPUT ""; #advconfigs my $advconfigs = Vim::get_view (mo_ref => $local_host->configManager->advancedOption); my $options_ref = $advconfigs->setting; foreach my $option (@$options_ref) { my $key = $option->key; my $value = $option->value; if($key eq 'LVM.EnableResignature') { print REPORT_OUTPUT ""; } if($key eq 'LVM.DisallowSnapshotLun') { print REPORT_OUTPUT ""; } if($key eq 'Disk.UseDeviceReset') { print REPORT_OUTPUT ""; } if($key eq 'Disk.UseLunReset') { print REPORT_OUTPUT ""; } } =no if($local_host->config->activeDiagnosticPartition) { print $local_host->config->activeDiagnosticPartition->diagnosticType,"\n"; print $local_host->config->activeDiagnosticPartition->id->diskName,print $local_host->config->activeDiagnosticPartition->id->partition,"\n"; print $local_host->config->activeDiagnosticPartition->storageType,"\n\n"; } =cut } print REPORT_OUTPUT "
HOSTNAMESC MEMORY
NTP SERVER(s)TIME ZONEGMT OFFSETLOCATION
AUTOSTART MANAGERLVM.EnableResignatureLVM.DisallowSnapshotLunDisk.UseDeviceResetDisk.UseLunReset
HIDE ME!",$local_host->summary->config->name,"",prettyPrintData($local_host->config->consoleReservation->serviceConsoleReserved,'B'),"UNKNOWN\n"; foreach (@$ntps) { $ntp_string .= "$_
"; } print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT "
",$ntp_string,"",$local_host->config->dateTimeInfo->timeZone->description,"",$local_host->config->dateTimeInfo->timeZone->gmtOffset," Sec(s)",$local_host->config->dateTimeInfo->timeZone->name,"
UNKNOWN",($local_host->config->autoStart->defaults->enabled) ? "YES" : "NO","",($value) ? "YES" : "NO","",($value) ? "YES" : "NO","",($value) ? "YES" : "NO","",($value) ? "YES" : "NO","
\n"; } sub printHBA { if(@hba_list) { push @jump_tags,"        ESX/ESXi HBA(s)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

ESX/ESXi HBA(s)

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach (@hba_list) { print REPORT_OUTPUT "",$_,""; } print REPORT_OUTPUT "
HOSTHBA TYPEDEVICEPCIMODELDRIVERSTATUSADDITIONAL INFO
\n"; } @hba_list = (); } sub printNIC { if(@nic_list) { push @jump_tags,"        ESX/ESXi NIC(s)
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

ESX/ESXi NIC(s)

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; foreach (@nic_list) { print REPORT_OUTPUT "",$_,""; } print REPORT_OUTPUT "
HOSTDEVICEPCIDRIVERDUPLEXSPEEDWOL ENABLEDMAC
\n"; } @nic_list = (); } 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 DUPEX" : "HALF-DUPLEX")."".$nic->linkSpeed->speedMb." MB"; } else { $nic_string .= "UNKNOWNUNKNOWN"; } $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.""; } 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 $netMgr = Vim::get_view(mo_ref => $_->configManager->networkSystem); my @physicalNicHintInfo = $netMgr->QueryNetworkHint(); foreach (@physicalNicHintInfo){ foreach ( @{$_} ){ if(defined($_->connectedSwitchPort)) { my $device = $_->device; my $port = $_->connectedSwitchPort->portId; $cdp_enabled{$device} = $port; } } } my $vswitches = $_->config->network->vswitch; foreach my $vSwitch (@$vswitches) { my $pNicName = ""; my $mtu = ""; my $cdp_vswitch = ""; print "Switch Name Num Ports Used Ports MTU Uplinks CDP Enabled\n"; 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}); printf("%-16.14s%-16s%-16s%-8s%-16s%-16s\n\n", $vSwitch->name, $vSwitch->numPorts, $vSwitch->numPorts - $vSwitch->numPortsAvailable, $vSwitch->{mtu}, $pNicName, $cdp_vswitch); my $portGroups = $vSwitch->portgroup; print " PortGroup Name VLAN ID Used Ports Uplinks\n"; foreach my $port (@$portGroups) { my $pg = FindPortGroupbyKey ($netMgr, $vSwitch->key, $port); next unless (defined $pg); my $usedPorts = (defined $pg->port) ? $#{$pg->port} + 1 : 0; printf(" %-22s%-10s%-16s%-16s\n", $pg->spec->name, $pg->spec->vlanId, $usedPorts, $pNicName); } print "\n"; } } 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_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 $cpu_perc_string = ""; my $mem_perc_string = ""; print REPORT_OUTPUT "

\n"; ########################### # PRINT CLUSTER SUMMARY ########################### push @jump_tags,"CLCluster: $cluster_name
"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "

Cluster: $cluster_name

\n"; print REPORT_OUTPUT "

Cluster Statistics:

\n"; print REPORT_OUTPUT "
COLOR LEGENDYELLOW < $yellow_warn %ORANGE < $orange_warn %RED < $red_warn %
"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; if(($local_cluster->summary->effectiveCpu > 0) && ($local_cluster->summary->totalCpu > 0)) { my $cpu_perc_free = &restrict_num_decimal_digits( ((100 * ($local_cluster->summary->effectiveCpu*0.001))/($local_cluster->summary->totalCpu*0.001)),2); if($cpu_perc_free < $red_warn) { $cpu_perc_string = ""; } elsif ($cpu_perc_free < $orange_warn) { $cpu_perc_string = ""; } elsif ($cpu_perc_free < $yellow_warn) { $cpu_perc_string = ""; } else { $cpu_perc_string = ""; } } else { $cpu_perc_string = ""; } print REPORT_OUTPUT $cpu_perc_string; print REPORT_OUTPUT ""; if(($local_cluster->summary->effectiveMemory > 0) && ($local_cluster->summary->totalMemory > 0)) { my $mem_perc_free = &restrict_num_decimal_digits( ((100 * ($local_cluster->summary->effectiveMemory/1024))/($local_cluster->summary->totalMemory/1024/1024/1000)),2); if($mem_perc_free < $red_warn) { $mem_perc_string = ""; } elsif ($mem_perc_free < $orange_warn) { $mem_perc_string = ""; } elsif ($mem_perc_free < $yellow_warn) { $mem_perc_string = ""; } else { $mem_perc_string = ""; } } else { $mem_perc_string = ""; } print REPORT_OUTPUT $mem_perc_string; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT "
AVAILABLE HOST(s)AVAILABLE CPUCPU % FREEAVAILABLE MEMMEM % FREEDRS ENABLEDHA ENABLEDDPM ENABLED
",$cluster_avail_host,"/",$cluster_host_cnt,"",$cluster_avail_cpu,"/",$cluster_cpu_cnt,"".$cpu_perc_free." %".$cpu_perc_free." %".$cpu_perc_free." %".$cpu_perc_free." %0",$cluster_avail_mem,"/",$cluster_mem_cnt,"".$mem_perc_free." %".$mem_perc_free." %".$mem_perc_free." %".$mem_perc_free." %0",($cluster_drs) ? "YES" : "NO","",($cluster_ha) ? "YES" : "NO" ,"",($cluster_dpm) ? "YES" : "NO" ,"
\n"; ########################### # PRINT HA INFO ########################### if($cluster_ha) { print REPORT_OUTPUT "

HA CONFIGURATIONS:

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT "
FAILOVER LEVELADMISSION CONTROLED ENABLEDISOLATION RESPONSERESTART PRIORITY
",$local_cluster->configuration->dasConfig->failoverLevel,"",($local_cluster->configuration->dasConfig->admissionControlEnabled) ? "YES" : "NO","",$local_cluster->configuration->dasConfig->defaultVmSettings->isolationResponse,"",$local_cluster->configuration->dasConfig->defaultVmSettings->restartPriority,"
\n"; } ########################### # PRINT DRS INFO ########################### if($cluster_drs) { print REPORT_OUTPUT "

DRS CONFIGURATIONS:

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; print REPORT_OUTPUT ""; print REPORT_OUTPUT "
DRS BEHAVIORVMOTION RATE
",$local_cluster->configuration->drsConfig->defaultVmBehavior->val,"",$local_cluster->configuration->drsConfig->vmotionRate,"
\n"; } ########################### # PRINT DPM INFO ########################### if($cluster_dpm) { print REPORT_OUTPUT "

DRS CONFIGURATIONS:

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "
DPM BEHAVIOR
",$local_cluster->configurationEx->dpmConfigInfo->defaultDpmBehavior->val,"
\n"; } ########################### # PRINT CLUSTER RULES ########################### my $rules = $local_cluster->configurationEx->rule; if($rules) { print REPORT_OUTPUT "

Cluster Rules:

\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\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 ""; } print REPORT_OUTPUT "
RULE NAMERULE TYPEENABLED
",$rule_name,"",$rule_type,"",($is_enabled) ? "YES" : "NO","
\n"; } } sub printBuildSummary { # get ServiceContent my $content = Vim::get_service_content(); 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 "\n"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT ""; print REPORT_OUTPUT "
BUILDVERSIONFULL NAME
",$content->about->build,"",$content->about->version,"",$content->about->fullName,"

\n"; #please do not touch this, else the jump tags will break print REPORT_OUTPUT "\n//\n"; } sub printStartHeader { print "Generating VMware Health Report \"$report_name\" (this can take a few minutes depending on environment size. Get a cup of coffee/tea and come back) ...\n"; ### begin_: initialize DateTime values 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; $my_time = "Date: $dttime{mon}-$dttime{mday}-$dttime{year} $dttime{hour}:$dttime{min}:$dttime{sec}"; $start_time = time(); open(REPORT_OUTPUT, ">$report_name"); print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "VMware Health Check Report $version - $my_time\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "\n"; print REPORT_OUTPUT "

VMware Health Check Report $version

\n"; print REPORT_OUTPUT "$my_time\n"; } sub printCloseHeader { print REPORT_OUTPUT "

\n"; print REPORT_OUTPUT "
Author: William Lam
"; print REPORT_OUTPUT "
Generated using: vmwareHealthCheck.pl
"; print REPORT_OUTPUT "
™Primp Industries
"; 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 (); } #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; } =head1 NAME vmwareHealthCheck.pl - Generate VMware health check against vCenter Cluster(s). =head1 SYNOPSIS vmwareHealthCheck.pl [--cluster "CLUSTER_NAME"] =head1 DESCRIPTION This script will generate a health check html report on each of the vCenter Cluster(s) for all residing ESX/ESXi hosts. =head1 OPTIONS =head1 EXAMPLES List all of the connected cdrom devices on host abc. vmwareHealthCheck.pl --server "vCENTER_SERVER" --username "vCenter_USERNAME" --password "vCENTER_PASSWORD" =head1 SUPPORTED PLATFORMS All operations are supported on ESX 3.5 and VirtualCenter 2.5 and better.