#!/usr/bin/perl -w # # This is a sample script and is provided as an example only. # This script is provided as is and is no support is provided. # # This script prints names of all VM's with Windows guest use strict; use warnings; use Getopt::Long; use VMware::VIM2Runtime; use VMware::VILib; use VMware::VIRuntime; $Util::script_version = "1.0"; my %opts = ( datacenter => { type => "=s", help => "Datacenter name", required => 1, } ); # read/validate options and connect to the server Opts::add_options(%opts); Opts::parse(); Opts::validate(); Util::connect(); # find datacenter my $datacenter = Opts::get_option('datacenter'); my $datacenter_view = Vim::find_entity_view(view_type => 'Datacenter', filter => { name => $datacenter }); if (!$datacenter_view) { die "Datacenter '" . $datacenter . "' not found\n"; } # get all hosts under this datacenter my $host_views = Vim::find_entity_views(view_type => 'HostSystem', begin_entity => $datacenter_view); # # Prime the %datastore array with the browser objects for each datastore # Will speed up searches for each VM # my %datastore; PrepSearches ($host_views); # print hosts my $counter = 1; print "Hosts found:\n"; foreach my $host (@$host_views) { print "$counter: " . $host->name . "\n"; $counter++; } # print vm's $counter = 1; print "\nVM's found:\n"; # get all VM's under this datacenter my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine', begin_entity => $datacenter_view); ####################################################################################### # Iterate through each Virtual Machine ####################################################################################### foreach my $vm_view (sort {$a->name cmp $b->name} @$vm_views) { my $vm_name = $vm_view->name; # # ListFiles will prepopulate the %fileList array with the list of files in the vm directory # this assumes that files are in the current VM directory # need to fix .... if files are in another directory # my $fileList = ListFiles ($vm_view->summary->config->vmPathName); print "$counter: " . $vm_name . "\n"; # # print information about each virtual machine disk ... if tools is installed then VirtualMachine.guest.disk[] will contain the array of disks # my $disks = $vm_view->guest->disk; if (defined $disks) { print "VM Disks\n"; foreach my $disk (@$disks) { my $capacity = $disk->capacity / (1024 * 1024 * 1024); my $used = (1 - ($disk->freeSpace / $disk->capacity)) * 100; printf (" %s: Capacity %.1fGB; Used %.1f%%\n", $disk->diskPath, $capacity, $used); } } # # skip any virtual machine that has incomplete information # if (! defined $vm_view->layout) { $counter++; next; } my $files = $vm_view->layout; foreach my $file ('configFile', 'disk', 'logFile', 'snapshot', 'swapFile') { my $item = $files->$file; next unless (defined $item); print "$file\n"; # # for snapshots, list the snapshot name, and the files of each snapshot # if ($file eq 'snapshot') { foreach my $snapshot (@$item) { my $i = 0; my $list = $snapshot->snapshotFile; my $name = $snapshot->key->value; print " $name", "\n"; foreach my $element (@{$list}) { print " $i ", $element, " ", FindSize ($fileList, $element), "\n"; $i++; } } } # # for disk files, list the diskFile array elsif ($file eq 'disk') { my $i = 0; foreach my $disk (@{$item}) { foreach my $element (@{$disk->diskFile}) { print " $i: ", $element, " ", FindSize ($fileList, $element), "\n"; $i++; } } } # # the item may have an array of files ... elsif (ref($item) eq 'ARRAY') { my $i = 0; foreach my $element (@{$item}) { print " $i: ", $element, " ", FindSize ($fileList, $element), "\n"; $i++; } } # the item is a simple item else { print " ", $item, " ", FindSize ($fileList, $item), "\n"; } } $counter++; } # disconnect from the server Util::disconnect(); # # The PrepSearches routine simply caches the datastore array with the datastore browser object for. # %datastore indexed by datastore name and holds a pointer to the datastore browser object # sub PrepSearches { my ($host_views) = @_; my @datastore_array; foreach my $host (@$host_views) { foreach my $datastore (@{$host->datastore}) { push (@datastore_array, $datastore); } } my $datastores = Vim::get_views (mo_ref_array => \@datastore_array); foreach my $datastore (@$datastores) { my $browser = Vim::get_view (mo_ref => $datastore->browser); my $name = $datastore->info->name; $datastore{$name} = $browser; } } # # ListFiles simply caches the files in the respective VM directory # # Strip out datastore and directory header from spec # Populate the %list, index by path name, and value is the fileSize # Return pointer to %list structure # sub ListFiles { my ($filename) = @_; my %list; $filename =~ /\[(.*)\](.*\/)([^\/]*)$/; my $name = $1; my $path = "[$1]$2"; my $browser = $datastore{$name}; my $flags = new FileQueryFlags (fileSize => 'true', fileType => 'false', modification => 'true'); my $searchSpec = new HostDatastoreBrowserSearchSpec (details => $flags, matchPattern => ['*']); my $result = $browser->SearchDatastore(datastorePath => $path, searchSpec => $searchSpec); my $files = $result->file; foreach my $file (@$files) { $list{$file->path} = $file->fileSize; } return \%list; } # # FindSize # Takes a filename, strips out the leading path and datastore, and returns the matching string # Should be generalized, just in case the file is stored somewhere else sub FindSize { my ($list, $filename) = @_; if ($filename =~ /\[/) { $filename =~ /\[(.*\/)([^\/]*)$/; $filename = $2; } if (exists $list->{$filename}) { return $list->{$filename}; } else { return "unknown"}; } sub Fail { my ($msg) = @_; Util::disconnect(); die ($msg); exit (); }