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 2008/12/17 22:42:46 UTC
svn commit: r727522 -
/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Desktop/Vista.pm
Author: arkurth
Date: Wed Dec 17 13:42:45 2008
New Revision: 727522
URL: http://svn.apache.org/viewvc?rev=727522&view=rev
Log:
Updated Vista.pm. Added several subroutines for image capture and load support.
Modified:
incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Desktop/Vista.pm
Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Desktop/Vista.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Desktop/Vista.pm?rev=727522&r1=727521&r2=727522&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Desktop/Vista.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Desktop/Vista.pm Wed Dec 17 13:42:45 2008
@@ -74,6 +74,9 @@
our $CONFIGURATION_DIRECTORY = "$TOOLS/Sysprep_Vista";
+# Node variables
+our $NODE_CONFIGURATION_DIRECTORY = 'C:/VCL';
+
=head2 $ROOT_PASSWORD
Data type : Scalar
@@ -91,6 +94,83 @@
#/////////////////////////////////////////////////////////////////////////////
+=head2 post_reload
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub post_reload {
+ 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 $image_name = $self->data->get_image_name();
+ my $computer_node_name = $self->data->get_computer_node_name();
+
+ notify($ERRORS{'OK'}, 0, "beginning Windows Vista post-reload preparation tasks: $image_name on $computer_node_name");
+
+ # Run NewSID
+ if (!$self->run_newsid()) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, unable to run newsid.exe on $computer_node_name");
+ return 0;
+ }
+
+ # Reboot the computer in order for the newsid changes to take effect
+ if (!$self->reboot()) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to reboot computer after disabling pagefile");
+ return 0;
+ }
+
+ # Set KMS licensing
+ if (!$self->set_kms_licensing()) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to configure node for KMS licensing");
+ return 0;
+ }
+
+ # Activate
+ if (!$self->activate_licensing()) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to activate licensing");
+ return 0;
+ }
+
+ ## Randomize root password
+ #my $root_random_password = getpw();
+ #if (!$self->set_password('root', $root_random_password)) {
+ # notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to set random root password");
+ # return 0;
+ #}
+
+ # Randomize Administrator password
+ my $administrator_random_password = getpw();
+ if (!$self->set_password('Administrator', $administrator_random_password)) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to set random Administrator password");
+ return 0;
+ }
+
+ # Disable RDP
+ if (!$self->firewall_disable_rdp()) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to disable RDP");
+ return 0;
+ }
+
+ # Set sshd service startup to auto
+ if (!$self->set_service_startup_mode('sshd', 'auto')) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to set sshd service startup mode to auto");
+ return 0;
+ }
+
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration successful, returning 1");
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 capture_prepare
Parameters :
@@ -103,7 +183,7 @@
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 0;
+ return;
}
my $request_id = $self->data->get_request_id();
@@ -125,286 +205,226 @@
notify($ERRORS{'OK'}, 0, "beginning Windows Vista image capture preparation tasks: $image_name on $computer_short_name");
- $self->disable_autoadminlogon();
- #$self->import_registry_file("$CONFIGURATION_DIRECTORY/Scripts/test.reg");
- #$self->disable_pagefile();
- #$self->firewall_disable_rdp();
- #$self->firewall_enable_rdp('152.1.0.0/16');
- exit;
-
- # Node variables
- my $local_configuration_directory = 'C:/VCL';
- my $local_scripts_directory = 'C:/VCL/Scripts';
+ # Log off all currently logged in users
+ if (!$self->logoff_users()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to log off all currently logged in users on $computer_node_name");
+ return 0;
+ }
+
+ # Set root account password to known value
+ if (!$self->set_password('root', $ROOT_PASSWORD)) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to set root password");
+ return 0;
+ }
+
+ # Delete the user assigned to this reservation
+ if (!$self->delete_user()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to delete user");
+ return 0;
+ }
+
+ # Disable all RDP access by removing firewall exceptions
+ if (!$self->firewall_disable_rdp()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable RDP");
+ return 0;
+ }
+
+ # Enable RDP access from private IP addresses by adding a firewall exception
+ if (!$self->firewall_enable_rdp('10.0.0.0/8')) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to enable RDP from private IP addresses");
+ return 0;
+ }
+
+$self->firewall_enable_rdp('152.14.52.0/24');
+
+ # Enable SSH access from private IP addresses by adding a firewall exception
+ if (!$self->firewall_enable_ssh_private()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to enable SSH from private IP addresses");
+ return 0;
+ }
+ # Enable ping access from private IP addresses by adding a firewall exception
+ if (!$self->firewall_enable_ping_private()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to enable ping from private IP addresses");
+ return 0;
+ }
+
+ # Create startup scheduled task to prepare computer
+ if (!$self->create_startup_scheduled_task('VCL Startup Configuration', $NODE_CONFIGURATION_DIRECTORY . '/Scripts/VCLPrepare.cmd >> ' . $NODE_CONFIGURATION_DIRECTORY . '/Logs/VCLPrepare.log')) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to create startup scheduled task");
+ return 0;
+ }
# Remove old configuration files if they exist
- notify($ERRORS{'OK'}, 0, "attempting to remove old configuration directory if it exists: $local_configuration_directory");
- my ($remove_old_status, $remove_old_output) = run_ssh_command($computer_node_name, $management_node_keys, "/usr/bin/rm.exe -rf $local_configuration_directory");
+ notify($ERRORS{'OK'}, 0, "attempting to remove old configuration directory if it exists: $NODE_CONFIGURATION_DIRECTORY");
+ my ($remove_old_status, $remove_old_output) = run_ssh_command($computer_node_name, $management_node_keys, "/usr/bin/rm.exe -rf $NODE_CONFIGURATION_DIRECTORY");
if (defined($remove_old_status) && $remove_old_status == 0) {
- notify($ERRORS{'OK'}, 0, "removed existing configuration directory: $local_configuration_directory");
+ notify($ERRORS{'OK'}, 0, "removed existing configuration directory: $NODE_CONFIGURATION_DIRECTORY");
}
elsif (defined($remove_old_status)) {
- notify($ERRORS{'OK'}, 0, "unable to remove existing configuration directory: $local_configuration_directory, exit status: $remove_old_status, output:\n@{$remove_old_output}");
+ notify($ERRORS{'WARNING'}, 0, "unable to remove existing configuration directory: $NODE_CONFIGURATION_DIRECTORY, exit status: $remove_old_status, output:\n@{$remove_old_output}");
+ return 0;
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to remove existing configuration directory: $local_configuration_directory");
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, failed to run ssh command to remove existing configuration directory: $NODE_CONFIGURATION_DIRECTORY");
return 0;
}
-
# Copy configuration files
- notify($ERRORS{'OK'}, 0, "copying Sysprep and other configuration files to $computer_short_name");
- if (run_scp_command($CONFIGURATION_DIRECTORY, "$computer_node_name:$local_configuration_directory", $IDENTITY_wxp)) {
- notify($ERRORS{'OK'}, 0, "copied $CONFIGURATION_DIRECTORY directory to $computer_node_name:$local_configuration_directory");
-
- notify($ERRORS{'OK'}, 0, "attempting to set permissions on $computer_node_name:$local_configuration_directory");
- if (run_ssh_command($computer_node_name, $IDENTITY_wxp, "/usr/bin/chmod.exe -R 755 $local_configuration_directory")) {
- notify($ERRORS{'OK'}, 0, "chmoded -R 755 $computer_node_name:$local_configuration_directory");
+ notify($ERRORS{'OK'}, 0, "copying image capture configuration files to $computer_short_name");
+ if (run_scp_command($CONFIGURATION_DIRECTORY, "$computer_node_name:$NODE_CONFIGURATION_DIRECTORY/", $management_node_keys)) {
+ notify($ERRORS{'OK'}, 0, "copied $CONFIGURATION_DIRECTORY directory to $computer_node_name:$NODE_CONFIGURATION_DIRECTORY");
+
+ notify($ERRORS{'OK'}, 0, "attempting to set permissions on $computer_node_name:$NODE_CONFIGURATION_DIRECTORY");
+ if (run_ssh_command($computer_node_name, $management_node_keys, "/usr/bin/chmod.exe -R 777 $NODE_CONFIGURATION_DIRECTORY")) {
+ notify($ERRORS{'OK'}, 0, "chmoded -R 777 $computer_node_name:$NODE_CONFIGURATION_DIRECTORY");
}
else {
- notify($ERRORS{'WARNING'}, 0, "could not chmod -R 755 $computer_node_name:$local_configuration_directory");
+ notify($ERRORS{'WARNING'}, 0, "could not chmod -R 777 $computer_node_name:$NODE_CONFIGURATION_DIRECTORY");
}
} ## end if (run_scp_command($CONFIGURATION_DIRECTORY, "$computer_node_name:C:\/Sysprep"...
else {
- notify($ERRORS{'WARNING'}, 0, "failed to copy $CONFIGURATION_DIRECTORY to $computer_node_name");
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, failed to copy $CONFIGURATION_DIRECTORY to $computer_node_name");
return 0;
}
-
-
- # Set root account password
- notify($ERRORS{'OK'}, 0, "changing root password on $computer_short_name");
- my ($root_password_exit_status, $root_password_output) = run_ssh_command($computer_node_name, $management_node_keys, "net user root '$ROOT_PASSWORD'");
- if ($root_password_exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "root password changed to $ROOT_PASSWORD");
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to change root password to $ROOT_PASSWORD, exit status: $root_password_exit_status, output:\n@{$root_password_output}");
+
+ # Disagle autoadminlogon before disabling the pagefile and rebooting
+ # There is no need to automatically logon after the reboot
+ if (!$self->disable_autoadminlogon()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable autoadminlogon");
return 0;
}
-
- # Log off all currently logged in users
- notify($ERRORS{'OK'}, 0, "logging off all currently logged in users");
- logoff_users($computer_node_name);
- # Wait to allow any files in use by users justed logged out to close
- notify($ERRORS{'OK'}, 0, "waiting for 5 seconds after any users were logged off to allow files to close");
- sleep 5;
+ # Make sure sshd service is set to auto
+ if (!_set_sshd_startmode($computer_node_name, "auto")) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to set sshd service startup mode to auto on $computer_node_name");
+ return 0;
+ }
- # Delete the user assigned to this reservation
- notify($ERRORS{'OK'}, 0, "attempting to delete user $user_unityid from $computer_node_name");
- delete_user($computer_node_name, $user_id);
+ # Disable IPv6
+ if (!$self->disable_ipv6()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable IPv6");
+ return 0;
+ }
+ # Call script to clean up the hard drive
+ my $cleanup_command = $NODE_CONFIGURATION_DIRECTORY . '/Scripts/cleanup_hard_drive.cmd > ' . $NODE_CONFIGURATION_DIRECTORY . '/logs/cleanup_hard_drive.log';
+ my ($cleanup_status, $cleanup_output) = run_ssh_command($computer_node_name, $management_node_keys, $cleanup_command);
+ if (defined($cleanup_status) && $cleanup_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully ran cleanup script");
+ }
+ elsif (defined($cleanup_status)) {
+ notify($ERRORS{'OK'}, 0, "capture preparation failed, failed to run cleanup script, exit status: $cleanup_status, output:\n@{$cleanup_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, failed to run cleanup script");
+ return 0;
+ }
- my @sshcmd;
- if ($IPCONFIGURATION eq "static") {
- #so we don't have conflicts we should set the public adapter back to dhcp
- #this change is immediate
- #figure out which adapter it public
- my $myadapter;
- my %ip;
- my ($privateadapter, $publicadapter);
- undef @sshcmd;
- @sshcmd = run_ssh_command($computer_node_name, $management_node_keys, "ipconfig -all", "root");
- # build hash of needed info and set the correct private adapter.
- my $id = 1;
- foreach my $a (@{$sshcmd[1]}) {
- if ($a =~ /Ethernet adapter (.*):/) {
- $myadapter = $1;
- $ip{$myadapter}{"id"} = $id;
- $ip{$myadapter}{"private"} = 0;
- }
- if ($a =~ /IP Address([\s.]*): $computer_private_ip/) {
- $ip{$myadapter}{"private"} = 1;
- }
- if ($a =~ /Physical Address([\s.]*): ([-0-9]*)/) {
- $ip{$myadapter}{"MACaddress"} = $2;
- }
- $id++;
- } ## end foreach my $a (@{$sshcmd[1]})
-
- foreach my $key (keys %ip) {
- if (defined($ip{$key}{private})) {
- if (!($ip{$key}{private})) {
- $publicadapter = "\"$key\"";
- }
- }
- }
-
- undef @sshcmd;
- my $netshcmd = "netsh interface ip set address name=\\\"$publicadapter\\\" source=dhcp";
- @sshcmd = run_ssh_command($computer_node_name, $management_node_keys, $netshcmd, "root");
- foreach my $l (@{$sshcmd[1]}) {
- if ($l =~ /Ok/) {
- notify($ERRORS{'OK'}, 0, "successfully set $publicadapter to dhcp");
- }
- else {
- notify($ERRORS{'OK'}, 0, "problem setting $publicadapter to dhcp on $computer_node_name @{ $sshcmd[1] }");
- }
- }
- } ## end if ($IPCONFIGURATION eq "static")
+## Defragment the hard drive
+#if (!$self->defragment_hard_drive()) {
+# notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to defragment the hard drive");
+# return 0;
+#}
- # Defrag before removing pagefile
- # we do this to speed up the process
- # defraging without a page file takes a little longer
- #DEFRAG: notify($ERRORS{'OK'}, 0, "starting defrag on $computer_node_name");
- #my ($defrag_exit_status, $defrag_output) = run_ssh_command($computer_node_name, $management_node_keys, "defrag.exe C: -v");
- #if (defined($defrag_exit_status)) {
- # notify($ERRORS{'OK'}, 0, "defrag exit status: $defrag_exit_status, defrag output:\n$defrag_output");
- #}
- #else {
- # notify($ERRORS{'WARNING'}, 0, "defrag failed");
- #}
+ # Disable and delete the pagefile
+ # This will set the registry key to disable the pagefile, reboot, then delete pagefile.sys
+ if (!$self->disable_pagefile()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable pagefile");
+ return 0;
+ }
+ # ********* node reboots *********
+ # Run ipconfig /all
+ my ($ipconfig_status, $ipconfig_output) = run_ssh_command($computer_node_name, $management_node_keys, "ipconfig /all");
+ if (defined($ipconfig_status) && $ipconfig_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully ran ipconfig /all");
+ }
+ elsif (defined($ipconfig_status)) {
+ notify($ERRORS{'OK'}, 0, "capture preparation failed, failed to run ipconfig /all, exit status: $ipconfig_status, output:\n@{$ipconfig_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, failed to run ssh command to execute ipconfig /all");
+ return 0;
+ }
- my @list;
- my $l;
- #execute the vbs script to disable the pagefile and reboot
- undef @sshcmd;
- @sshcmd = run_ssh_command($computer_node_name, $management_node_keys, "cscript.exe //Nologo $local_scripts_directory/auto_create_image.vbs");
- foreach $l (@{$sshcmd[1]}) {
- if ($l =~ /createimage reboot/) {
- notify($ERRORS{'OK'}, 0, "auto_create_image.vbs initiated, $computer_node_name rebooting, sleeping 50");
- sleep 50;
- next;
- }
- elsif ($l =~ /failed error/) {
- notify($ERRORS{'WARNING'}, 0, "auto_create_image.vbs failed, @{ $sshcmd[1] }");
- #legacy code for a bug in xcat, now fixed
- # force a reboot, or really a power cycle.
- #crap hate to do this.
- notify($ERRORS{'WARNING'}, 0, "forcing a power cycle");
- if (VCL::Module::Provisioning::xCAT::_rpower($computer_node_name, "cycle")) {
- notify($ERRORS{'WARNING'}, 0, "forced power cycle complete");
- next;
- }
- } ## end elsif ($l =~ /failed error/) [ if ($l =~ /createimage reboot/)
- } ## end foreach $l (@{$sshcmd[1]})
-
-
- #Set up simple ping loop to determine if machine is actually rebooting
- my $online = 1;
- my $pingloop = 0;
- notify($ERRORS{'OK'}, 0, "checking for pingable $computer_node_name");
- while ($online) {
- if (!(_pingnode($computer_node_name))) {
- notify($ERRORS{'OK'}, 0, "Success $computer_node_name is not pingable");
- $online = 0;
+ # so we don't have conflicts we should set the public adapter back to dhcp
+ # this change is immediate
+ # figure out which adapter it public
+ my $myadapter;
+ my ($privateadapter, $publicadapter);
+
+ # build hash of needed info and set the correct private adapter.
+ my $id = 1;
+ my %ip;
+ foreach my $ipconfig_line (@{$ipconfig_output}) {
+ #notify($ERRORS{'DEBUG'}, 0, "ipconfig line: $ipconfig_line");
+ if ($ipconfig_line =~ /Ethernet adapter (.*):/) {
+ $myadapter = $1;
+ $ip{$myadapter}{"id"} = $id;
+ $ip{$myadapter}{"private"} = 0;
+ notify($ERRORS{'DEBUG'}, 0, "adapter found: $myadapter, id: $id");
}
- else {
- notify($ERRORS{'OK'}, 0, "$computer_node_name is still pingable - loop $pingloop");
- sleep 10;
- $pingloop++;
+ if ($ipconfig_line =~ /IP Address([\s.]*): $computer_private_ip/) {
+ $ip{$myadapter}{"private"} = 1;
+ notify($ERRORS{'DEBUG'}, 0, "$myadapter: private");
}
- if ($pingloop > 10) {
- notify($ERRORS{'CRITICAL'}, 0, "$computer_node_name should have rebooted by now, trying to force it");
- if (VCL::Module::Provisioning::xCAT::_rpower($computer_node_name, "boot")) {
- notify($ERRORS{'WARNING'}, 0, "forced power cycle complete");
- sleep 25;
- next;
- }
+ if ($ipconfig_line =~ /Physical Address([\s.]*): ([-0-9]*)/) {
+ $ip{$myadapter}{"MACaddress"} = $2;
+ notify($ERRORS{'DEBUG'}, 0, "$myadapter MAC address: $2");
}
- } ## end while ($online)
-
+ $id++;
+ } ## end foreach my $ipconfig_line (@{$sshcmd[1]})
- # Wait until the reboot process has started to shutdown services
- notify($ERRORS{'OK'}, 0, "$computer_node_name rebooting, waiting");
- my $socketflag = 0;
-
-
- REBOOTED:
- my $rebooted = 1;
- my $reboot_wait_count = 0;
- while ($rebooted) {
- if ($reboot_wait_count > 55) {
- notify($ERRORS{'CRITICAL'}, 0, "waited $reboot_wait_count on reboot after auto_create_image on $computer_node_name");
- return 0;
- }
- notify($ERRORS{'OK'}, 0, "$computer_node_name not completed reboot sleeping for 25");
- sleep 25;
- if (_pingnode($computer_node_name)) {
- #it pingable check if sshd is open
- notify($ERRORS{'OK'}, 0, "$computer_node_name is pingable, checking sshd port");
- my $sshd = _sshd_status($computer_node_name, $image_name);
- if ($sshd =~ /on/) {
- $rebooted = 0;
- notify($ERRORS{'OK'}, 0, "$computer_node_name sshd is open");
+ foreach my $key (keys %ip) {
+ if (defined($ip{$key}{private})) {
+ if (!($ip{$key}{private})) {
+ $publicadapter = $key;
+ notify($ERRORS{'DEBUG'}, 0, "public adapter: $key");
}
- else {
- notify($ERRORS{'OK'}, 0, "$computer_node_name sshd NOT open yet,sleep 5");
- sleep 5;
- }
- } ## end if (_pingnode($computer_node_name))
- $reboot_wait_count++;
- } # Close while rebooted
+ }
+ }
+ # Use netsh to set the public adapter to use DHCP
+ my $set_dhcp_command = '$SYSTEMROOT/System32/netsh.exe interface ip set address name="' . $publicadapter . '" source=dhcp';
+ my ($set_dhcp_status, $set_dhcp_output) = run_ssh_command($computer_node_name, $management_node_keys, $set_dhcp_command);
+ if (defined($set_dhcp_status) && $set_dhcp_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully set public adapter '$publicadapter' to use dhcp");
+ }
+ elsif (defined($set_dhcp_status)) {
+ notify($ERRORS{'OK'}, 0, "capture preparation failed, unable to set public adapter '$publicadapter' to use dhcp, exit status: $set_dhcp_status, output:\n@{$set_dhcp_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to run ssh command to set public adapter '$publicadapter' to use dhcp");
+ return 0;
+ }
- # Check for recent bug
- undef @sshcmd;
- @sshcmd = run_ssh_command($computer_node_name, $IDENTITY_wxp, "uname -s");
- foreach my $l (@{$sshcmd[1]}) {
- if ($l =~ /^Warning:/) {
- #if (makesshgkh($computer_node_name)) {
- #}
- }
- if ($l =~ /^Read from socket failed:/) {
- if ($socketflag) {
- notify($ERRORS{'CRITICAL'}, 0, "could not login $computer_node_name via ssh socket failure");
- return 0;
- }
- notify($ERRORS{'CRITICAL'}, 0, "discovered ssh read from socket failure on $computer_node_name, attempting to repair");
- #power cycle node
- if (VCL::Module::Provisioning::xCAT::_rpower($computer_node_name, "cycle")) {
- notify($ERRORS{'CRITICAL'}, 0, "$computer_node_name power cycled going to reboot check routine");
- sleep 40;
- $socketflag = 1;
- goto REBOOTED;
- }
- } ## end if ($l =~ /^Read from socket failed:/)
- } ## end foreach my $l (@{$sshcmd[1]})
+ # Reenable the pagefile, this will take effect when the saved image boots
+ if (!$self->enable_pagefile()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to reenable pagefile");
+ return 0;
+ }
- notify($ERRORS{'OK'}, 0, "proceeding to CIMONITOR");
- #monitor for signal to set node to image and then reboot
- my $sshd_status;
- my ($loop, $rebootsignal, $reboot_copied) = 0;
- CIMONITOR:
- #check ssh port in case we finish above steps before first reboot completes
- # while ssh port is off sleep few seconds then loop
- # this section is useless for linux images
- my $ping_result = _pingnode($computer_node_name);
- #check our loop
- if ($loop > 200) {
- notify($ERRORS{'CRITICAL'}, 0, "CIMONITOR $computer_node_name taking longer to reboot than expected, check it");
- return 0;
- }
- notify($ERRORS{'OK'}, 0, "CIMONITOR ping check");
- if (!$ping_result) {
- sleep 5;
- notify($ERRORS{'OK'}, 0, "CIMONITOR ping is off waiting for $computer_node_name to complete reboot");
- $loop++;
- goto CIMONITOR;
- }
- # is port 22 open yet
- if (!nmap_port($computer_node_name, 22)) {
- notify($ERRORS{'OK'}, 0, "port 22 not open on $computer_node_name yet, looping");
- $loop++;
- sleep 3;
- goto CIMONITOR;
- }
-
- ## Set sshd service startup to manual
- #if (_set_sshd_startmode($computer_node_name, "manual")) {
- # notify($ERRORS{'OK'}, 0, "successfully set manual mode for sshd start");
- #}
- #else {
- # notify($ERRORS{'CRITICAL'}, 0, "failed to set manual mode for sshd on $computer_node_name");
+ ## Enable autoadminlogon
+ #if (!$self->enable_autoadminlogon()) {
+ # notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to enable autoadminlogon");
# return 0;
#}
+ ## Add a RunOnce registry key to run VCLprepare.cmd when the captured image comes up
+ #if (!$self->add_runonce_registry_value("VCL Prepare", 'C:\\\\VCL\\\\Scripts\\\\VCLprepare.cmd')) {
+ # notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to add runonce registry value to call VCLprepare.cmd");
+ # return 0;
+ #}
- #actually remove the pagefile.sys sometimes movefile.exe does not work
- if (run_ssh_command($computer_node_name, $IDENTITY_wxp, "/usr/bin/rm -fv C:\/pagefile.sys")) {
- notify($ERRORS{'OK'}, 0, "removed pagefile.sys ");
+ # Set sshd service startup mode to manual
+ if (!$self->set_service_startup_mode('sshd', 'manual')) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to set sshd service startup mode to manual");
+ return 0;
}
notify($ERRORS{'OK'}, 0, "returning 1");
@@ -425,114 +445,32 @@
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 0;
+ return;
}
my $request_id = $self->data->get_request_id();
- my $reservation_id = $self->data->get_reservation_id();
- my $image_id = $self->data->get_image_id();
- my $image_os_name = $self->data->get_image_os_name();
- my $management_node_keys = $self->data->get_management_node_keys();
- my $image_os_type = $self->data->get_image_os_type();
- my $image_name = $self->data->get_image_name();
- my $imagemeta_sysprep = $self->data->get_imagemeta_sysprep();
- my $computer_id = $self->data->get_computer_id();
- my $computer_short_name = $self->data->get_computer_short_name();
my $computer_node_name = $self->data->get_computer_node_name();
- my $computer_type = $self->data->get_computer_type();
- my $user_id = $self->data->get_user_id();
- my $user_unityid = $self->data->get_user_login_id();
- my $managementnode_shortname = $self->data->get_management_node_short_name();
- my $computer_private_ip = $self->data->get_computer_private_ip();
-
- notify($ERRORS{'OK'}, 0, "initiating Windows image capture: $image_name on $computer_short_name");
-
- my @sshcmd;
-
- if ($imagemeta_sysprep) {
- notify($ERRORS{'OK'}, 0, "starting sysprep on $computer_node_name");
- if (open(SSH, "/usr/bin/ssh -q -i $IDENTITY_wxp $computer_node_name \"C:\/Sysprep\/sysprep.cmd\" 2>&1 |")) {
- my $notstop = 1;
- my $loop = 0;
- while ($notstop) {
- my $l = <SSH>;
- $loop++;
- #notify($ERRORS{'DEBUG'}, 0, "sysprep.cmd loop count: $loop");
- #notify($ERRORS{'DEBUG'}, 0, "$l");
- if ($l =~ /sysprep/) {
- notify($ERRORS{'OK'}, 0, "sysprep.exe has started, $l");
-
- notify($ERRORS{'DEBUG'}, 0, "attempting to kill management node sysprep.cmd SSH process in 60 seconds");
- sleep 60;
-
- notify($ERRORS{'DEBUG'}, 0, "attempting to kill management node sysprep.cmd SSH process");
- if (_killsysprep($computer_node_name)) {
- notify($ERRORS{'OK'}, 0, "killed sshd process for sysprep command");
- }
-
- notify($ERRORS{'DEBUG'}, 0, "closing SSH filehandle");
- close(SSH);
- notify($ERRORS{'DEBUG'}, 0, "SSH filehandle closed");
-
- $notstop = 0;
- } ## end if ($l =~ /sysprep/)
- elsif ($l =~ /sysprep.cmd: Permission denied/) {
- notify($ERRORS{'CRITICAL'}, 0, "chmod 755 failed to correctly set execute on sysprep.cmd output $l");
- close(SSH);
- return 0;
- }
-
- #avoid infinite loop
- if ($loop > 1000) {
- notify($ERRORS{'DEBUG'}, 0, "sysprep executed in loop control condition, exceeded limit");
-
- notify($ERRORS{'DEBUG'}, 0, "attempting to kill management node sysprep.cmd SSH process in 60 seconds");
- sleep 60;
-
- notify($ERRORS{'DEBUG'}, 0, "attempting to kill management node sysprep.cmd SSH process");
- if (_killsysprep($computer_node_name)) {
- notify($ERRORS{'OK'}, 0, "killed sshd process for sysprep command");
- }
-
- notify($ERRORS{'DEBUG'}, 0, "closing SSH filehandle");
- close(SSH);
- notify($ERRORS{'DEBUG'}, 0, "SSH filehandle closed");
-
- $notstop = 0;
- } ## end if ($loop > 1000)
-
- } ## end while ($notstop)
- } # Close open handle for SSH sysprep.cmd command
- else {
- notify($ERRORS{'CRITICAL'}, 0, "failed to start sysprep on $computer_node_name $!");
- return 0;
- } # Close sysprep.cmd could not be launched
- } # Close if Sysprep
-
+ my $image_name = $self->data->get_image_name();
+
+ notify($ERRORS{'OK'}, 0, "initiating Vista image capture: $image_name on $computer_node_name");
+
+ # Attempt to reboot the computer, don't wait after reboot is initiated
+ if ($self->reboot(0)) {
+ notify($ERRORS{'OK'}, 0, "$computer_node_name was rebooted");
+ }
else {
- #non sysprep option
- #
- #just reboot machine -- future expansion of additional methods newsid, custom scripts, etc.
- notify($ERRORS{'OK'}, 0, "starting custom script VCLprep1.vbs on $computer_node_name");
- if (run_scp_command("$TOOLS/VCLprep1.vbs", "$computer_node_name:VCLprep1.vbs", $IDENTITY_wxp)) {
- undef @sshcmd;
- @sshcmd = run_ssh_command($computer_node_name, $IDENTITY_wxp, "cscript //Nologo VCLprep1.vbs", "root");
- foreach my $s (@{$sshcmd[1]}) {
- chomp($s);
- if ($s =~ /copied VCLprepare/) {
- notify($ERRORS{'OK'}, 0, "$s");
- }
- if ($s =~ /rebooting/) {
- notify($ERRORS{'OK'}, 0, "SUCCESS started image procedure on $computer_node_name");
- last;
- }
- } ## end foreach my $s (@{$sshcmd[1]})
- } # Close SCP VCLPrep1.vbs
- else {
- notify($ERRORS{'CRITICAL'}, 0, "failed to copy $TOOLS/VCLprep1.vbs to $computer_node_name ");
- return 0;
- }
- } # Close if not Sysprep
+ notify($ERRORS{'WARNING'}, 0, "capture start failed, unable to initiate reboot");
+ return 0;
+ }
+
+ # Wait for computer to become unresponsive
+ if ($self->wait_for_shutdown(5)) {
+ notify($ERRORS{'OK'}, 0, "reboot was successful, $computer_node_name is unresponsive");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "capture start failed, reboot was not successful, computer is still responding to ping");
+ return 0;
+ }
notify($ERRORS{'OK'}, 0, "returning 1");
return 1;
@@ -549,25 +487,37 @@
=cut
sub user_exists {
- my ($node, $user) = @_;
- notify($ERRORS{'WARNING'}, 0, "node is not defined") if (!(defined($node)));
- notify($ERRORS{'WARNING'}, 0, "user is not defined") if (!(defined($user)));
-
- my ($net_user_exit_status, $net_user_output) = run_ssh_command($node, $IDENTITY_wxp, "net user $user");
- if ($net_user_exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "user $user exists on $node");
+ 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();
+
+ # Attempt to get the user login id from the arguments
+ # If not specified, use DataStructure value
+ my $user_login_id = shift;
+ if (!defined($user_login_id)) {
+ $user_login_id = $self->data->get_user_login_id();
+ }
+
+ my ($net_user_exit_status, $net_user_output) = run_ssh_command($computer_node_name, $management_node_keys, "net user $user_login_id");
+ if (defined($net_user_exit_status) && $net_user_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "user $user_login_id exists on $computer_node_name");
return 1;
}
elsif ($net_user_exit_status == 2) {
- notify($ERRORS{'OK'}, 0, "user $user does NOT exist on $node");
+ notify($ERRORS{'OK'}, 0, "user $user_login_id does NOT exist on $computer_node_name");
return 0;
}
elsif ($net_user_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to determine if user $user exists on $node, exit status: $net_user_exit_status, output:\n@{$net_user_output}");
+ notify($ERRORS{'WARNING'}, 0, "failed to determine if user $user_login_id exists on $computer_node_name, exit status: $net_user_exit_status, output:\n@{$net_user_output}");
return;
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to determine if user $user exists on $node");
+ notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to determine if user $user_login_id exists on $computer_node_name");
return;
}
}
@@ -584,10 +534,14 @@
sub logoff_users {
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 ($exit_status, $output) = run_ssh_command($computer_node_name, $management_node_keys, "qwinsta.exe");
if ($exit_status > 0) {
notify($ERRORS{'WARNING'}, 0, "failed to run qwinsta.exe on $computer_node_name, exit status: $exit_status, output:\n@{$output}");
@@ -635,6 +589,11 @@
sub delete_user {
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();
@@ -642,7 +601,7 @@
# If no argument was supplied, use the user specified in the DataStructure
my $username = shift;
if (!(defined($username))) {
- $username = $self->data->get_user_logon_id();
+ $username = $self->data->get_user_login_id();
}
notify($ERRORS{'OK'}, 0, "attempting to delete user $username from $computer_node_name");
@@ -653,6 +612,10 @@
if (defined($delete_user_exit_status) && $delete_user_exit_status == 0) {
notify($ERRORS{'OK'}, 0, "deleted user $username from $computer_node_name");
}
+ elsif (defined($delete_user_exit_status) && $delete_user_exit_status == 2) {
+ notify($ERRORS{'OK'}, 0, "user $username was not deleted, user does not exist");
+ return 1;
+ }
elsif (defined($delete_user_exit_status)) {
notify($ERRORS{'WARNING'}, 0, "failed to delete user $username from $computer_node_name, exit status: $delete_user_exit_status, output:\n@{$delete_user_output}");
return 0;
@@ -682,64 +645,54 @@
#/////////////////////////////////////////////////////////////////////////////
-=head2 disable_pagefile
+=head2 set_password
- Parameters :
- Returns :
- Description :
+ Parameters : $username, $password
+ Returns :
+ Description :
=cut
-sub disable_pagefile {
+sub set_password {
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 $disable_pagefile_key = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management";
- my $disable_pagefile_command = "reg.exe add \"$disable_pagefile_key\" /v \"PagingFiles\" /t REG_SZ /d \"\" /f";
- my ($disable_pagefile_exit_status, $disable_pagefile_output) = run_ssh_command($computer_node_name, $management_node_keys, $disable_pagefile_command);
- if ($disable_pagefile_exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "registry key set to disable pagefile");
- }
- elsif ($disable_pagefile_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to set registry key to disable pagefile, exit status: $disable_pagefile_exit_status, output:\n@{$disable_pagefile_output}");
- return;
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to set registry key to disable pagefile");
- return;
- }
-
- # Attempt to reboot the computer in order to delete the pagefile
- if ($self->reboot()) {
- notify($ERRORS{'OK'}, 0, "computer was rebooted after disabling pagefile in the registry");
+ # Attempt to get the username from the arguments
+ my $username = shift;
+ my $password = shift;
+
+ # If no argument was supplied, use the user specified in the DataStructure
+ if (!defined($username) && !defined($password)) {
+ $username = $self->data->get_user_logon_id();
+ $password = $self->data->get_reservation_password();
}
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to reboot computer after disabling pagefile");
- return;
+ elsif (defined($username) && !defined($password)) {
+ notify($ERRORS{'WARNING'}, 0, "password set failed, username $username was passed as an argument but the password was not");
+ return 0;
}
- # Attempt to delete the pagefile
- my $delete_pagefile_command = "attrib.exe -S -H -R C:/pagefile.sys";
- $delete_pagefile_command .= " && /usr/bin/rm.exe -rfv C:/pagefile.sys";
- my ($delete_pagefile_exit_status, $delete_pagefile_output) = run_ssh_command($computer_node_name, $management_node_keys, $delete_pagefile_command);
- if ($delete_pagefile_exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "pagefile.sys was deleted");
+ # Attempt to set the password
+ notify($ERRORS{'OK'}, 0, "setting password of $username to $password on $computer_node_name");
+ my ($set_password_exit_status, $set_password_output) = run_ssh_command($computer_node_name, $management_node_keys, "net user $username '$password'");
+ if ($set_password_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "$username password changed to $password on $computer_node_name");
return 1;
}
- elsif ($delete_pagefile_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to delete pagefile.sys, exit status: $delete_pagefile_exit_status, output:\n@{$delete_pagefile_output}");
- return;
- }
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to delete pagefile.sys");
- return;
+ notify($ERRORS{'WARNING'}, 0, "failed to set password of $username to $password on $computer_node_name, exit status: $set_password_exit_status, output:\n@{$set_password_output}");
+ return 0;
}
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 import_registry_file
+=head2 disable_pagefile
Parameters :
Returns :
@@ -747,8 +700,157 @@
=cut
-sub import_registry_file {
+sub disable_pagefile {
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 $registry_string .= <<"EOF";
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management]
+"PagingFiles"=""
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "successfully set the registry key to disable the pagefile");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set the registry key to disable the pagefile");
+ return 0;
+ }
+
+ # Attempt to reboot the computer in order to delete the pagefile
+ if ($self->reboot()) {
+ notify($ERRORS{'OK'}, 0, "computer was rebooted after disabling pagefile in the registry");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to reboot computer after disabling pagefile");
+ return;
+ }
+
+ # Attempt to delete the pagefile
+ my $delete_pagefile_command = "attrib.exe -S -H -R C:/pagefile.sys";
+ $delete_pagefile_command .= " && /usr/bin/rm.exe -rfv C:/pagefile.sys";
+ my ($delete_pagefile_exit_status, $delete_pagefile_output) = run_ssh_command($computer_node_name, $management_node_keys, $delete_pagefile_command);
+ if (defined($delete_pagefile_exit_status) && $delete_pagefile_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "pagefile.sys was deleted");
+ return 1;
+ }
+ elsif ($delete_pagefile_exit_status) {
+ notify($ERRORS{'WARNING'}, 0, "failed to delete pagefile.sys, exit status: $delete_pagefile_exit_status, output:\n@{$delete_pagefile_output}");
+ return;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to delete pagefile.sys");
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 disable_pagefile
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub enable_pagefile {
+ 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 $registry_string .= <<'EOF';
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management]
+"PagingFiles"="?:\\\\pagefile.sys"
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "successfully set the registry key to enable the pagefile");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set the registry key to enable the pagefile");
+ return 0;
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 disable_ipv6
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub disable_ipv6 {
+ 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 $registry_string .= <<'EOF';
+Windows Registry Editor Version 5.00
+
+; This registry file contains the entries to disable all IPv6 components
+; http://support.microsoft.com/kb/929852
+
+[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters]
+"DisabledComponents"=dword:ffffffff
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "successfully set the registry keys to disable IPv6");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set the registry keys to disable IPv6");
+ return 0;
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 import_registry_file
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub import_registry_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 $management_node_keys = $self->data->get_management_node_keys();
my $computer_node_name = $self->data->get_computer_node_name();
@@ -762,21 +864,40 @@
notify($ERRORS{'DEBUG'}, 0, "registry file contents:\n$registry_file_contents");
$registry_file_contents =~ s/([\"])/\\$1/gs;
- my $import_registry_command = "/usr/bin/echo.exe -E \"$registry_file_contents\" > tmp.reg";
- $import_registry_command .= " && reg.exe IMPORT tmp.reg";
- my ($import_registry_exit_status, $import_registry_output) = run_ssh_command($computer_node_name, $management_node_keys, $import_registry_command);
- if ($import_registry_exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "registry file contents imported");
+ # Specify where on the node the temporary registry file will reside
+ my $temp_registry_file_path = 'C:/Cygwin/tmp/vcl_import.reg';
+
+ # Echo the registry string to a file on the node
+ my $echo_registry_command = "/usr/bin/echo.exe -E \"$registry_file_contents\" > " . $temp_registry_file_path;
+ my ($echo_registry_exit_status, $echo_registry_output) = run_ssh_command($computer_node_name, $management_node_keys, $echo_registry_command, '', '', 1);
+ if (defined($echo_registry_exit_status) && $echo_registry_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "registry file contents echoed to $temp_registry_file_path");
+ }
+ elsif ($echo_registry_exit_status) {
+ notify($ERRORS{'WARNING'}, 0, "failed to echo registry file contents to $temp_registry_file_path, exit status: $echo_registry_exit_status, output:\n@{$echo_registry_output}");
+ return;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to echo registry file contents to $temp_registry_file_path");
+ return;
+ }
+
+ # Run reg.exe IMPORT
+ my $import_registry_command .= '"$SYSTEMROOT/System32/reg.exe" IMPORT ' . $temp_registry_file_path;
+ my ($import_registry_exit_status, $import_registry_output) = run_ssh_command($computer_node_name, $management_node_keys, $import_registry_command, '', '', 1);
+ if (defined($import_registry_exit_status) && $import_registry_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "registry file contents imported from $temp_registry_file_path");
}
elsif ($import_registry_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to import registry file contents, exit status: $import_registry_exit_status, output:\n@{$import_registry_output}");
+ notify($ERRORS{'WARNING'}, 0, "failed to import registry file contents from $temp_registry_file_path, exit status: $import_registry_exit_status, output:\n@{$import_registry_output}");
return;
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to import registry file contents");
+ notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to import registry file contents from $temp_registry_file_path");
return;
}
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
@@ -791,6 +912,11 @@
sub import_registry_string {
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();
@@ -800,29 +926,476 @@
return;
}
- notify($ERRORS{'DEBUG'}, 0, "registry string:\n$registry_string");
+ # Escape special characters with a backslash:
+ # \
+ # "
+ #notify($ERRORS{'DEBUG'}, 0, "registry string:\n$registry_string");
$registry_string =~ s/([\"])/\\$1/gs;
- my $import_registry_command = "/usr/bin/echo.exe -E \"$registry_string\" > tmp.reg";
- $import_registry_command .= " && reg.exe IMPORT tmp.reg";
- my ($import_registry_exit_status, $import_registry_output) = run_ssh_command($computer_node_name, $management_node_keys, $import_registry_command);
- if ($import_registry_exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "registry string contents imported");
+ # Replace regular newlines with Windows newlines
+ $registry_string =~ s/\n/\r\n/gs;
+
+ # Specify where on the node the temporary registry file will reside
+ my $temp_registry_file_path = 'C:/Cygwin/tmp/vcl_import.reg';
+
+ # Echo the registry string to a file on the node
+ my $echo_registry_command = "/usr/bin/echo.exe -E \"$registry_string\" > " . $temp_registry_file_path;
+ my ($echo_registry_exit_status, $echo_registry_output) = run_ssh_command($computer_node_name, $management_node_keys, $echo_registry_command, '', '', 1);
+ if (defined($echo_registry_exit_status) && $echo_registry_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "registry string contents echoed to $temp_registry_file_path");
+ }
+ elsif ($echo_registry_exit_status) {
+ notify($ERRORS{'WARNING'}, 0, "failed to echo registry string contents to $temp_registry_file_path, exit status: $echo_registry_exit_status, output:\n@{$echo_registry_output}");
+ return;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to echo registry string contents to $temp_registry_file_path");
+ return;
+ }
+
+ # Run reg.exe IMPORT
+ my $import_registry_command .= '"$SYSTEMROOT/System32/reg.exe" IMPORT ' . $temp_registry_file_path;
+ my ($import_registry_exit_status, $import_registry_output) = run_ssh_command($computer_node_name, $management_node_keys, $import_registry_command, '', '', 1);
+ if (defined($import_registry_exit_status) && $import_registry_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "registry string contents imported from $temp_registry_file_path");
}
elsif ($import_registry_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to import registry string contents, exit status: $import_registry_exit_status, output:\n@{$import_registry_output}");
+ notify($ERRORS{'WARNING'}, 0, "failed to import registry string contents from $temp_registry_file_path, exit status: $import_registry_exit_status, output:\n@{$import_registry_output}");
+ return;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to import registry string contents from $temp_registry_file_path");
+ return;
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 add_runonce_registry_value
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub add_runonce_registry_value {
+ 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 $command_name = shift;
+ my $command = shift;
+
+ # Escape backslashes, can never have enough...
+ $command =~ s/\\/\\\\/g;
+
+ # Make sure arguments were supplied
+ if (!defined($command_name) && !defined($command)) {
+ notify($ERRORS{'WARNING'}, 0, "runonce registry key not added, arguments were not passed correctly");
+ return 0;
+ }
+
+ my $registry_string .= <<"EOF";
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce]
+"$command_name"="$command"
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "successfully added runonce registry value, name: $command_name, command: $command");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to add runonce registry value, name: $command_name, command: $command");
+ return 0;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 create_startup_scheduled_task
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub create_startup_scheduled_task {
+ 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 $task_name = shift;
+ my $task_command = shift;
+
+ # Escape backslashes, can never have enough...
+ $task_command =~ s/\\/\\\\/g;
+
+ # Replace forward slashes with backslashes
+ $task_command =~ s/\//\\\\/g;
+
+ # Make sure arguments were supplied
+ if (!defined($task_name) && !defined($task_command)) {
+ notify($ERRORS{'WARNING'}, 0, "startup scheduled task not added, arguments were not passed correctly");
+ return;
+ }
+
+ #SCHTASKS /Create [/S system [/U username [/P [password]]]]
+ # [/RU username [/RP password]] /SC schedule [/MO modifier] [/D day]
+ # [/M months] [/I idletime] /TN taskname /TR taskrun [/ST starttime]
+ # [/RI interval] [ {/ET endtime | /DU duration} [/K] [/XML xmlfile] [/V1]]
+ # [/SD startdate] [/ED enddate] [/IT | /NP] [/Z] [/F]
+ #
+ #Description:
+ # Enables an administrator to create scheduled tasks on a local or
+ # remote system.
+ #
+ #Parameter List:
+ # /S system Specifies the remote system to connect to. If omitted
+ # the system parameter defaults to the local system.
+ #
+ # /U username Specifies the user context under which SchTasks.exe
+ # should execute.
+ #
+ # /P [password] Specifies the password for the given user context.
+ # Prompts for input if omitted.
+ #
+ # /RU username Specifies the "run as" user account (user context)
+ # under which the task runs. For the system account,
+ # valid values are "", "NT AUTHORITY\SYSTEM"
+ # or "SYSTEM".
+ # For v2 tasks, "NT AUTHORITY\LOCALSERVICE" and
+ # "NT AUTHORITY\NETWORKSERVICE" are also available as well
+ # as the well known SIDs for all three.
+ #
+ # /RP [password] Specifies the password for the "run as" user.
+ # To prompt for the password, the value must be either
+ # "*" or none. This password is ignored for the
+ # system account. Must be combined with either /RU or
+ # /XML switch.
+ #
+ # /SC schedule Specifies the schedule frequency.
+ # Valid schedule types: MINUTE, HOURLY, DAILY, WEEKLY,
+ # MONTHLY, ONCE, ONSTART, ONLOGON, ONIDLE, ONEVENT.
+ #
+ # /MO modifier Refines the schedule type to allow finer control over
+ # schedule recurrence. Valid values are listed in the
+ # "Modifiers" section below.
+ #
+ # /D days Specifies the day of the week to run the task. Valid
+ # values: MON, TUE, WED, THU, FRI, SAT, SUN and for
+ # MONTHLY schedules 1 - 31 (days of the month).
+ # Wildcard "*" specifies all days.
+ #
+ # /M months Specifies month(s) of the year. Defaults to the first
+ # day of the month. Valid values: JAN, FEB, MAR, APR,
+ # MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC. Wildcard "*"
+ # specifies all months.
+ #
+ # /I idletime Specifies the amount of idle time to wait before
+ # running a scheduled ONIDLE task.
+ # Valid range: 1 - 999 minutes.
+ #
+ # /TN taskname Specifies a name which uniquely
+ # identifies this scheduled task.
+ #
+ # /TR taskrun Specifies the path and file name of the program to be
+ # run at the scheduled time.
+ # Example: C:\windows\system32\calc.exe
+ #
+ # /ST starttime Specifies the start time to run the task. The time
+ # format is HH:mm (24 hour time) for example, 14:30 for
+ # 2:30 PM. Defaults to current time if /ST is not
+ # specified. This option is required with /SC ONCE.
+ #
+ # /RI interval Specifies the repetition interval in minutes. This is
+ # not applicable for schedule types: MINUTE, HOURLY,
+ # ONSTART, ONLOGON, ONIDLE, ONEVENT.
+ # Valid range: 1 - 599940 minutes.
+ # If either /ET or /DU is specified, then it defaults to
+ # 10 minutes.
+ #
+ # /ET endtime Specifies the end time to run the task. The time format
+ # is HH:mm (24 hour time) for example, 14:50 for 2:50 PM.
+ # This is not applicable for schedule types: ONSTART,
+ # ONLOGON, ONIDLE, ONEVENT.
+ #
+ # /DU duration Specifies the duration to run the task. The time
+ # format is HH:mm. This is not applicable with /ET and
+ # for schedule types: ONSTART, ONLOGON, ONIDLE, ONEVENT.
+ # For /V1 tasks, if /RI is specified, duration defaults
+ # to 1 hour.
+ #
+ # /K Terminates the task at the endtime or duration time.
+ # This is not applicable for schedule types: ONSTART,
+ # ONLOGON, ONIDLE, ONEVENT. Either /ET or /DU must be
+ # specified.
+ #
+ # /SD startdate Specifies the first date on which the task runs. The
+ # format is mm/dd/yyyy. Defaults to the current
+ # date. This is not applicable for schedule types: ONCE,
+ # ONSTART, ONLOGON, ONIDLE, ONEVENT.
+ #
+ # /ED enddate Specifies the last date when the task should run. The
+ # format is mm/dd/yyyy. This is not applicable for
+ # schedule types: ONCE, ONSTART, ONLOGON, ONIDLE, ONEVENT.
+ #
+ # /EC ChannelName Specifies the event channel for OnEvent triggers.
+ #
+ # /IT Enables the task to run interactively only if the /RU
+ # user is currently logged on at the time the job runs.
+ # This task runs only if the user is logged in.
+ #
+ # /NP No password is stored. The task runs non-interactively
+ # as the given user. Only local resources are available.
+ #
+ # /Z Marks the task for deletion after its final run.
+ #
+ # /XML xmlfile Creates a task from the task XML specified in a file.
+ # Can be combined with /RU and /RP switches, or with /RP
+ # alone, when task XML already contains the principal.
+ #
+ # /V1 Creates a task visible to pre-Vista platforms.
+ # Not compatible with /XML.
+ #
+ # /F Forcefully creates the task and suppresses warnings if
+ # the specified task already exists.
+ #
+ # /RL level Sets the Run Level for the job. Valid values are
+ # LIMITED and HIGHEST. The default is LIMITED.
+ #
+ # /DELAY delaytime Specifies the wait time to delay the running of the
+ # task after the trigger is fired. The time format is
+ # mmmm:ss. This option is only valid for schedule types
+ # ONSTART, ONLOGON, ONEVENT.
+ #
+ # /? Displays this help message.
+ #
+ #Modifiers: Valid values for the /MO switch per schedule type:
+ # MINUTE: 1 - 1439 minutes.
+ # HOURLY: 1 - 23 hours.
+ # DAILY: 1 - 365 days.
+ # WEEKLY: weeks 1 - 52.
+ # ONCE: No modifiers.
+ # ONSTART: No modifiers.
+ # ONLOGON: No modifiers.
+ # ONIDLE: No modifiers.
+ # MONTHLY: 1 - 12, or
+ # FIRST, SECOND, THIRD, FOURTH, LAST, LASTDAY.
+ #
+ # ONEVENT: XPath event query string.
+
+ # Run schtasks.exe to add the task
+ my $create_task_command = 'schtasks.exe /Create /RU SYSTEM /SC ONSTART /TN "' . $task_name . '" /TR "' . $task_command . '" /F';
+ my ($create_task_exit_status, $create_task_output) = run_ssh_command($computer_node_name, $management_node_keys, $create_task_command);
+ if (defined($create_task_exit_status) && $create_task_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully created scheduled task on $computer_node_name");
+ }
+ elsif (defined($create_task_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to create scheduled task on $computer_node_name, exit status: $create_task_exit_status, output:\n@{$create_task_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command created scheduled task on $computer_node_name");
+ return;
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 enable_autoadminlogon
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub enable_autoadminlogon {
+ 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 $registry_string .= <<"EOF";
+Windows Registry Editor Version 5.00
+
+; This file enables autoadminlogon for the root account
+
+[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon]
+"AutoAdminLogon"="1"
+"DefaultUserName"="root"
+"DefaultPassword"= "$ROOT_PASSWORD"
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "successfully enabled autoadminlogon");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to enable autoadminlogon");
+ return 0;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 disable_autoadminlogon
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub disable_autoadminlogon {
+ 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 $registry_string .= <<EOF;
+Windows Registry Editor Version 5.00
+
+; This file disables autoadminlogon for the root account
+
+[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon]
+"AutoAdminLogon"="0"
+"DefaultUserName"=""
+"DefaultPassword"= ""
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "successfully disabled autoadminlogon");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to disable autoadminlogon");
+ return 0;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 set_network_location
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub set_network_location {
+ 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();
+
+ #Category key: Home/Work=00000000, Public=00000001
+
+ my $registry_string .= <<"EOF";
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Signatures\\FirstNetwork]
+"Category"=dword:00000001
+EOF
+
+ # Import the string into the registry
+ if ($self->import_registry_string($registry_string)) {
+ notify($ERRORS{'OK'}, 0, "successfully set network location");
+ return 1;
+ }
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to import registry string contents");
+ notify($ERRORS{'WARNING'}, 0, "failed to set network location");
+ return 0;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 set_kms_licensing
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+sub set_kms_licensing {
+ 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 $kms_server = shift;
+ my $kms_port = shift;
+
+ # Make sure the KMS server address was passed as an argument
+ if (!defined($kms_server)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to set kms server, server address was not passed correctly as an argument");
+ return 0;
+ }
+
+ # Set the default KMS port if it wasn't specified.
+ $kms_port = 1688 if !$kms_port;
+
+ # Run slmgr.vbs -skms
+ my $kms_command = '$SYSTEMROOT/System32/cscript.exe $SYSTEMROOT/System32/slmgr.vbs -skms ' . "$kms_server:$kms_port";
+ my ($kms_exit_status, $kms_output) = run_ssh_command($computer_node_name, $management_node_keys, $kms_command);
+ if (defined($kms_exit_status) && $kms_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully set kms server to $kms_server:$kms_port on $computer_node_name");
+ }
+ elsif (defined($kms_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to set kms server to $kms_server:$kms_port on $computer_node_name, exit status: $kms_exit_status, output:\n@{$kms_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command to set kms server to $kms_server:$kms_port on $computer_node_name");
+ return;
+ }
+
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 enable_autoadminlogon
+=head2 activate_licensing
Parameters :
Returns :
@@ -830,36 +1403,37 @@
=cut
-sub enable_autoadminlogon {
+sub activate_licensing {
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 $registry_string .= <<"EOF";
-Windows Registry Editor Version 5.00
-
-; This file enables autoadminlogon for the root account
-
-[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon]
-"AutoAdminLogon"="1"
-"DefaultUserName"="root"
-"DefaultPassword"= "$ROOT_PASSWORD"
-EOF
- # Import the string into the registry
- if ($self->import_registry_string($registry_string)) {
- notify($ERRORS{'WARNING'}, 0, "successfully enabled autoadminlogon");
- return 1;
+ # Run slmgr.vbs -ato
+ my $activate_command = '$SYSTEMROOT/System32/cscript.exe $SYSTEMROOT/System32/slmgr.vbs -ato';
+ my ($activate_exit_status, $activate_output) = run_ssh_command($computer_node_name, $management_node_keys, $activate_command);
+ if (defined($activate_exit_status) && $activate_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully activated licensing on $computer_node_name");
}
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to enable autoadminlogon");
+ elsif (defined($activate_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to activated licensing on $computer_node_name, exit status: $activate_exit_status, output:\n@{$activate_output}");
return 0;
}
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to activated licensing on $computer_node_name");
+ return;
+ }
+
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 disable_autoadminlogon
+=head2 create_eventlog_entry
Parameters :
Returns :
@@ -867,38 +1441,47 @@
=cut
-sub disable_autoadminlogon {
+sub create_eventlog_entry {
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 $registry_string .= <<EOF;
-Windows Registry Editor Version 5.00
-
-; This file disables autoadminlogon for the root account
-
-[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon]
-"AutoAdminLogon"="0"
-"DefaultUserName"=""
-"DefaultPassword"= ""
-EOF
- # Import the string into the registry
- if ($self->import_registry_string($registry_string)) {
- notify($ERRORS{'WARNING'}, 0, "successfully disabled autoadminlogon");
- return 1;
+ my $message = shift;
+
+ # Make sure the message was passed as an argument
+ if (!defined($message)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to create eventlog entry, message was passed as an argument");
+ return 0;
}
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to disable autoadminlogon");
+
+ # Run eventcreate.exe to create an event log entry
+ my $eventcreate_command = '$SYSTEMROOT/System32/eventcreate.exe /T INFORMATION /L APPLICATION /SO VCL /ID 555 /D "' . $message . '"';
+ my ($eventcreate_exit_status, $eventcreate_output) = run_ssh_command($computer_node_name, $management_node_keys, $eventcreate_command);
+ if (defined($eventcreate_exit_status) && $eventcreate_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully created event log entry on $computer_node_name: $message");
+ }
+ elsif (defined($eventcreate_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to create event log entry on $computer_node_name: $message, exit status: $eventcreate_exit_status, output:\n@{$eventcreate_output}");
return 0;
}
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to create event log entry on $computer_node_name: $message");
+ return;
+ }
+
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
=head2 reboot
- Parameters :
+ Parameters : $wait_for_reboot
Returns :
Description :
@@ -906,21 +1489,39 @@
sub reboot {
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();
+ # Check if an argument was supplied
+ my $wait_for_reboot = shift;
+ if (!defined($wait_for_reboot) || $wait_for_reboot !~ /0/) {
+ notify($ERRORS{'DEBUG'}, 0, "rebooting $computer_node_name and waiting for ssh to become active");
+ $wait_for_reboot = 1;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "rebooting $computer_node_name and NOT waiting");
+ $wait_for_reboot = 0;
+ }
+
my $reboot_start_time = time();
notify($ERRORS{'DEBUG'}, 0, "reboot will be attempted on $computer_node_name");
- # Make sure sshd service is set to auto
- notify($ERRORS{'DEBUG'}, 0, "attempting to make sure sshd service startup is set to auto");
- if (_set_sshd_startmode($computer_node_name, "auto")) {
- notify($ERRORS{'OK'}, 0, "successfully set sshd service startup mode to auto on $computer_node_name");
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to set sshd service startup mode to auto on $computer_node_name");
+ # Make sure SSH access is enabled from private IP addresses
+ if (!$self->firewall_enable_ssh_private()) {
+ notify($ERRORS{'WARNING'}, 0, "reboot not attempted, failed to enable ssh from private IP addresses");
+ return 0;
}
+ # Make sure ping access is enabled from private IP addresses
+ if (!$self->firewall_enable_ping_private()) {
+ notify($ERRORS{'WARNING'}, 0, "reboot not attempted, failed to enable ping from private IP addresses");
+ return 0;
+ }
# Initiate the shutdown.exe command to reboot the computer
my $shutdown_command = "C:/Windows/system32/shutdown.exe -r -t 0 -f";
@@ -937,6 +1538,12 @@
return;
}
+ # Check if wait for reboot is set
+ if (!$wait_for_reboot) {
+ return 1;
+ }
+
+ # Wait for reboot is true
notify($ERRORS{'OK'}, 0, "sleeping for 30 seconds while $computer_node_name begins reboot");
sleep 30;
@@ -998,6 +1605,11 @@
sub wait_for_ping {
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 $computer_node_name = $self->data->get_computer_node_name();
# Attempt to get the total number of minutes to wait from the command line
@@ -1056,6 +1668,62 @@
#/////////////////////////////////////////////////////////////////////////////
+=head2 wait_for_shutdown
+
+ Parameters : Maximum number of minutes to wait (optional)
+ Returns : 1 if computer is not pingable, 0 otherwise
+ Description : Attempts to ping the computer specified in the DataStructure
+ for the current reservation. It will wait up to a maximum number
+ of minutes for ping to fail.
+
+=cut
+
+sub wait_for_shutdown {
+ 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 $computer_node_name = $self->data->get_computer_node_name();
+
+ # Attempt to get the total number of minutes to wait from the command line
+ my $total_wait_minutes = shift;
+ if (!defined($total_wait_minutes) || $total_wait_minutes !~ /^\d+$/) {
+ $total_wait_minutes = 5;
+ }
+
+ # Looping configuration variables
+ # Seconds to wait in between loop attempts
+ my $attempt_delay = 30;
+ # Total loop attempts made
+ # Add 1 to the number of attempts because if you're waiting for x intervals, you check x+1 times including at 0
+ my $attempts = ($total_wait_minutes * 2) + 1;
+
+ notify($ERRORS{'OK'}, 0, "waiting for $computer_node_name to become unresponsive, maximum of $total_wait_minutes minutes");
+
+ # Loop until computer is offline
+ my $computer_pingable = 0;
+ for (my $attempt = 1; $attempt <= $attempts; $attempt++) {
+ notify($ERRORS{'OK'}, 0, "attempt $attempt/$attempts: checking if computer is pingable: $computer_node_name");
+ $computer_pingable = _pingnode($computer_node_name);
+
+ if (!$computer_pingable) {
+ notify($ERRORS{'OK'}, 0, "$computer_node_name is not pingable, returning 1");
+ return 1;
+ }
+
+ notify($ERRORS{'OK'}, 0, "sleeping for $attempt_delay seconds before next ping attempt");
+ sleep $attempt_delay;
+ }
+
+ # Reached end of wait loop
+ notify($ERRORS{'WARNING'}, 0, "$computer_node_name is still pingable, returning 0");
+ return 0;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 wait_for_ssh
Parameters : Maximum number of minutes to wait (optional)
@@ -1070,6 +1738,11 @@
sub wait_for_ssh {
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();
@@ -1123,6 +1796,10 @@
sub firewall_enable_ping_private {
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 %firewall_parameters = (
name => 'VCL: allow ping from private network',
@@ -1158,9 +1835,13 @@
sub firewall_enable_ssh_private {
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 %firewall_parameters = (
- name => 'VCL: allow ssh port 22 from private network',
+ name => 'VCL: allow SSH port 22 from private network',
dir => 'in',
action => 'allow',
description => 'Allows incoming TCP port 22 traffic from 10.x.x.x addresses',
@@ -1194,6 +1875,10 @@
sub firewall_enable_rdp {
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;
+ }
# Check if the remote IP was passed correctly as an argument
my $remote_ip = shift;
@@ -1235,6 +1920,10 @@
sub firewall_disable_rdp {
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;
+ }
#"\netsh.exe advfirewall firewall delete rule name=RDP protocol=TCP localport=3389"
@@ -1267,6 +1956,11 @@
sub firewall_configure {
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();
@@ -1292,7 +1986,7 @@
# Add quotes around anything with a space in the parameters hash which isn't already enclosed in quotes
foreach my $rule_property (sort keys(%{$firewall_parameters})) {
$firewall_parameters->{$rule_property} =~ s/^(.*\s.*)$/\"$1\"/g;
- notify($ERRORS{'DEBUG'}, 0, "enclosing property in quotes: $firewall_parameters->{$rule_property}");
+ #notify($ERRORS{'DEBUG'}, 0, "enclosing property in quotes: $firewall_parameters->{$rule_property}");
}
# Attempt to run the command to set existing firewall rule
@@ -1419,6 +2113,11 @@
sub firewall_close {
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();
@@ -1432,7 +2131,7 @@
# Add quotes around anything with a space in the parameters hash which isn't already enclosed in quotes
foreach my $rule_property (sort keys(%{$firewall_parameters})) {
$firewall_parameters->{$rule_property} =~ s/^(.*\s.*)$/\"$1\"/g;
- notify($ERRORS{'DEBUG'}, 0, "enclosing '$rule_property' property in quotes: $firewall_parameters->{$rule_property}");
+ #notify($ERRORS{'DEBUG'}, 0, "enclosing '$rule_property' property in quotes: $firewall_parameters->{$rule_property}");
}
# Usage: delete rule name=<string>
@@ -1477,6 +2176,145 @@
#/////////////////////////////////////////////////////////////////////////////
+=head2 set_service_startup_mode
+
+ Parameters :
+ Returns : 1 if succeeded, 0 otherwise
+ Description :
+
+=cut
+
+sub set_service_startup_mode {
+ 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();
+
+ # Make sure firewall parameters hash was passed
+ my $service_name = shift;
+ my $startup_mode = shift;
+
+ # Make sure both arguments were supplied
+ if (!defined($service_name) && !defined($startup_mode)) {
+ notify($ERRORS{'WARNING'}, 0, "set service startup mode failed, service name and startup mode arguments were not passed correctly");
+ return 0;
+ }
+
+ # Make sure the startup mode is valid
+ if ($startup_mode !~ /boot|system|auto|demand|disabled|delayed-auto|manual/i) {
+ notify($ERRORS{'WARNING'}, 0, "set service startup mode failed, invalid startup mode: $startup_mode");
+ return 0;
+ }
+
+ # Set the mode to demand if manual was specified, specific to sc command
+ $startup_mode = "demand" if ($startup_mode eq "manual");
+
+ # Use sc.exe to change the start mode
+ my $service_startup_command = '"$SYSTEMROOT/System32/sc.exe" config ' . "$service_name start= $startup_mode";
+ my ($service_startup_exit_status, $service_startup_output) = run_ssh_command($computer_node_name, $management_node_keys, $service_startup_command);
+ if (defined($service_startup_exit_status) && $service_startup_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "$service_name service startup mode set to $startup_mode");
+ }
+ elsif ($service_startup_exit_status) {
+ notify($ERRORS{'WARNING'}, 0, "failed to set $service_name service startup mode to $startup_mode, exit status: $service_startup_exit_status, output:\n@{$service_startup_output}");
+ return;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set $service_name service startup mode to $startup_mode, exit status: $service_startup_exit_status, output:\n@{$service_startup_output}");
+ return;
+ }
+
+ return 1;
+} ## end sub _set_sshd_startmode
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 defragment_hard_drive
+
+ Parameters :
+ Returns : 1 if succeeded, 0 otherwise
+ Description :
+
+=cut
+
+sub defragment_hard_drive {
+ 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();
+
+ # Defragment the hard drive
+ notify($ERRORS{'OK'}, 0, "beginning to defragment the hard drive on $computer_node_name");
+ my ($defrag_exit_status, $defrag_output) = run_ssh_command($computer_node_name, $management_node_keys, '$SYSTEMROOT/System32/defrag.exe $SYSTEMDRIVE -v');
+ if (defined($defrag_exit_status) && $defrag_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully defragmented the hard drive, exit status: $defrag_exit_status, output:\n@{$defrag_output}");
+ return 1;
+ }
+ elsif (defined($defrag_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to defragment the hard drive, exit status: $defrag_exit_status, output:\n@{$defrag_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run the SSH command to defragment the hard drive");
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 run_newsid
+
+ Parameters :
+ Returns : 1 success 0 failure
+ Description :
+
+=cut
+
+sub run_newsid {
+ 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();
+
+ # Attempt to get the computer name from the arguments
+ # If no argument was supplied, use the name specified in the DataStructure
+ my $computer_name = shift;
+ if (!(defined($computer_name))) {
+ $computer_name = $self->data->get_computer_short_name();
+ }
+
+ # Attempt to delete the user account
+ my $newsid_command = "start /wait $NODE_CONFIGURATION_DIRECTORY/Utilities/newsid.exe /a /n $computer_name";
+ my ($newsid_exit_status, $newsid_output) = run_ssh_command($computer_node_name, $management_node_keys, $newsid_command);
+ if (defined($newsid_exit_status) && $newsid_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully ran newsid.exe on $computer_node_name, new computer name: $computer_name");
+ }
+ elsif (defined($newsid_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to run newsid.exe on $computer_node_name, exit status: $newsid_exit_status, output:\n@{$newsid_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to run newsid.exe on $computer_node_name");
+ return;
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
1;
__END__