You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2016/07/27 22:02:46 UTC

svn commit: r1754346 - /vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm

Author: arkurth
Date: Wed Jul 27 22:02:46 2016
New Revision: 1754346

URL: http://svn.apache.org/viewvc?rev=1754346&view=rev
Log:
VCL-977
Updated VIM_SSH.pm::vm_register to detect vim.fault.AlreadyExists. If so, retrieves the conflicting VM ID and attempts to unregister it.

Updated VIM_SSH.pm::vm_unregister to accept either a vmx file path or VM ID.

Updated VIM_SSH.pm::_run_vim_cmd to accept an $attempt_limit argument. If set to 1 and the exit status isn't 0, used to indicate that exit status and output should be returned and calling subroutine for checking.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm?rev=1754346&r1=1754345&r2=1754346&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm Wed Jul 27 22:02:46 2016
@@ -148,9 +148,24 @@ sub initialize {
 
 =head2 _run_vim_cmd
 
- Parameters  : $vim_arguments, $timeout_seconds (optional)
+ Parameters  : $vim_arguments, $timeout_seconds (optional), $attempt_limit (optional)
  Returns     : array ($exit_status, $output)
- Description : Runs VIM command on the VMware host.
+ Description : Runs vim-cmd command on the VMware host. This was designed to
+               allow it to handle most of the error checking.
+               
+               By default, 5 attempts are made.
+               
+               If the exit status of the vim-cmd command is 0 after any attempt,
+               $exit_status and $output are returned to the calling subroutine.
+               
+               If the exit $attempt_limit > 1 and the status is not 0 after all
+               attempts are made, undefined is returned. This allows the calling
+               subroutine to simply check if result is true if it does not care
+               about the output.
+               
+               There is a special condition if the $attempt_limit is 1 and the
+               exit status is not 0. $exit_status and $output are always
+               returned so calling subroutine can handle the logic.
 
 =cut
 
@@ -168,6 +183,7 @@ sub _run_vim_cmd {
 	}
 	
 	my $timeout_seconds = shift || 60;
+	my $attempt_limit = shift || 5;
 	
 	my $request_state_name = $self->data->get_request_state_name();
 	my $vmhost_computer_name = $self->vmhost_os->data->get_computer_short_name();
@@ -175,7 +191,6 @@ sub _run_vim_cmd {
 	my $command = "$self->{vim_cmd} $vim_arguments";
 	
 	my $attempt = 0;
-	my $attempt_limit = 5;
 	my $wait_seconds = 5;
 	
 	my $connection_reset_errors = 0;
@@ -272,8 +287,8 @@ sub _run_vim_cmd {
 			next ATTEMPT;
 		}
 		elsif ($exit_status != 0) {
-			if (grep(/(Create snapshot failed)/i, @$output)) {
-				notify($ERRORS{'WARNING'}, 0, "attempt $attempt/$attempt_limit: command failed on VM host $vmhost_computer_name, not making another attempt, task error checking will be done by calling subroutine, command: $command, exit status: $exit_status, output:\n" . join("\n", @$output));
+			if ($attempt_limit == 1) {
+				notify($ERRORS{'DEBUG'}, 0, "command failed on VM host $vmhost_computer_name, not making another attempt because attempt limit argument is set to $attempt_limit, error checking will be done by calling subroutine, command: $command, exit status: $exit_status, output:\n" . join("\n", @$output));
 				return ($exit_status, $output);
 			}
 			else {
@@ -1446,7 +1461,7 @@ sub vm_register {
 	
 	$vmx_file_path =~ s/\\* /\\ /g;
 	my $vim_cmd_arguments = "solo/registervm \"$vmx_file_path\"";
-	my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
+	my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments, 60, 1);
 	return if !$output;
 	
 	# Note: registervm does not produce any output if it was successful
@@ -1458,6 +1473,40 @@ sub vm_register {
 	#   msg = "The object or item referred to could not be found.",
 	# }
 	
+	if (grep(/vim.fault.NotFound/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to register VM, vmx file was not found: $vmx_file_path, output:\n" . join("\n", @$output));
+		return;
+	}
+	elsif (grep(/vim.fault.AlreadyExists/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to register VM on the 1st attempt, an existing invalid VM using the same vmx file path may already already be registered, output:\n" . join("\n", @$output));
+		
+		# If an "invalid" VM exists using the same .vmx path, this fault will be generated:
+		#    (vim.fault.AlreadyExists) {
+		#    faultCause = (vmodl.MethodFault) null,
+		#    name = "51",
+		#    msg = "The specified key, name, or identifier '51' already exists."
+		my ($vm_id) = join("\n", @$output) =~ /name\s*=\s*"(\d+)"/;
+		if ($vm_id) {
+			if ($self->vm_unregister($vm_id)) {
+				notify($ERRORS{'DEBUG'}, 0, "unregistered existing invalid VM $vm_id, making another attempt to register VM: $vmx_file_path");
+			}
+			else {
+				notify($ERRORS{'WARNING'}, 0, "failed to register VM: $vmx_file_path, unable to unregister existing invalid VM $vm_id");
+				return;
+			}
+		}
+		else {
+			notify($ERRORS{'WARNING'}, 0, "failed to register VM: $vmx_file_path, ID of existing invalid VM could not be determined, was expecting a line beginning with 'name = \"<ID>\"' in output:\n" . join("\n", @$output));
+			return;
+		}
+	}
+	
+	if (grep(/fault/i, @$output)) {
+		# Only made 1 attempt so far, try again if fault occurred, allow 4 more attempts
+		($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments, 60, 4);
+		return if !$output;
+	}
+	
 	if (grep(/fault/i, @$output)) {
 		notify($ERRORS{'WARNING'}, 0, "failed to register VM: $vmx_file_path, vim-cmd $vim_cmd_arguments output:\n" . join("\n", @$output));
 		return;
@@ -1478,9 +1527,10 @@ sub vm_register {
 
 =head2 vm_unregister
 
- Parameters  : $vmx_file_path
+ Parameters  : $vm_identifier 
  Returns     : boolean
- Description : Unregisters the VM indicated by the vmx file path argument.
+ Description : Unregisters the VM indicated by the argument which may either be
+               the .vmx file path or VM ID.
 
 =cut
 
@@ -1491,39 +1541,51 @@ sub vm_unregister {
 		return;
 	}
 	
-	# Get the vmx file path argument
-	my $vmx_file_path = shift;
-	if (!$vmx_file_path) {
-		notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not supplied");
+	# Note: allow the VM ID to be passed in case the .vmx file path cannot be determined
+	# This allows an invalid VM with a missing .vmx file to be unregistered
+	
+	my $vm_identifier = shift;
+	if (!$vm_identifier) {
+		notify($ERRORS{'WARNING'}, 0, "VM identifier argument was not supplied");
 		return;
 	}
 	
-	# Check if the VM is not registered
-	if (!$self->is_vm_registered($vmx_file_path)) {
-		notify($ERRORS{'OK'}, 0, "VM not unregistered because it is not registered: $vmx_file_path");
-		return 1;
+	my $vm_id;
+	my $vmx_file_path;
+	if ($vm_identifier =~ /^\d+$/) {
+		$vm_id = $vm_identifier;
 	}
-	
-	# Power of the VM if it is powered on or the unregister command will fail
-	my $vm_power_state = $self->get_vm_power_state($vmx_file_path);
-	if ($vm_power_state && $vm_power_state =~ /on/i) {
-		if (!$self->vm_power_off($vmx_file_path)) {
-			notify($ERRORS{'WARNING'}, 0, "failed to unregister VM because it could not be powered off: $vmx_file_path");
+	else {
+		# Argument should be the vmx file path
+		$vmx_file_path = $vm_identifier;
+		
+		# Check if the VM is not registered
+		if (!$self->is_vm_registered($vmx_file_path)) {
+			notify($ERRORS{'OK'}, 0, "VM not unregistered because it is not registered: $vmx_file_path");
+			return 1;
+		}
+		
+		# Power of the VM if it is powered on or the unregister command will fail
+		my $vm_power_state = $self->get_vm_power_state($vmx_file_path);
+		if ($vm_power_state && $vm_power_state =~ /on/i) {
+			if (!$self->vm_power_off($vmx_file_path)) {
+				notify($ERRORS{'WARNING'}, 0, "failed to unregister VM because it could not be powered off: $vmx_file_path");
+				return;
+			}
+		}
+		
+		$vm_id = $self->_get_vm_id($vmx_file_path);
+		if (!defined($vm_id)) {
+			notify($ERRORS{'OK'}, 0, "unable to unregister VM because VM ID could not be determined for vmx path argument: $vmx_file_path");
 			return;
 		}
 	}
 	
-	my $vm_id = $self->_get_vm_id($vmx_file_path);
-	if (!defined($vm_id)) {
-		notify($ERRORS{'OK'}, 0, "unable to unregister VM because VM ID could not be determined for vmx path: $vmx_file_path");
-		return;
-	}
-	
 	my $vim_cmd_arguments = "vmsvc/unregister $vm_id";
 	my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
 	
 	# Delete cached .vmx - VM ID mapping if previously retrieved
-	delete $self->{vm_id}{$vmx_file_path};
+	delete $self->{vm_id}{$vm_identifier};
 	
 	return if !$output;
 	
@@ -1535,18 +1597,18 @@ sub vm_unregister {
 	# }
 	
 	if (grep(/fault/i, @$output)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to unregister VM $vm_id: $vmx_file_path\nVIM command arguments: '$vim_cmd_arguments'\noutput:\n" . join("\n", @$output));
+		notify($ERRORS{'WARNING'}, 0, "failed to unregister VM, VIM command arguments: '$vim_cmd_arguments'\noutput:\n" . join("\n", @$output));
 		return;
 	}
 	
 	# Check to make sure the VM is not registered
-	if (!$self->is_vm_registered($vmx_file_path)) {
-		notify($ERRORS{'OK'}, 0, "unregistered VM: $vmx_file_path (ID: $vm_id)");
-		return 1;
+	if ($vmx_file_path && $self->is_vm_registered($vmx_file_path)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to unregister VM: $vmx_file_path (ID: $vm_id), it still appears to be registered");
+		return;
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to unregister VM: $vmx_file_path  (ID: $vm_id), it still appears to be registered");
-		return;
+		notify($ERRORS{'OK'}, 0, "unregistered VM: $vm_identifier");
+		return 1;
 	}
 }
 
@@ -2064,7 +2126,7 @@ sub create_snapshot {
 	}
 	
 	my $vim_cmd_arguments = "vmsvc/snapshot.create $vm_id '$snapshot_name'";
-	my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
+	my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments, 60, 1);
 	return if !$output;
 	
 	notify($ERRORS{'DEBUG'}, 0, "create snapshot output:\n" . join("\n", @$output));