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;
+       }
 }
 
 #/////////////////////////////////////////////////////////////////////////////


Reply via email to