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 2010/10/08 16:47:28 UTC

svn commit: r1005851 - in /incubator/vcl/trunk/managementnode/lib/VCL/Module/OS: Windows.pm Windows/Version_5.pm Windows/Version_6.pm

Author: arkurth
Date: Fri Oct  8 14:47:27 2010
New Revision: 1005851

URL: http://svn.apache.org/viewvc?rev=1005851&view=rev
Log:
VCL-196
Removed the explicit System32 path in all the places cmd.exe is called.  Calling cmd.exe with the full path causes problems if the Windows OS is 64-bit.  In this case, System32 is C:\Windows\Sysnative, pointing to the 64-bit copy of the System32 directory.  When cmd.exe is called in this manner, you're running the native 64-bit cmd.exe shell, which does not have access to the Sysnative link.  As a result, if you pass a Sysnative path to a subroutine which calls cmd.exe, this path doesn't exist with the cmd.exe shell and problems occur.

Updated Windows.pm::create_directory().  Removed unused option which allowed an array of directories to be passed.  This was done to simplify the subroutine.

VCL-390
Added code to Windows.pm::get_public_ip_address to detect if an auto-generated 169.254 IP address is retrieved.  It this is the case and DHCP is being used, the subroutine attempts to renew the public IP address to obtain a valid one.

VCL-391
Added check to see if tsshutdn.exe exists on the computer where shutdown.exe is called.  shutdown.exe often fails on Windows 2003 when called remotely and tsshutdn.exe works.  tsshutdn.exe is called if it exists.  Otherwise, shutdown.exe is called.

Other
Improved output in Windows.pm::delete_file if an error occurs.

