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 2009/06/03 16:15:51 UTC
svn commit: r781393 -
/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows_mod.pm
Author: arkurth
Date: Wed Jun 3 14:15:51 2009
New Revision: 781393
URL: http://svn.apache.org/viewvc?rev=781393&view=rev
Log:
VCL-23
Added subroutines and added calls in pre_capture() to further automate image creation tasks:
disable_windows_defender()
disable_automatic_updates()
disable_security_center_notifications()
Added condition to delete_file() to check for "Circular directory" warning when rm is used. It now catches this and doesn't display a warning. Other deletion methods are then attempted.
Fixed bug in filesystem_entry_exists() if path specified included backslashes. Added regex to convert them to forward slashes before checking if exists. Changed command to enclose path in double quotes instead of single.
Added ipconfig_renew() subroutine and added call to it from enable_dhcp(). This is necessary because the default gateways are sometimes lost when DHCP is enabled.
Added to the POD documentation for a few of the subroutines.
Modified:
incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows_mod.pm
Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows_mod.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows_mod.pm?rev=781393&r1=781392&r2=781393&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows_mod.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows_mod.pm Wed Jun 3 14:15:51 2009
@@ -71,10 +71,14 @@
=head2 $SOURCE_CONFIGURATION_DIRECTORY
- Data type : Scalar
- Description : Location on management node of script/utilty/configuration
- files needed to configure the OS. This is normally the
- directory under the 'tools' directory specific to this OS.
+ Data type : String
+ Description : Location on the management node of the files specific to this OS
+ module which are needed to configure the loaded OS on a computer.
+ This is normally the directory under 'tools' named after this OS
+ module.
+
+ Example:
+ /usr/local/vcl/tools/Windows
=cut
@@ -83,9 +87,14 @@
=head2 $NODE_CONFIGURATION_DIRECTORY
- Data type : Scalar
- Description : Destination location on computer of
- script/utilty/configuration files needed to configure the OS.
+ Data type : String
+ Description : Location on computer on which an image has been loaded where
+ configuration files reside. The files residing on the managment
+ node in the directory specified by $NODE_CONFIGURATION_DIRECTORY
+ are copied to this directory.
+
+ Example:
+ C:\Cygwin\home\root\VCL
=cut
@@ -101,10 +110,15 @@
=head2 pre_capture
- Parameters : None, but must be called as an object method
- Returns : 1 if successful, 0 if failed
- Description : Performs the steps necessary to prepare a Windows OS to be captured.
- Called by provisioning module's capture() subroutine.
+ Parameters : Hash containing 'end_state' key
+ Returns : If successful: true
+ If failed: false
+ Description : Performs the steps necessary to prepare a Windows OS before an
+ image is captured.
+ This subroutine is called by a provisioning module's capture()
+ subroutine.
+
+ The steps performed are:
=over 3
@@ -132,7 +146,7 @@
=item 1
-Log off all currently logged in users
+ Log off all currently logged in users
=cut
@@ -143,7 +157,7 @@
=item *
-Set root account password to known value
+ Set root account password to known value
=cut
@@ -154,7 +168,7 @@
=item *
-Delete the users assigned to this reservation
+ Delete the users assigned to this reservation
=cut
@@ -165,7 +179,7 @@
=item *
-Copy the capture configuration files to the computer (scripts, utilities, drivers...)
+ Copy the capture configuration files to the computer (scripts, utilities, drivers...)
=cut
@@ -176,7 +190,7 @@
=item *
-Disable autoadminlogon before disabling the pagefile and rebooting
+ Disable autoadminlogon before disabling the pagefile and rebooting
=cut
@@ -187,7 +201,7 @@
=item *
-Disable IPv6
+ Disable IPv6
=cut
@@ -197,17 +211,17 @@
=item *
-Disable dynamic DNS
+ Disable dynamic DNS
=cut
if (!$self->disable_dynamic_dns()) {
notify($ERRORS{'WARNING'}, 0, "unable to disable dynamic dns");
}
-
+
=item *
-Disable Internet Explorer configuration page
+ Disable Internet Explorer configuration page
=cut
@@ -217,7 +231,37 @@
=item *
-Call script to clean up the hard drive
+ Disable Windows Defender
+
+=cut
+
+ if (!$self->disable_windows_defender()) {
+ notify($ERRORS{'WARNING'}, 0, "unable to disable Windows Defender");
+ }
+
+=item *
+
+ Disable Automatic Updates
+
+=cut
+
+ if (!$self->disable_automatic_updates()) {
+ notify($ERRORS{'WARNING'}, 0, "unable to disable automatic updates");
+ }
+
+=item *
+
+ Disable Security Center notifications
+
+=cut
+
+ if (!$self->disable_security_center_notifications()) {
+ notify($ERRORS{'WARNING'}, 0, "unable to disable Security Center notifications");
+ }
+
+=item *
+
+ Clean up the hard drive
=cut
@@ -227,7 +271,7 @@
=item *
-Apply Windows security templates
+ Apply Windows security templates
=cut
@@ -236,16 +280,23 @@
notify($ERRORS{'WARNING'}, 0, "unable to apply security templates");
return 0;
}
-
+
=item *
-Disable the pagefile
+ Configure the network adapters to use DHCP
- ********* node reboots *********
+=cut
+
+ if (!$self->enable_dhcp()) {
+ notify($ERRORS{'WARNING'}, 0, "unable to enable DHCP on the public and private interfaces");
+ return 0;
+ }
=item *
-Disable the pagefile, reboot, and delete pagefile.sys
+ Disable the pagefile, reboot, and delete pagefile.sys
+
+ ********* node reboots *********
=cut
@@ -258,18 +309,7 @@
=item *
-Configure the network adapters to use DHCP
-
-=cut
-
- if (!$self->enable_dhcp()) {
- notify($ERRORS{'WARNING'}, 0, "unable to enable DHCP on the public and private interfaces");
- return 0;
- }
-
-=item *
-
-Allow users to connect remotely
+ Allow users to connect remotely (this does not enable RDP, but allows general remote access)
=cut
@@ -279,7 +319,7 @@
=item *
-Disable RDP access from any address by adding a firewall exception
+ Disable RDP access from any IP address
=cut
@@ -290,7 +330,7 @@
=item *
-Enable SSH access from any IP addresses by adding a firewall exception
+ Enable SSH access from any IP address
=cut
@@ -301,7 +341,7 @@
=item *
-Enable ping access from any IP addresses by adding a firewall exception
+ Enable ping from any IP address
=cut
@@ -312,7 +352,7 @@
=item *
-Reenable the pagefile, this will take effect when the saved image boots
+ Reenable the pagefile
=cut
@@ -323,7 +363,7 @@
=item *
-Set sshd service startup mode to manual
+ Set the Cygwin SSHD service startup mode to manual
=cut
@@ -345,10 +385,16 @@
=head2 post_load
- Parameters : reference to an object of this class
- Returns : 1 if successful, 0 if failed
- Description : Performs the steps necessary to configure a Windows OS after an image has been loaded.
- Called by provisioning module's load() subroutine.
+ Parameters : None.
+ Returns : If successful: true
+ If failed: false
+ Description : Performs the steps necessary to configure a Windows OS after an
+ image has been loaded.
+
+ This subroutine is called by a provisioning module's load()
+ subroutine.
+
+ The steps performed are:
=over 3
@@ -369,7 +415,10 @@
=item 1
-Log off all currently logged in users
+ Log off all currently logged on users
+
+ Do this in case autoadminlogon was enabled during the load process and the user
+ account was not properly logged off.
=cut
@@ -379,17 +428,22 @@
=item *
-Set the Cygwin SSHD server startup mode to auto
+ Set the Cygwin SSHD service startup mode to automatic
+
+ The Cygwin SSHD service startup mode should be set to automatic after an image
+ has been loaded and is ready to be reserved. Access will be lost if the service
+ is not set to automatic and the computer is rebooted.
=cut
if (!$self->set_service_startup_mode('sshd', 'auto')) {
notify($ERRORS{'WARNING'}, 0, "unable to set sshd service startup mode to auto");
+ return 0;
}
=item *
-Set the computer name
+ Set the computer name
=cut
@@ -399,7 +453,7 @@
=item *
-Enable RDP access only from private network by adding a firewall exception
+ Enable RDP access on the private network interface
=cut
@@ -410,7 +464,7 @@
=item *
-Enable SSH access only from private IP addresses by adding a firewall exception
+ Enable SSH access on the private network interface
=cut
@@ -420,7 +474,7 @@
=item *
-Enable ping access only from private IP addresses by adding a firewall exception
+ Enable ping on the private network interface
=cut
@@ -430,7 +484,7 @@
=item *
-Set the "My Computer" description to the image pretty name
+ Set the "My Computer" description to the image pretty name
=cut
@@ -460,7 +514,7 @@
=item *
-Randomize root password
+ Randomize the root account password
=cut
@@ -471,7 +525,7 @@
=item *
-Randomize Administrator password
+ Randomize the Administrator account password
=cut
@@ -482,7 +536,7 @@
=item *
-Check if imagemeta postoption is set to reboot
+ Check if the imagemeta postoption is set to reboot, reboot if necessary
=cut
@@ -815,6 +869,9 @@
elsif (defined($rm_exit_status) && $rm_exit_status == 0) {
notify($ERRORS{'OK'}, 0, "file either deleted or does not exist on $computer_node_name: $path, output:\n@{$rm_output}");
}
+ elsif (defined($rm_output) && grep(/Circular directory structure/i, @{$rm_output})) {
+ notify($ERRORS{'DEBUG'}, 0, "circular directory structure found, rm can't handle this, attempting next deletion method");
+ }
elsif ($rm_exit_status) {
notify($ERRORS{'WARNING'}, 0, "failed to delete file on $computer_node_name: $path, exit status: $rm_exit_status, output:\n@{$rm_output}");
}
@@ -829,6 +886,8 @@
return 1;
}
+ notify($ERRORS{'DEBUG'}, 0, "file still exists: $path, attempting to delete it using cmd.exe /c del");
+
# rm didn't get rid of the file, try del
# Assemble the Windows shell del command and execute it
my $del_command = '$SYSTEMROOT/System32/cmd.exe /c "del /s /q /f /a \\"' . $path . '\\""';
@@ -855,6 +914,8 @@
notify($ERRORS{'DEBUG'}, 0, "confirmed file does not exist: $path");
return 1;
}
+
+ notify($ERRORS{'DEBUG'}, 0, "file still exists: $path, attempting to delete it using cmd.exe /c rmdir");
# Assemble the Windows shell rmdir command and execute it
my $rmdir_command = '$SYSTEMROOT/System32/cmd.exe /c "rmdir /s /q \\"' . $path . '\\""';
@@ -1021,16 +1082,19 @@
notify($ERRORS{'WARNING'}, 0, "unable to detmine if file exists, path was not specified as an argument");
return;
}
+
+ # Replace backslashes with forward slashes
+ $path =~ s/\\+/\//;
# Assemble the ls command and execute it
- my $ls_command = "ls -la '$path'";
+ my $ls_command = "ls -la \"$path\"";
my ($ls_exit_status, $ls_output) = run_ssh_command($computer_node_name, $management_node_keys, $ls_command, '', '', 1);
if (defined($ls_exit_status) && $ls_exit_status == 0) {
notify($ERRORS{'DEBUG'}, 0, "filesystem entry exists on $computer_node_name: $path");
return 1;
}
elsif (defined($ls_exit_status) && $ls_exit_status == 2) {
- notify($ERRORS{'DEBUG'}, 0, "filesystem entry does NOT exist on $computer_node_name: $path");
+ notify($ERRORS{'DEBUG'}, 0, "filesystem entry does NOT exist on $computer_node_name: $path\noutput:\n" . join("\n", @$ls_output));
return 0;
}
elsif ($ls_exit_status) {
@@ -4663,7 +4727,7 @@
notify($ERRORS{'OK'}, 0, "dhcp is already enabled on interface '$interface_name'");
}
elsif (defined($set_dhcp_status)) {
- notify($ERRORS{'OK'}, 0, "unable to set interface '$interface_name' to use dhcp, exit status: $set_dhcp_status, output:\n@{$set_dhcp_output}");
+ notify($ERRORS{'WARNING'}, 0, "unable to set interface '$interface_name' to use dhcp, exit status: $set_dhcp_status, output:\n@{$set_dhcp_output}");
return 0;
}
else {
@@ -4671,11 +4735,59 @@
return 0;
}
} ## end for my $interface_name (@interface_names)
- return 1;
+
+ # Run ipconfig /renew after setting the adapters to use DHCP
+ # The default gateway gets lost otherwise
+ return $self->ipconfig_renew();
} ## end sub enable_dhcp
#/////////////////////////////////////////////////////////////////////////////
+=head2 ipconfig_renew
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub ipconfig_renew {
+ 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 $management_node_keys = $self->data->get_management_node_keys();
+ my $computer_node_name = $self->data->get_computer_node_name();
+
+ my $interface_name_argument = shift;
+
+ # Assemble the ipconfig command, include the interface name if argument was specified
+ my $ipconfig_command = '$SYSTEMROOT/System32/ipconfig.exe /renew';
+ if ($interface_name_argument) {
+ $ipconfig_command .= " \"$interface_name_argument\"";
+ }
+
+ # Run ipconfig
+ 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");
+ }
+ elsif (defined($ipconfig_status)) {
+ notify($ERRORS{'WARNING'}, 0, "unable to run ipconfig /renew, exit status: $ipconfig_status, output:\n@{$ipconfig_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to to run ipconfig /renew");
+ return 0;
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 delete_capture_configuration_files
Parameters :
@@ -6448,7 +6560,7 @@
=head2 get_node_configuration_directory
- Parameters : None
+ Parameters : None.
Returns : String containing filesystem path
Description : Retrieves the $NODE_CONFIGURATION_DIRECTORY variable value the
OS. This is the path on the computer's hard drive where image
@@ -6464,7 +6576,7 @@
=head2 set_computer_name
- Parameters : $computer_name
+ Parameters : $computer_name (optional)
Returns : If successful: true
If failed: false
Description : Sets the registry keys to set the computer name. This subroutine
@@ -6523,6 +6635,173 @@
#/////////////////////////////////////////////////////////////////////////////
+=head2 disable_security_center_notifications
+
+ Parameters : None.
+ Returns : If successful: true
+ If failed: false
+ Description : Disables Windows Security Center notifications which are
+ displayed in the notification area (system tray).
+
+=cut
+
+sub disable_security_center_notifications {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module module object method");
+ return;
+ }
+
+ 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\SOFTWARE\Microsoft\Security Center]
+"AntiSpywareDisableNotify"=dword:00000001
+"AntiVirusDisableNotify"=dword:00000001
+"FirewallDisableNotify"=dword:00000001
+"UacDisableNotify"=dword:00000001
+"UpdatesDisableNotify"=dword:00000001
+"FirstRunDisabled"=dword:00000001
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Security Center\Svc]
+"AntiVirusOverride"=dword:00000001
+"AntiSpywareOverride"=dword:00000001
+"FirewallOverride"=dword:00000001
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "set the registry keys to disable security center notifications");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set the registry key to disable security center notifications");
+ return 0;
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 disable_automatic_updates
+
+ Parameters : None
+ Returns : If successful: true
+ If failed: false
+ Description : Disables Windows Automatic Updates by configuring a local group
+ policy:
+ HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\NoAutoUpdate=1
+
+ This must be done using a policy in order to prevent
+ Windows Security Center will display a warning icon in the
+ notification area. Windows Update can be disabled via the GUI
+ which configures the following key but a warning will be
+ presented to the user:
+ HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update
+
+=cut
+
+sub disable_automatic_updates {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module module object method");
+ return;
+ }
+
+ 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\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU]
+"NoAutoUpdate"=dword:00000001
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "disabled automatic updates");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set the registry key to disable automatic updates");
+ return 0;
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 disable_windows_defender
+
+ Parameters : None
+ Returns : If successful: true
+ If failed: false
+ Description : Disables Windows Defender by doing the following:
+ -Configures local group policy to disable Windows Defender
+ -Removes HKLM...Run registry key to start Windows Defender at logon
+ -Stops the Windows Defender service
+ -Disables the Windows Defender service
+
+=cut
+
+sub disable_windows_defender {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module module object method");
+ return;
+ }
+
+ 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\SOFTWARE\Policies\Microsoft\Windows Defender]
+"DisableAntiSpyware"=dword:00000001
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
+"Windows Defender"=-
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'DEBUG'}, 0, "set the registry keys to disable Windows defender");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set the registry key to disable Windows defender");
+ return 0;
+ }
+
+ # Stop the Windows Defender service
+ if ($self->stop_service('WinDefend')) {
+ notify($ERRORS{'DEBUG'}, 0, "stopped the Windows Defender service");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to stop the Windows Defender service");
+ return 0;
+ }
+
+ # Disable the Windows Defender service
+ if ($self->set_service_startup_mode('WinDefend', 'disabled')) {
+ notify($ERRORS{'DEBUG'}, 0, "disabled the Windows Defender service");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to disable the Windows Defender service");
+ return 0;
+ }
+
+ notify($ERRORS{'OK'}, 0, "disabled Windows Defender");
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
1;
__END__