Author: arkurth
Date: Wed Oct 13 16:58:52 2010
New Revision: 1022187
URL: http://svn.apache.org/viewvc?rev=1022187&view=rev
Log:
VCL-390
Updated Windows.pm::get_network_configuration to call
utils.pm::is_public_ip_address(). This code was duplicated in the Windows.pm
subroutine and was missing some additional logic included in utils.pm.
Previously, the Windows subroutine considered 169.254 addresses public and
would return the first one it found if the public information was requested.
This caused the wrong information to be returned if another interface with a
valid public address exists.
VCL-391
Updated places where tsshutdn.exe or shutdown.exe is called to only call
tsshutdn.exe if Windows Server 2003 is used. I've seen this hang on Windows XP.
Other
Added Windows.pm::clear_event_log. This is called before a computer is
shutdown if Sysprep is not used. This causes only the events that happen
during and after an image is loaded to appear in the Event Viewer, making it
easier to determine the events related to that image being loaded and also
removing older security events which the reservation user shouldn't see.
Modified:
incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.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=1022187&r1=1022186&r2=1022187&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Wed Oct 13
16:58:52 2010
@@ -3124,7 +3124,8 @@ sub reboot {
# 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")) {
+ my $windows_product_name = $self->get_product_name() || '';
+ if ($windows_product_name =~ /2003/ &&
$self->file_exists("$system32_path/tsshutdn.exe")) {
$reboot_command = "$system32_path/tsshutdn.exe 0
/REBOOT /DELAY:0 /V";
}
else {
@@ -3272,6 +3273,9 @@ sub shutdown {
# Kill the screen saver process, it occasionally prevents reboots and
shutdowns from working
$self->kill_process('logon.scr');
+ # Clear the event log before shutting down
+ $self->clear_event_log();
+
my $shutdown_command = "/bin/cygstart.exe cmd.exe /c \"";
if ($disable_dhcp) {
@@ -3296,8 +3300,9 @@ sub shutdown {
}
# 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")) {
+ # tsshutdn.exe is the preferred utility for Windows 2003, shutdown.exe
often fails
+ my $windows_product_name = $self->get_product_name() || '';
+ if ($windows_product_name =~ /2003/ &&
$self->file_exists("$system32_path/tsshutdn.exe")) {
$shutdown_command .= "$system32_path/tsshutdn.exe 0 /POWERDOWN
/DELAY:0 /V";
}
else {
@@ -4897,7 +4902,7 @@ sub get_network_configuration {
}
# Check if interface has private IP address assigned to it
- if (grep(/$computer_private_ip_address/, @ip_addresses)) {
+ if (grep { $_ eq $computer_private_ip_address } @ip_addresses) {
# If private interface information was requested,
return a hash containing only this interface
notify($ERRORS{'DEBUG'}, 0, "private interface found:
$interface_name, description: $description, address(es): " . join (", ",
@ip_addresses));
if ($network_type =~ /private/i) {
@@ -4911,42 +4916,19 @@ sub get_network_configuration {
}
# Check if the interface should be ignored based on the name or
description
- if ($interface_name =~
/loopback|vmnet|afs|tunnel|6to4|isatap|teredo/i) {
- notify($ERRORS{'DEBUG'}, 0, "interface ignored because
of name: $interface_name, description: $description, address(es): " . join (",
", @ip_addresses));
+ if ($interface_name =~
/(loopback|vmnet|afs|tunnel|6to4|isatap|teredo)/i) {
+ notify($ERRORS{'DEBUG'}, 0, "interface
'$interface_name' ignored because name contains '$1', address(es): " . join (",
", @ip_addresses));
next;
}
- elsif ($description =~
/loopback|virtual|afs|tunnel|pseudo|6to4|isatap/i) {
- notify($ERRORS{'DEBUG'}, 0, "interface ignored because
of description: $interface_name, description: $description, address(es): " .
join (", ", @ip_addresses));
+ elsif ($description =~
/(loopback|virtual|afs|tunnel|pseudo|6to4|isatap)/i) {
+ notify($ERRORS{'DEBUG'}, 0, "interface
'$interface_name' ignored because description contains '$1': '$description',
address(es): " . join (", ", @ip_addresses));
next;
}
# Loop through the IP addresses for the interface
# Once a public address is found, return the data for that
interface
for my $ip_address (@ip_addresses) {
- # Split up the IP address being checked into its octets
- my @octets = split(/\./, $ip_address);
-
- # Determine if this is a private or public address
- # Private:
- # 10.0.0.0 - 10.255.255.255
- # 172.16.0.0 - 172.16.31.255.255
- # 192.168.0.0 - 192.168.255.255
- if (($octets[0] == 10) ||
- ($octets[0] != 172 && ($octets[1] >= 16 &&
$octets[1] <= 31)) ||
- ($octets[0] == 192 && $octets[1] == 168)
- ) {
- notify($ERRORS{'DEBUG'}, 0, "interface found
with private address not matching private address for reservation:
$interface_name, description: $description, address(es): " . join (", ",
@ip_addresses));
-
- if (keys(%public_interface)) {
- notify($ERRORS{'DEBUG'}, 0, "already
found another interface with a private address not matching private address for
reservation, this one will be used if a public address isn't found");
- next;
- }
- else {
- notify($ERRORS{'DEBUG'}, 0, "interface
will be returned if another with a public address isn't found");
- $public_interface{$interface_name} =
$network_configuration{$interface_name};
- }
- }
- else {
+ if (is_public_ip_address($ip_address)) {
notify($ERRORS{'DEBUG'}, 0, "public interface
found: $interface_name, description: $description, address(es): " . join (", ",
@ip_addresses));
if ($network_type =~ /public/i) {
my %return_hash = ($interface_name =>
$network_configuration{$interface_name});
@@ -4957,6 +4939,19 @@ sub get_network_configuration {
next;
}
}
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "interface found
with non-public address not matching private address for reservation:
$interface_name, description: $description, address(es): " . join (", ",
@ip_addresses));
+
+ if (keys(%public_interface)) {
+ notify($ERRORS{'DEBUG'}, 0, "already
found another interface with a non-public address not matching private address
for reservation, this one will be used if a public address isn't found");
+ next;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "interface
will be returned if another with a public address isn't found");
+ $public_interface{$interface_name} =
$network_configuration{$interface_name};
+ }
+ }
+
}
}
@@ -9726,6 +9721,64 @@ sub sanitize_files {
#/////////////////////////////////////////////////////////////////////////////
+=head2 clear_event_log
+
+ Parameters : @logfile_names (optional)
+ Returns : boolean
+ Description : Clears the Windows 'Application', 'Security', 'System' event
+ logs. One or more event logfile names may be specified to only
+ clear certain event logs.
+
+=cut
+
+sub clear_event_log {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ my @logfile_names = @_;
+ @logfile_names = ('Application', 'Security', 'System') if
!...@logfile_names;
+
+ 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;
+
+ # Assemble the command
+ # Call wmic.exe - the WMI shell
+ # wmic.exe will hang if it is called by itself. It has something to do
with TTY/PTY
+ # Piping the echo command seems to prevent it from hanging
+ my $command;
+ for my $logfile_name (@logfile_names) {
+ $command .= "echo | $system32_path/Wbem/wmic.exe NTEVENTLOG
WHERE LogFileName=\\\"$logfile_name\\\" CALL ClearEventLog ; ";
+ }
+
+ # Remove the last ' ; ' added to the command
+ $command =~ s/[\s;]*$//g;
+
+ my ($status, $output) = run_ssh_command($computer_node_name,
$management_node_keys, $command);
+ if (!defined($output)) {
+ notify($ERRORS{'DEBUG'}, 0, "failed to run SSH command to clear
the event log: @logfile_names");
+ return;
+ }
+ elsif (grep(/ERROR/i, @$output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to clear event log:
@logfile_names, output:\n" . join("\n", @$output));
+ return;
+ }
+ elsif (grep(/Method execution successful/i, @$output)) {
+ notify($ERRORS{'DEBUG'}, 0, "cleared event log:
@logfile_names");
+ $self->create_eventlog_entry("Event log cleared by VCL");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "unexpected output while clearing
event log: @logfile_names, output:\n" . join("\n", @$output));
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
1;
__END__
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=1022187&r1=1022186&r2=1022187&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
Wed Oct 13 16:58:52 2010
@@ -273,31 +273,14 @@ sub run_sysprep {
# Run Sysprep.exe, use cygstart to lauch the .exe and return immediately
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();
- 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 .= "$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 .= "$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
# 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")) {
+ my $windows_product_name = $self->get_product_name() || '';
+ if ($windows_product_name =~ /2003/ &&
$self->file_exists("$system32_path/tsshutdn.exe")) {
$sysprep_command .= "$system32_path/tsshutdn.exe 0 /POWERDOWN
/DELAY:0 /V";
}
else {
@@ -333,12 +316,27 @@ sub run_sysprep {
notify($ERRORS{'OK'}, 0, "unable to determine power status of
$computer_node_name from provisioning module, sleeping 5 minutes to allow
computer time to power off");
sleep 300;
}
- elsif (!$power_off) {
+ elsif ($power_off) {
+ notify($ERRORS{'OK'}, 0, "$computer_node_name powered off after
running Sysprep.exe");
+ return 1;
+ }
+ else {
notify($ERRORS{'WARNING'}, 0, "$computer_node_name never
powered off after running sysprep.exe");
- return;
}
- return 1;
+ # Computer never powered off, check if provisioning module can
forcefully power off the computer
+ if (!$self->provisioner->can('power_off')) {
+ notify($ERRORS{'OK'}, 0, "provisioning module does not
implement a power_off subroutine");
+ return 1;
+ }
+ elsif ($self->provisioner->power_off()) {
+ notify($ERRORS{'OK'}, 0, "forcefully powered off
$computer_node_name");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to forcefully power off
$computer_node_name");
+ return 0;
+ }
}
#/////////////////////////////////////////////////////////////////////////////