Changed return code of Windows.pm::delete_files_by_pattern from undefined to 1 if the base directory does not exist (meaning there's nothing to delete).  This was causing warnings to be displayed during capture when attempting to delete some files.

Added Windows.pm::create_text_file.  It isn't being called by anything yet.

Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.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=1005851&r1=1005850&r2=1005851&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Fri Oct  8 14:47:27 2010
@@ -966,65 +966,41 @@ sub create_directory {
 
 	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;
 	
-	my @paths;
-
-	# Get 1 or more paths from the subroutine arguments
-	while (my $path = shift) {
-		push @paths, $path;
-	}
-
-	# Make sure at least 1 path was specified
-	if (!@paths) {
-		notify($ERRORS{'WARNING'}, 0, "directory path was not specified as an argument");
+	my $path = shift;
+	if (!$path) {
+		notify($ERRORS{'WARNING'}, 0, "directory path argument was not specified");
 		return;
 	}
 
-	notify($ERRORS{'DEBUG'}, 0, "attempting to create " . scalar @paths . " directories:\n" . join("\n", @paths));
-
-	# Keep a count of paths which couldn't be deleted
-	my $directories_not_created = 0;
+	notify($ERRORS{'DEBUG'}, 0, "attempting to create directory: '$path'");
 
-	# Loop through the paths
-	for my $path (@paths) {
-		notify($ERRORS{'DEBUG'}, 0, "attempting to create directory: $path");
-
-		# Assemble the Windows shell mkdir command and execute it
-		my $mkdir_command = $system32_path . '/cmd.exe /c "mkdir \\"' . $path . '\\""';
-		my ($mkdir_exit_status, $mkdir_output) = run_ssh_command($computer_node_name, $management_node_keys, $mkdir_command, '', '', 1);
-		if (defined($mkdir_exit_status) && $mkdir_exit_status == 0) {
-			notify($ERRORS{'OK'}, 0, "directory created on $computer_node_name: $path, output:\n@{$mkdir_output}");
-		}
-		elsif (defined($mkdir_exit_status) && $mkdir_exit_status == 1 && grep(/already exists/i, @{$mkdir_output})) {
-			notify($ERRORS{'OK'}, 0, "directory already exists on $computer_node_name: $path, exit status: $mkdir_exit_status, output:\n@{$mkdir_output}");
-		}
-		elsif (defined($mkdir_exit_status)) {
-			notify($ERRORS{'WARNING'}, 0, "failed to create directory on $computer_node_name: $path, exit status: $mkdir_exit_status, output:\n@{$mkdir_output}");
-		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to delete file on $computer_node_name: $path");
-			$directories_not_created++;
-			next;
-		}
-
-		# Make sure directory was created
-		if (!$self->file_exists($path)) {
-			notify($ERRORS{'WARNING'}, 0, "filesystem entry does not exist on $computer_node_name: $path");
-			$directories_not_created++;
-			next;
-		}
-		else {
-			notify($ERRORS{'DEBUG'}, 0, "verified that filesystem entry exists on $computer_node_name: $path");
-		}
-	} ## end for my $path (@paths)
+	# Assemble the Windows shell mkdir command and execute it
+	my $mkdir_command = "cmd.exe /c \"mkdir \\\"$path\\\"\"";
+	my ($mkdir_exit_status, $mkdir_output) = run_ssh_command($computer_node_name, $management_node_keys, $mkdir_command, '', '', 1);
+	
+	if (!defined($mkdir_output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to create directory on $computer_node_name: $path");
+		return;
+	}
+	elsif ($mkdir_exit_status == 0) {
+		notify($ERRORS{'OK'}, 0, "created directory on $computer_node_name: '$path'");
+	}
+	elsif (grep(/already exists/i, @$mkdir_output)) {
+		notify($ERRORS{'OK'}, 0, "directory already exists on $computer_node_name: '$path'");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to create directory on $computer_node_name: '$path', exit status: $mkdir_exit_status, output:\n" . join("\n", @$mkdir_output));
+	}
 
-	# Check if any paths couldn't be created
-	if ($directories_not_created) {
-		notify($ERRORS{'WARNING'}, 0, "some paths could not be created");
+	# Make sure directory was created
+	if (!$self->file_exists($path)) {
+		notify($ERRORS{'WARNING'}, 0, "directory does not exist on $computer_node_name: '$path'");
 		return 0;
 	}
 	else {
+		notify($ERRORS{'DEBUG'}, 0, "verified directory exists on $computer_node_name: '$path'");
 		return 1;
 	}
 } ## end sub create_directory
@@ -1057,6 +1033,12 @@ sub delete_file {
 		return;
 	}
 	
+	# Check if file exists before attempting to delete it
+	if (!$self->file_exists($path_argument)) {
+		notify($ERRORS{'OK'}, 0, "failed not deleted because it does not exist: '$path_argument'");
+		return 1;
+	}
+	
 	my $path_unix = $self->format_path_unix($path_argument);
 	my $path_dos = $self->format_path_dos($path_argument);
 	
@@ -1076,24 +1058,28 @@ sub delete_file {
 	$command .= " ; /usr/bin/chmod.exe -Rv 777 $path_unix 2>&1";
 	
 	$command .= " ; echo ---";
-	$command .= " ; echo Calling rm.exe to to delete file...";
+	$command .= " ; echo Calling \\\"rm.exe -rfv $path_unix\\\" to to delete file...";
 	$command .= " ; /usr/bin/rm.exe -rfv $path_unix 2>&1";
 	
 	# Add call to rmdir if the path does not contain a wildcard
 	# rmdir does not accept wildcards
 	if ($path_dos !~ /\*/) {
 		$command .= " ; echo ---";
-		$command .= " ; echo Calling 'cmd.exe /c rmdir' to to delete directory...";
-		$command .= " ; $system32_path/cmd.exe /c \"rmdir /s /q \\\"$path_dos\\\"\" 2>&1";
+		$command .= " ; echo Calling \\\"cmd.exe /c rmdir $path_dos\\\" to to delete directory...";
+		$command .= " ; cmd.exe /c \"rmdir /s /q \\\"$path_dos\\\"\" 2>&1";
 	}
 	
 	$command .= " ; echo ---";
-	$command .= " ; echo Calling 'cmd.exe /c del' to to delete file...";
-	$command .= " ; $system32_path/cmd.exe /c \"del /s /q /f /a \\\"$path_dos\\\" 2>&1\" 2>&1";
+	$command .= " ; echo Calling \\\"cmd.exe /c del $path_dos\\\" to to delete file...";
+	$command .= " ; cmd.exe /c \"del /s /q /f /a \\\"$path_dos\\\" 2>&1\" 2>&1";
 	
 	$command .= " ; echo ---";
-	$command .= " ; echo Calling 'cmd.exe /c dir' to to list remaining files...";
-	$command .= " ; $system32_path/cmd.exe /c \"dir /a /w \\\"$path_dos\\\"\"";
+	$command .= " ; echo Calling \\\"cmd.exe /c dir $path_dos\\\" to to list remaining files...";
+	$command .= " ; cmd.exe /c \"dir /a /w \\\"$path_dos\\\"\" 2>&1";
+	
+	$command .= " ; echo ---";
+	$command .= " ; date +%r";
+	
 	
 	# Run the command
 	my ($exit_status, $output) = run_ssh_command($computer_node_name, $management_node_keys, $command, '', '', 0);
@@ -1102,12 +1088,12 @@ sub delete_file {
 		return;
 	}
 	
-	# Sleep 1 second before checking if file was deleted
-	sleep 1;
+	## Sleep 1 second before checking if file was deleted
+	#sleep 1;
 	
 	# Check if file was deleted
 	if ($self->file_exists($path_argument)) {
-		notify($ERRORS{'WARNING'}, 0, "file still exists: '$path_argument, command:\n$command\noutput:\n" . join("\n", @$output));
+		notify($ERRORS{'WARNING'}, 0, "failed to delete file, it still exists: '$path_argument', command:\n$command\noutput:\n" . join("\n", @$output));
 		return;
 	}
 	else {
@@ -1235,7 +1221,7 @@ sub delete_files_by_pattern {
 	}
 	elsif (grep(/find:.*no such file/i, @$output)) {
 		notify($ERRORS{'OK'}, 0, "files not deleted because base directory does not exist: $base_directory");
-		return;
+		return 1;
 	}
 	elsif (grep(/(^Usage:)/i, @$output)) {
 		notify($ERRORS{'WARNING'}, 0, "failed to delete files under $base_directory matching pattern $pattern\ncommand: $command\noutput:\n" . join("\n", @$output));
@@ -1271,8 +1257,7 @@ sub file_exists {
 
 	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;
-
+	
 	# Get the path from the subroutine arguments and make sure it was passed
 	my $path = shift;
 	if (!$path) {
@@ -1280,22 +1265,22 @@ sub file_exists {
 		return;
 	}
 	
-	$path = $self->format_path_dos($path);
+	my $path_dos = $self->format_path_dos($path);
 	
 	# Assemble the dir command and execute it
-	my $dir_command = "$system32_path/cmd.exe /c \"dir /a /b \\\"$path\\\"\"";
+	my $dir_command = "cmd.exe /c \"dir /a /b \\\"$path_dos\\\"\"";
 	my ($dir_exit_status, $dir_output) = run_ssh_command($computer_node_name, $management_node_keys, $dir_command, '', '', 0);
 	if (!defined($dir_output)) {
 		notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to determine if file exists on $computer_node_name: $path");
 		return;
 	}
 	
-	if (grep(/file not found/i, @$dir_output)) {
-		notify($ERRORS{'DEBUG'}, 0, "file does NOT exist on $computer_node_name: $path");
+	if ($dir_exit_status == 1 || grep(/(file not found|cannot find)/i, @$dir_output)) {
+		notify($ERRORS{'DEBUG'}, 0, "file does NOT exist on $computer_node_name: '$path'");
 		return 0;
 	}
 	else {
-		notify($ERRORS{'DEBUG'}, 0, "file exists on $computer_node_name: $path, dir output:\n" . join("\n", @$dir_output));
+		notify($ERRORS{'DEBUG'}, 0, "file exists on $computer_node_name: '$path'");
 		return 1;
 	}
 }
@@ -2916,7 +2901,7 @@ sub create_startup_scheduled_task {
 	}
 
 	# You cannot create a task if one with the same name already exists
-	# Vista's version of schtasks.exe has a /F which forces a new task to be created if one with the same name already exists
+	# Windows 6.x schtasks.exe has a /F which forces a new task to be created if one with the same name already exists
 	# This option isn't supported with XP and other older versions of Windows
 	if (!$self->delete_scheduled_task($task_name)) {
 		notify($ERRORS{'WARNING'}, 0, "unable to delete existing scheduled task '$task_name' on $computer_node_name");
@@ -3136,16 +3121,29 @@ sub reboot {
 		# Kill the screen saver process, it occasionally prevents reboots and shutdowns from working
 		$self->kill_process('logon.scr');
 		
-		# Initiate the shutdown.exe command to reboot the computer
-		my $shutdown_command = $system32_path . "/shutdown.exe -r -t 0 -f";
-		my ($shutdown_exit_status, $shutdown_output) = run_ssh_command($computer_node_name, $management_node_keys, $shutdown_command);
-		if (defined($shutdown_exit_status) && $shutdown_exit_status == 0) {
+		# Check if tsshutdn.exe exists on the computer
+		# tsshutdn.exe is the preferred utility, shutdown.exe often fails on Windows Server 2003
+		my $reboot_command;
+		if ($self->file_exists("$system32_path/tsshutdn.exe")) {
+			$reboot_command = "$system32_path/tsshutdn.exe 0 /REBOOT /DELAY:0 /V";
+		}
+		else {
+			$reboot_command = "$system32_path/shutdown.exe /r /t 0 /f";
+		}
+		
+		my ($reboot_exit_status, $reboot_output) = run_ssh_command($computer_node_name, $management_node_keys, $reboot_command);
+		if (!defined($reboot_output)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command to reboot $computer_node_name");
+			return;
+		}
+		
+		if ($reboot_exit_status == 0) {
 			notify($ERRORS{'OK'}, 0, "executed reboot command on $computer_node_name");
 		}
-		elsif (defined($shutdown_output) && grep(/processing another action/, @$shutdown_output)) {
+		else {
 			# The following message may be displayed causing the reboot to fail:
 			# The computer is processing another action and thus cannot be shut down. Wait until the computer has finished its action, and then try again.(21) 
-			notify($ERRORS{'WARNING'}, 0, "unable to reboot because of processing another action error on $computer_node_name, computer will be forcefully restarted, exit status: $shutdown_exit_status, output:\n@{$shutdown_output}");
+			notify($ERRORS{'WARNING'}, 0, "failed to reboot $computer_node_name, attempting power reset, output:\n" . join("\n", @$reboot_output));
 			
 			# Call provisioning module's power_reset() subroutine
 			if ($self->provisioner->power_reset()) {
@@ -3153,18 +3151,10 @@ sub reboot {
 			}
 			else {
 				notify($ERRORS{'WARNING'}, 0, "reboot failed, failed to initiate power reset on $computer_node_name");
-				return 0;
+				return;
 			}
 		}
-		elsif (defined($shutdown_exit_status)) {
-			notify($ERRORS{'WARNING'}, 0, "failed to execute reboot command on $computer_node_name, exit status: $shutdown_exit_status, output:\n@{$shutdown_output}");
-			return 0;
-		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command to reboot $computer_node_name");
-			return;
-		}
-	} ## end if ($self->wait_for_ssh(0))
+	}
 	else {
 		# Computer did not respond to ssh
 		notify($ERRORS{'WARNING'}, 0, "$computer_node_name did not respond to ssh, graceful reboot cannot be performed, attempting hard reset");
@@ -3259,7 +3249,7 @@ sub reboot {
 
 =head2 shutdown
 
- Parameters  : 
+ Parameters  : $enable_dhcp
  Returns     : 
  Description : 
 
@@ -3282,7 +3272,7 @@ sub shutdown {
 	# Kill the screen saver process, it occasionally prevents reboots and shutdowns from working
 	$self->kill_process('logon.scr');
 	
-	my $shutdown_command = "/bin/cygstart.exe $system32_path/cmd.exe /c \"";
+	my $shutdown_command = "/bin/cygstart.exe cmd.exe /c \"";
 	
 	if ($disable_dhcp) {
 		notify($ERRORS{'DEBUG'}, 0, "enabling DHCP and shutting down $computer_node_name");
@@ -3294,19 +3284,25 @@ sub shutdown {
 			return;
 		}
 		
-		$shutdown_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set address name=\\\"$private_interface_name\\\" source=dhcp & ";
-		$shutdown_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set dnsservers name=\\\"$private_interface_name\\\" source=dhcp & ";
-		$shutdown_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set address name=\\\"$public_interface_name\\\" source=dhcp & ";
-		$shutdown_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set dnsservers name=\\\"$public_interface_name\\\" source=dhcp & ";
-		$shutdown_command .= "\%SYSTEMROOT\%/System32/ipconfig.exe /release & ";
-		$shutdown_command .= "\%SYSTEMROOT\%/System32/route.exe DELETE 0.0.0.0 MASK 0.0.0.0 & ";
+		$shutdown_command .= "$system32_path/netsh.exe interface ip set address name=\\\"$private_interface_name\\\" source=dhcp & ";
+		$shutdown_command .= "$system32_path/netsh.exe interface ip set dnsservers name=\\\"$private_interface_name\\\" source=dhcp & ";
+		$shutdown_command .= "$system32_path/netsh.exe interface ip set address name=\\\"$public_interface_name\\\" source=dhcp & ";
+		$shutdown_command .= "$system32_path/netsh.exe interface ip set dnsservers name=\\\"$public_interface_name\\\" source=dhcp & ";
+		$shutdown_command .= "$system32_path/ipconfig.exe /release & ";
+		$shutdown_command .= "$system32_path/route.exe DELETE 0.0.0.0 MASK 0.0.0.0 & ";
 	}
 	else {
 		notify($ERRORS{'DEBUG'}, 0, "shutting down $computer_node_name");
 	}
 	
-	# Initiate the shutdown.exe command to reboot the computer
-	$shutdown_command .= "start \%SYSTEMROOT\%/System32/shutdown.exe -s -t 0 -f";
+	# Check if tsshutdn.exe exists on the computer
+	# tsshutdn.exe is the preferred utility, shutdown.exe often fails on Windows Server 2003
+	if ($self->file_exists("$system32_path/tsshutdn.exe")) {
+		$shutdown_command .= "$system32_path/tsshutdn.exe 0 /POWERDOWN /DELAY:0 /V";
+	}
+	else {
+		$shutdown_command .= "$system32_path/shutdown.exe /s /t 0 /f";
+	}
 	
 	$shutdown_command .= "\"";
 	
@@ -3358,6 +3354,71 @@ sub shutdown {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 create_text_file
+
+ Parameters  : $file_path, $file_contents
+ Returns     : boolean
+ Description : Creates a text file on the Windows computer. The $file_contents
+               string argument is converted to ASCII hex values. These values
+               are echo'd on the Windows host which avoids problems with special
+               characters and escaping. If the file already exists it is
+               overwritten.
+
+=cut
+
+sub create_text_file {
+	my $self = shift;
+	if (ref($self) !~ /windows/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my ($file_path, $file_contents_string) = @_;
+	if (!$file_contents_string) {
+		notify($ERRORS{'WARNING'}, 0, "file contents argument was not supplied");
+		return;
+	}
+	
+	my $management_node_keys = $self->data->get_management_node_keys();
+	my $computer_node_name   = $self->data->get_computer_node_name();
+	
+	# Replace Unix newlines with DOS/Windows newlines: \n --> \r\n
+	$file_contents_string =~ s/\r?\n/\r\n/g;
+	
+	# Convert the string to a string containing the hex value of each character
+	# This is done to avoid problems with special characters in the file contents
+	
+	# Split the string up into an array if integers representing each character's ASCII decimal value
+	my @decimal_values = unpack("C*", $file_contents_string);
+	
+	# Convert the ASCII decimal values into hex values and add '\x' before each hex value
+	my @hex_values = map { '\x' . sprintf("%x", $_) } @decimal_values;
+	
+	# Join the hex values together into a string
+	my $hex_string = join('', @hex_values);
+	
+	# Create a command to echo the hex string to the file
+	# Use -e to enable interpretation of backslash escapes
+	my $command .= "echo -e \"$hex_string\" > $file_path 2>&1 && du -b $file_path";
+	my ($exit_status, $output) = run_ssh_command($computer_node_name, $management_node_keys, $command, '', '', 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command to create file on $computer_node_name: $file_path");
+		return;
+	}
+	
+	my ($file_size) = map(/^(\d+)\s/, @$output);
+	
+	if (!defined($file_size) || $file_size !~ /^\d+$/ || grep(/^\w+:/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to create a file on $computer_node_name: $file_path, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	
+	notify($ERRORS{'DEBUG'}, 0, "created file on $computer_node_name: $file_path, size: $file_size bytes");
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 set_service_startup_mode
 
  Parameters  : 
@@ -4798,10 +4859,6 @@ sub get_network_configuration {
 				$network_configuration{$interface_name}{$setting} = $value;
 			}
 		}
-		
-		
-		
-		
 		notify($ERRORS{'DEBUG'}, 0, 'saving network configuration in $self->{network_configuration}');
 		$self->{network_configuration} = \%network_configuration;
 	}
@@ -5073,9 +5130,13 @@ sub get_private_ip_address {
 
 =head2 get_public_ip_address
 
- Parameters  : 
- Returns     : 
- Description : 
+ Parameters  : none
+ Returns     : string
+ Description : Retrieves the public IP address assigned to the computer. If an
+					auto-generated public IP address is detected (169.254.x.x or
+					0.0.0.0), the public interface is using DHCP, and the management
+					node is configured to use DHCP, an attempt will be made to call
+					'ipconfig /renew' to obtain a valid public IP address.
 
 =cut
 
@@ -5085,7 +5146,9 @@ sub get_public_ip_address {
 		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
 		return;
 	}
-
+	
+	my $argument = shift;
+	
 	# Make sure network configuration was retrieved
 	my $network_configuration = $self->get_network_configuration('public');
 	if (!$network_configuration) {
@@ -5093,9 +5156,36 @@ sub get_public_ip_address {
 		return;
 	}
 	
+	my $public_ip_configuration = $self->data->get_management_node_public_ip_configuration();
+	
 	my $interface_name = (keys(%{$network_configuration}))[0];
+	
 	my $ip_address_config = $network_configuration->{$interface_name}{ip_address};
 	my $ip_address = (keys(%$ip_address_config))[0];
+	
+	my $dhcp_enabled = $network_configuration->{$interface_name}{dhcp_enabled};
+	
+	# Check if DHCP is to be used and an auto-generated IP address is detected
+	if ($public_ip_configuration =~ /dhcp/i && $dhcp_enabled =~ /yes/i && $ip_address =~ /^(169\.254\.|0\.0\.0\.0)/) {
+		# Check if this is the 2nd attempt to retrieve the public IP address
+		# This subroutine calls itself with a 'renewed' argument if an auto-generated IP address was detected and 'ipconfig /renew' was called
+		if ($argument && $argument eq 'renewed') {
+			notify($ERRORS{'WARNING'}, 0, "unable to retrieve public IP address, public interface '$interface_name' is still assigned an auto-generated IP address after attempting 'ipconfig /renew \"$interface_name\"'");
+			return;
+		}
+		
+		notify($ERRORS{'WARNING'}, 0, "public interface '$interface_name' has DHCP enabled and is assigned an auto-generated IP address: $ip_address, management node DHCP configuration: '$public_ip_configuration'");
+		
+		# Attempt to renew the IP address
+		if (!$self->ipconfig_renew($interface_name)) {
+			notify($ERRORS{'WARNING'}, 0, "unable to retrieve public IP address, failed to renew the IP address for the public interface '$interface_name'");
+			return;
+		}
+		
+		# Call this subroutine again, pass the 'renewed' argument so that 'ipconfig /renew' isn't called again (prevent infinite loop)
+		return $self->get_public_ip_address('renewed');
+	}
+	
 	notify($ERRORS{'DEBUG'}, 0, "returning public IP address: $ip_address");
 	return $ip_address;
 }
@@ -5294,6 +5384,9 @@ sub ipconfig_renew {
 	my ($ipconfig_status, $ipconfig_output) = run_ssh_command($computer_node_name, $management_node_keys, $ipconfig_command);
 	if (defined($ipconfig_status) && $ipconfig_status == 0) {
 		notify($ERRORS{'OK'}, 0, "ran ipconfig /renew");
+		
+		# Undefined previously retrieved network configuration so that it is retrieved again
+		$self->{network_configuration} = undef;
 	}
 	elsif (defined($ipconfig_status)) {
 		notify($ERRORS{'WARNING'}, 0, "unable to run ipconfig /renew, exit status: $ipconfig_status, output:\n@{$ipconfig_output}");
@@ -5869,7 +5962,7 @@ sub run_gpupdate {
 	my $computer_node_name   = $self->data->get_computer_node_name();
 	my $system32_path        = $self->get_system32_path() || return;
 	
-	my $gpupdate_command = "$system32_path/cmd.exe /c \%SYSTEMROOT\%/System32/gpupdate.exe /Force";
+	my $gpupdate_command = "cmd.exe /c $system32_path/gpupdate.exe /Force";
 	my ($gpupdate_status, $gpupdate_output) = run_ssh_command($computer_node_name, $management_node_keys, $gpupdate_command);
 	if (defined($gpupdate_output) && !grep(/error/i, @{$gpupdate_output})) {
 		notify($ERRORS{'OK'}, 0, "ran gpupdate /force");
@@ -6890,14 +6983,14 @@ sub kill_process {
 		notify($ERRORS{'OK'}, 0, scalar @killed . "processe(s) killed matching pattern: $task_pattern\n" . join("\n", @killed));
 	}
 	elsif (defined($taskkill_exit_status) && $taskkill_exit_status == 0 && grep(/No tasks running/i, @{$taskkill_output})) {
-		notify($ERRORS{'DEBUG'}, 0, "process does not exist matching patterh: $task_pattern");
+		notify($ERRORS{'DEBUG'}, 0, "process does not exist matching pattern: $task_pattern");
 	}
 	elsif (defined($taskkill_exit_status)) {
-		notify($ERRORS{'WARNING'}, 0, "unable to kill process matching $task_pattern\n" . join("\n", @{$taskkill_output}));
+		notify($ERRORS{'WARNING'}, 0, "unable to kill process matching pattern: $task_pattern\n" . join("\n", @{$taskkill_output}));
 		return;
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to kill process matching $task_pattern");
+		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to kill process matching pattern: $task_pattern");
 		return;
 	}
 	
@@ -6993,42 +7086,42 @@ sub set_computer_name {
 	}
 	
 	# Get the computer name
-	my $computer_name = shift;
-	if (!$computer_name) {
-		$computer_name = $self->data->get_computer_short_name();
-		if (!$computer_name) {
+	my $new_computer_name = shift;
+	if (!$new_computer_name) {
+		$new_computer_name = $self->data->get_computer_short_name();
+		if (!$new_computer_name) {
 			notify($ERRORS{'WARNING'}, 0, "computer name argument was not supplied and could not be retrieved from the reservation data");
 			return;
 		}
 		
 		# Append the image ID to the computer name
 		my $image_id = $self->data->get_image_id();
-		$computer_name .= "-$image_id" if $image_id;
+		$new_computer_name .= "-$image_id" if $image_id;
 	}
-
+	
 	my $management_node_keys = $self->data->get_management_node_keys();
 	my $computer_node_name   = $self->data->get_computer_node_name();
-
+	
 	my $registry_string .= <<"EOF";
 Windows Registry Editor Version 5.00
 
 [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName]
-"ComputerName"="$computer_name"
+"ComputerName"="$new_computer_name"
 
 [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters]
-"NV Hostname"="$computer_name"
+"Hostname"="$new_computer_name"
+"NV Hostname"="$new_computer_name"
 EOF
-
+	
 	# Import the string into the registry
 	if ($self->import_registry_string($registry_string)) {
-		notify($ERRORS{'OK'}, 0, "set registry keys to change the computer name to $computer_name");
+		notify($ERRORS{'DEBUG'}, 0, "set registry keys to change the computer name of $computer_node_name to $new_computer_name");
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to set registry keys to change the computer name to $computer_name");
+		notify($ERRORS{'WARNING'}, 0, "failed to set registry keys to change the computer name of $computer_node_name to $new_computer_name");
 		return;
 	}
 
-	return 1;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -7871,7 +7964,10 @@ sub format_path_dos {
 	}
 	
 	# Replace all forward slashes with 2 backslashes
-	$path =~ s/[\/\\]/\\/g;
+	$path =~ s/[\/\\]/\\\\/g;
+	
+	# Change $VARIABLE to %VARIABLE%
+	$path =~ s/\$([^\\]+)/\%$1\%/g;
 	
 	#notify($ERRORS{'DEBUG'}, 0, "formatted path for DOS: $path");
 	return $path;
@@ -8790,11 +8886,7 @@ sub set_device_path_key {
 	
 	# Find the paths of .inf files in the drivers directory
 	my @inf_paths = $self->get_driver_inf_paths();
-	if (!@inf_paths) {
-		notify($ERRORS{'WARNING'}, 0, "failed to locate driver .inf paths");
-		return;
-	}
-	elsif ($inf_paths[0] eq '0') {
+	if (!@inf_paths || $inf_paths[0] eq '0') {
 		# No driver paths were found, just use the inf path
 		$device_path_value = '%SystemRoot%\\inf';
 		notify($ERRORS{'DEBUG'}, 0, "no driver .inf paths were found");

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm?rev=1005851&r1=1005850&r2=1005851&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm Fri Oct  8 14:47:27 2010
@@ -271,7 +271,7 @@ sub run_sysprep {
 	
 	# Assemble the Sysprep command
 	# Run Sysprep.exe, use cygstart to lauch the .exe and return immediately
-	my $sysprep_command = "/bin/cygstart.exe $system32_path/cmd.exe /c \"";
+	my $sysprep_command = "/bin/cygstart.exe cmd.exe /c \"";
 	
 	# First enable DHCP on the private and public interfaces and delete the default route
 	my $private_interface_name = $self->get_private_interface_name();
@@ -282,20 +282,28 @@ sub run_sysprep {
 	}
 	
 	# Release any DHCP addresses and delete the default route
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/ipconfig.exe /release & ";
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/route.exe DELETE 0.0.0.0 MASK 0.0.0.0 & ";
+	$sysprep_command .= "$system32_path/ipconfig.exe /release & ";
+	$sysprep_command .= "$system32_path/route.exe DELETE 0.0.0.0 MASK 0.0.0.0 & ";
 	
 	# Disable DHCP
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set address name=\\\"$private_interface_name\\\" source=dhcp & ";
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set dns name=\\\"$private_interface_name\\\" source=dhcp & ";
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set address name=\\\"$public_interface_name\\\" source=dhcp & ";
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set dns name=\\\"$public_interface_name\\\" source=dhcp & ";
+	$sysprep_command .= "$system32_path/netsh.exe interface ip set address name=\\\"$private_interface_name\\\" source=dhcp & ";
+	$sysprep_command .= "$system32_path/netsh.exe interface ip set dns name=\\\"$private_interface_name\\\" source=dhcp & ";
+	$sysprep_command .= "$system32_path/netsh.exe interface ip set address name=\\\"$public_interface_name\\\" source=dhcp & ";
+	$sysprep_command .= "$system32_path/netsh.exe interface ip set dns name=\\\"$public_interface_name\\\" source=dhcp & ";
 	
 	# Run Sysprep.exe
 	$sysprep_command .= "C:/Sysprep/sysprep.exe /quiet /reseal /mini /forceshutdown & ";
 	
 	# Shutdown the computer - Sysprep does not always shut the computer down automatically
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/shutdown.exe -s -t 0 -f";
+	# Check if tsshutdn.exe exists on the computer
+	# tsshutdn.exe is the preferred utility, shutdown.exe often fails on Windows Server 2003
+	if ($self->file_exists("$system32_path/tsshutdn.exe")) {
+		$sysprep_command .= "$system32_path/tsshutdn.exe 0 /POWERDOWN /DELAY:0 /V";
+	}
+	else {
+		$sysprep_command .= "$system32_path/shutdown.exe /s /t 0 /f";
+	}
+	
 	$sysprep_command .= "\"";
 	
 	my ($sysprep_status, $sysprep_output) = run_ssh_command($computer_node_name, $management_node_keys, $sysprep_command);

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm?rev=1005851&r1=1005850&r2=1005851&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm Fri Oct  8 14:47:27 2010
@@ -496,7 +496,7 @@ sub run_slmgr_ipk {
 	}
 	
 	# Run cscript.exe slmgr.vbs -ipk to install the product key
-	my $ipk_command = "$system32_path/cmd.exe /c \%SYSTEMROOT\%/System32/cscript.exe //NoLogo \%SYSTEMROOT\%/System32/slmgr.vbs -ipk $product_key";
+	my $ipk_command = "$system32_path/cscript.exe //NoLogo \$SYSTEMROOT/System32/slmgr.vbs -ipk $product_key";
 	my ($ipk_exit_status, $ipk_output) = run_ssh_command($computer_node_name, $management_node_keys, $ipk_command);
 	if (defined($ipk_exit_status) && $ipk_exit_status == 0 && grep(/successfully/i, @$ipk_output)) {
 		notify($ERRORS{'OK'}, 0, "installed product key: $product_key");
@@ -537,7 +537,7 @@ sub run_slmgr_ckms {
 	
 	# Run slmgr.vbs -ckms to clear an existing KMS server from a computer
 	# slmgr.vbs must be run in a command shell using the correct System32 path or the task it's supposed to do won't really take effect
-	my $skms_command = "$system32_path/cmd.exe /c \%SYSTEMROOT\%/System32/cscript.exe //NoLogo \%SYSTEMROOT\%/System32/slmgr.vbs -ckms";
+	my $skms_command = "$system32_path/cscript.exe //NoLogo \$SYSTEMROOT/System32/slmgr.vbs -ckms";
 	my ($skms_exit_status, $skms_output) = run_ssh_command($computer_node_name, $management_node_keys, $skms_command);
 	if (defined($skms_exit_status) && $skms_exit_status == 0 && grep(/successfully/i, @$skms_output)) {
 		notify($ERRORS{'OK'}, 0, "cleared kms server");
@@ -578,7 +578,7 @@ sub run_slmgr_cpky {
 	
 	# Run slmgr.vbs -cpky to clear an existing product key from a computer
 	# slmgr.vbs must be run in a command shell using the correct System32 path or the task it's supposed to do won't really take effect
-	my $skms_command = "$system32_path/cmd.exe /c \%SYSTEMROOT\%/System32/cscript.exe //NoLogo \%SYSTEMROOT\%/System32/slmgr.vbs -cpky";
+	my $skms_command = "$system32_path/cscript.exe //NoLogo \$SYSTEMROOT/System32/slmgr.vbs -cpky";
 	my ($skms_exit_status, $skms_output) = run_ssh_command($computer_node_name, $management_node_keys, $skms_command);
 	if (defined($skms_exit_status) && $skms_exit_status == 0 && grep(/successfully/i, @$skms_output)) {
 		notify($ERRORS{'OK'}, 0, "cleared product key");
@@ -629,7 +629,9 @@ sub run_slmgr_skms {
 	
 	# Run slmgr.vbs -skms to configure the computer to use the KMS server
 	# slmgr.vbs must be run in a command shell using the correct System32 path or the task it's supposed to do won't really take effect
-	my $skms_command = "$system32_path/cmd.exe /c \%SYSTEMROOT\%/System32/cscript.exe //NoLogo \%SYSTEMROOT\%/System32/slmgr.vbs -skms $kms_address:$kms_port";
+	my $skms_command = "$system32_path/cscript.exe //NoLogo \$SYSTEMROOT/System32/slmgr.vbs -skms $kms_address:$kms_port";
+	$skms_command .= " && $system32_path/cscript.exe //NoLogo \$SYSTEMROOT/System32/slmgr.vbs -ato";
+	
 	my ($skms_exit_status, $skms_output) = run_ssh_command($computer_node_name, $management_node_keys, $skms_command);
 	if (defined($skms_exit_status) && $skms_exit_status == 0 && grep(/successfully/i, @$skms_output)) {
 		notify($ERRORS{'OK'}, 0, "set kms server to $kms_address:$kms_port");
@@ -669,7 +671,7 @@ sub run_slmgr_ato {
 	my $system32_path        = $self->get_system32_path() || return;
 	
 	# Run cscript.exe slmgr.vbs -ato to install the product key
-	my $ato_command = "$system32_path/cmd.exe /c \%SYSTEMROOT\%/System32/cscript.exe //NoLogo \%SYSTEMROOT\%/System32/slmgr.vbs -ato";
+	my $ato_command = "$system32_path/cscript.exe //NoLogo \$SYSTEMROOT/System32/slmgr.vbs -ato";
 	my ($ato_exit_status, $ato_output) = run_ssh_command($computer_node_name, $management_node_keys, $ato_command);
 	if (defined($ato_exit_status) && $ato_exit_status == 0 && grep(/successfully/i, @$ato_output)) {
 		notify($ERRORS{'OK'}, 0, "activated license");
@@ -709,7 +711,7 @@ sub run_slmgr_dlv {
 	my $system32_path        = $self->get_system32_path() || return;
 	
 	# Run cscript.exe slmgr.vbs -dlv to install the product key
-	my $dlv_command = "$system32_path/cmd.exe /c \%SYSTEMROOT\%/System32/cscript.exe //NoLogo \%SYSTEMROOT\%/System32/slmgr.vbs -dlv";
+	my $dlv_command = "$system32_path/cscript.exe //NoLogo \$SYSTEMROOT/System32/slmgr.vbs -dlv";
 	my ($dlv_exit_status, $dlv_output) = run_ssh_command($computer_node_name, $management_node_keys, $dlv_command, '', '', 0);
 	if (defined($dlv_exit_status) && $dlv_exit_status == 0) {
 		notify($ERRORS{'OK'}, 0, "licensing information:\n" . join("\n", @$dlv_output));
@@ -750,7 +752,7 @@ sub get_license_status {
 	my $system32_path        = $self->get_system32_path() || return;
 	
 	# Run cscript.exe slmgr.vbs -dlv to get the activation status
-	my $dlv_command = "$system32_path/cmd.exe /c \%SYSTEMROOT\%/System32/cscript.exe //NoLogo \%SYSTEMROOT\%/System32/slmgr.vbs -dlv";
+	my $dlv_command = "$system32_path/cscript.exe //NoLogo \$SYSTEMROOT/System32/slmgr.vbs -dlv";
 	my ($dlv_exit_status, $dlv_output) = run_ssh_command($computer_node_name, $management_node_keys, $dlv_command, '', '', 0);
 	if ($dlv_output && grep(/License Status/i, @$dlv_output)) {
 		#notify($ERRORS{'DEBUG'}, 0, "retrieved license information");
@@ -1592,28 +1594,10 @@ EOF
 	$self->kill_process('logon.scr');
 	
 	# Run Sysprep.exe, use cygstart to lauch the .exe and return immediately
-	my $sysprep_command = "/bin/cygstart.exe $system32_path/cmd.exe /c \"";
-	
-	# First enable DHCP on the private and public interfaces and delete the default route
-	my $private_interface_name = $self->get_private_interface_name();
-	my $public_interface_name = $self->get_public_interface_name();
-	if (!$private_interface_name || !$public_interface_name) {
-		notify($ERRORS{'WARNING'}, 0, "unable to determine private and public interface names, failed to enable DHCP and shut down $computer_node_name");
-		return;
-	}
-	
-	# Release any DHCP addresses and delete the default route
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/ipconfig.exe /release & ";
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/route.exe DELETE 0.0.0.0 MASK 0.0.0.0 & ";
-	
-	# Disable DHCP
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set address name=\\\"$private_interface_name\\\" source=dhcp & ";
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set dns name=\\\"$private_interface_name\\\" source=dhcp & ";
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set address name=\\\"$public_interface_name\\\" source=dhcp & ";
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/netsh.exe interface ip set dns name=\\\"$public_interface_name\\\" source=dhcp & ";
+	my $sysprep_command = "/bin/cygstart.exe cmd.exe /c \"";
 	
 	# Run Sysprep.exe
-	$sysprep_command .= "\%SYSTEMROOT\%/System32/sysprep/sysprep.exe /generalize /oobe /shutdown /quiet /unattend:$system32_path/sysprep/Unattend.xml";
+	$sysprep_command .= "$system32_path/sysprep/sysprep.exe /generalize /oobe /shutdown /quiet /unattend:\$SYSTEMROOT/System32/sysprep/Unattend.xml";
 	
 	$sysprep_command .= "\"";