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 2012/06/15 23:20:47 UTC

svn commit: r1350805 - /incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm

Author: arkurth
Date: Fri Jun 15 21:20:47 2012
New Revision: 1350805

URL: http://svn.apache.org/viewvc?rev=1350805&view=rev
Log:
VCL-390
Added Windows.pm::get_public_ip_address subroutine. It overloads the one in OS.pm. It contains added logic to try to detect invalid public IP addresses (169.254.*.*, 0.0.0.0). If this is detected, ipconfig /renew is run and the network configuration is retrieved again.

Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1350805&r1=1350804&r2=1350805&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Fri Jun 15 21:20:47 2012
@@ -5581,25 +5581,20 @@ sub get_network_configuration {
 	my $initialization_check_delay = 10;
 	while (++$initialization_check) {
 		# Get the list of running tasks (this returns an array reference of the raw tasklist.exe output)
-		my $task_list_output = $self->get_task_list();
-		if (!$task_list_output) {
-			notify($ERRORS{'WARNING'}, 0, "attempt $initialization_check/$initialization_check_limit: unable to determine if devices are still being initialized, no task list output was retrieved, sleeping for $initialization_check_delay seconds");
+		notify($ERRORS{'DEBUG'}, 0, "attempt $initialization_check/$initialization_check_limit: checking if devices still appear to be initializing before retrieving network configuration");
+		my $task_info = $self->get_task_info('drvinst');
+		if (!defined($task_info)) {
+			notify($ERRORS{'WARNING'}, 0, "attempt $initialization_check/$initialization_check_limit: unable to determine if devices are still being initialized, task information could not be retrieved, sleeping for $initialization_check_delay seconds");
 			sleep $initialization_check_delay;
 			next;
 		}
-		
-		# Check if any running tasks match known patterns which run only when the OS is being initialized
-		my @matching_tasks = grep(/drvinst/, @$task_list_output);
-		if (!@matching_tasks) {
-			notify($ERRORS{'DEBUG'}, 0, "no devices appear to still be initializing, task list output:\n" . join("\n", @$task_list_output));
-			last;
-		}
-		elsif ($initialization_check >= $initialization_check_limit) {
-			notify($ERRORS{'WARNING'}, 0, "attempt $initialization_check/$initialization_check_limit: devices still appear to be initializing, matching tasks:\n" . join("\n", @matching_tasks) . "\n---\ntask list output:\n" . join("\n", @$task_list_output));
+		elsif (!keys(%$task_info)) {
+			#notify($ERRORS{'DEBUG'}, 0, "no devices appear to still be initializing");
+			notify($ERRORS{'DEBUG'}, 0, "no devices appear to still be initializing, tasks:\n" . format_data($task_info));
 			last;
 		}
 		else {
-			notify($ERRORS{'DEBUG'}, 0, "attempt $initialization_check/$initialization_check_limit: devices still appear to be initializing, sleeping for $initialization_check_delay seconds, matching tasks:\n" . join("\n", @matching_tasks));
+			notify($ERRORS{'DEBUG'}, 0, "attempt $initialization_check/$initialization_check_limit: devices still appear to be initializing, sleeping for $initialization_check_delay seconds, matching tasks:\n" . format_data($task_info));
 			sleep $initialization_check_delay;
 		}
 	}
@@ -5710,6 +5705,52 @@ sub get_network_configuration {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_public_ip_address
+
+ Parameters  : none
+ Returns     : string
+ Description : Retrieves the public IP address from the computer. If the
+               management node is configured to use DHCP for public IP
+               addresses, the IP address is checked to make sure it is valid. If
+               the computer has an invalid public IP address (169.254.*.*,
+               0.0.0.0), an attempt is made to run 'ipconfig /renew' and
+               retrieve the network configuration again.
+
+=cut
+
+sub get_public_ip_address {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my $computer_node_name   = $self->data->get_computer_node_name();
+	my $public_ip_configuration = $self->data->get_management_node_public_ip_configuration();
+	
+	my $public_ip_address = $self->get_ip_address('public');
+	
+	# Check to make sure the address is valid if DHCP is used
+	if ($public_ip_configuration =~ /dhcp/i) {
+		if (!$public_ip_address || $public_ip_address =~ /^(169\.254|0\.0\.0\.0)/) {
+			notify($ERRORS{'WARNING'}, 0, "$computer_node_name is assigned an invalid public IP address: $public_ip_address, attempting to run ipconfig /renew");
+			delete $self->{network_configuration};
+			$self->ipconfig_renew('public');
+			
+			$public_ip_address = $self->get_ip_address('public');
+			if (!$public_ip_address || $public_ip_address =~ /^(169\.254|0\.0\.0\.0)/) {
+				notify($ERRORS{'CRITICAL'}, 0, "$computer_node_name failed to obtain a valid public IP address: $public_ip_address");
+				return;
+			}
+		}
+	}
+	
+	notify($ERRORS{'DEBUG'}, 0, "retrieved public IP address of $computer_node_name: $public_ip_address");
+	return $public_ip_address;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 enable_dhcp
 
  Parameters  : 
@@ -5875,7 +5916,7 @@ sub ipconfig_renew {
 			notify($ERRORS{'WARNING'}, 0, "attempt $attempt/$attempt_limit: failed to renew IP configuration for interface '$interface_name', exit status: $ipconfig_status, output:\n" . join("\n", @$ipconfig_output));
 			return;
 		}
-		elsif ($ipconfig_status ne '0' || grep(/error occurred/i, @$ipconfig_output) || !grep(/IP Address/i, @$ipconfig_output)) {
+		elsif ($ipconfig_status ne '0' || grep(/error occurred/i, @$ipconfig_output)) {
 			notify($ERRORS{'WARNING'}, 0, "attempt $attempt/$attempt_limit: failed to renew IP configuration for interface '$interface_name', exit status: $ipconfig_status, command: '$ipconfig_command', output:\n" . join("\n", @$ipconfig_output));
 		}
 		else {
@@ -7306,12 +7347,84 @@ sub get_task_list {
 		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to run tasklist.exe");
 		return;
 	}
-
+	
 	return $tasklist_output;
 } ## end sub get_task_list
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_task_info
+
+ Parameters  : $pattern (optional)
+ Returns     : hash reference
+ Description : Runs tasklist.exe and returns a hash reference containing
+               information about the processes running on the computer. The hash
+               keys are the process PIDs.
+
+=cut
+
+sub get_task_info {
+	my $self = shift;
+	if (!ref($self)) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my $pattern = shift;
+	
+	my $management_node_keys = $self->data->get_management_node_keys();
+	my $computer_node_name   = $self->data->get_computer_node_name();
+	my $system32_path        = $self->get_system32_path() || return;
+	
+	# Attempt to run tasklist.exe with /NH for no header
+	my $tasklist_command = $system32_path . '/tasklist.exe /V /FO CSV';
+	my ($tasklist_exit_status, $tasklist_output) = run_ssh_command($computer_node_name, $management_node_keys, $tasklist_command, '', '', 0);
+	if (defined($tasklist_exit_status) && $tasklist_exit_status == 0) {
+		notify($ERRORS{'DEBUG'}, 0, "ran tasklist.exe");
+	}
+	elsif (defined($tasklist_exit_status)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to run tasklist.exe, exit status: $tasklist_exit_status, output:\n@{$tasklist_output}");
+		return;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to run tasklist.exe");
+		return;
+	}
+	
+	use Text::CSV_XS;
+	use IO::String;
+	
+	my $csv = Text::CSV_XS->new();
+	
+	my $heading_line = shift @$tasklist_output;
+	$csv->parse($heading_line);
+	
+	my @column_names = $csv->fields();
+	
+	
+	notify($ERRORS{'DEBUG'}, 0, "column names: " . join(", ", @column_names));
+	$csv->column_names(@column_names);
+	
+	my $tasklist_io = IO::String->new(join("\n", @$tasklist_output));
+	
+	my $tasks = $csv->getline_hr_all($tasklist_io);
+	
+	my $task_info = {};
+	for my $task (@$tasks) {
+		my $task_pid = $task->{'PID'};
+		my $task_name = $task->{'Image Name'};
+		
+		if ($pattern && $task_name !~ /$pattern/i) {
+			next;
+		}
+		$task_info->{$task_pid} = $task;
+	}
+	notify($ERRORS{'DEBUG'}, 0, "task info:\n" . format_data($task_info));
+	return $task_info;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 apply_security_templates
 
  Parameters  : None