#!/usr/bin/perl -w # William Lam # http://blogs.vmware.com/vsphere/automation/ use strict; use warnings; use VMware::VIRuntime; use VMware::VILib; my %opts = ( operation => { type => "=s", help => "Operation to perform [list|update]", required => 1, }, key => { type => "=s", help => "Name of advanced option to query", required => 0, }, value => { type => "=s", help => "Value of advanced option to update", required => 0, }, vmname => { type => "=s", help => "Name of VM to query for advanced option", required => 1, }, optionlist => { type => "=s", help => "List of key/value pairs to update", required => 0, }, ); Opts::add_options(%opts); Opts::parse(); Opts::validate(); Util::connect(); my $key = Opts::get_option('key'); my $value = Opts::get_option('value'); my $vmname = Opts::get_option('vmname'); my $operation = Opts::get_option('operation'); my $optionlist = Opts::get_option('optionlist'); my @configOptions = (); my $vm = Vim::find_entity_view(view_type => 'VirtualMachine', filter => {'name' => $vmname}, properties => ['name','runtime.powerState','config.extraConfig']); unless($vm) { print "Unable to locate " . $vmname . "\n"; Util::disconnect(); exit 1; } my $advOptions = $vm->{'config.extraConfig'}; if($operation eq "list") { &getOption(); } elsif($operation eq "update") { if($optionlist) { &processFile($optionlist); } else { unless($key && $value) { print "The \"update\" option requires both key and value parameters to be specified!\n"; Util::disconnect(); exit 1; } } &updateOption(); } else { print "Invalid operation!\n"; } Util::disconnect(); sub getOption { foreach my $option (sort {$a->key cmp $b->key} @$advOptions) { if($key) { if($option->key eq $key) { print "Key: " . $option->{'key'} . "\tValue: " . $option->{'value'} . "\n"; } } else { print "Key: " . $option->{'key'} . "\tValue: " . $option->{'value'} . "\n"; } } } sub processFile { my ($conf) = @_; open(CONFIG, "$conf") || die "Error: Couldn't open the $conf!"; while () { chomp; s/#.*//; # Remove comments s/^\s+//; # Remove opening whitespace s/\s+$//; # Remove closing whitespace next unless length; my ($key,$value) = split(',',$_,2); chomp($key); $key =~ s/^\s+//; chomp($value); my $option = OptionValue->new(key => $key, value => $value); push @configOptions, $option; } close(CONFIG); } sub updateOption { my ($task,$vmSpec); if($optionlist) { eval { print "Reconfiguring " . $vmname . " advanced setting(s) ...\n"; $vmSpec = VirtualMachineConfigSpec->new(extraConfig => \@configOptions); $task = $vm->ReconfigVM_Task(spec => $vmSpec); &getStatus($task,"Successfully updated advanced setting for " . $vmname); }; if($@) { print "Error: Unable to update option - \"" . $key ."=" . $value . "\" " . $@ . "\n"; } } else { eval { print "Reconfiguring " . $vmname . " with advanced setting: " . $key . "=" . $value . " ...\n"; my $option = OptionValue->new(key => $key, value => $value); $vmSpec = VirtualMachineConfigSpec->new(extraConfig => [$option]); $task = $vm->ReconfigVM_Task(spec => $vmSpec); &getStatus($task,"Successfully updated advanced setting for " . $vmname); }; if($@) { print "Error: Unable to update option - \"" . $key ."=" . $value . "\" " . $@ . "\n"; } } } sub getStatus { my ($taskRef,$message) = @_; my $task_view = Vim::get_view(mo_ref => $taskRef); my $taskinfo = $task_view->info->state->val; my $continue = 1; while ($continue) { my $info = $task_view->info; if ($info->state->val eq 'success') { print $message,"\n"; return $info->result; $continue = 0; } elsif ($info->state->val eq 'error') { my $soap_fault = SoapFault->new; $soap_fault->name($info->error->fault); $soap_fault->detail($info->error->fault); $soap_fault->fault_string($info->error->localizedMessage); die "$soap_fault\n"; } sleep 5; $task_view->ViewBase::update_view_data(); } }