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/30 20:26:51 UTC
svn commit: r730217 [2/3] - in /incubator/vcl/trunk/managementnode/lib/VCL:
DataStructure.pm Module/OS/Windows/Desktop/Vista.pm
Module/Provisioning/xCAT.pm new.pm reclaim.pm reserved.pm utils.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=730217&r1=730216&r2=730217&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 Tue Dec 30 11:26:51 2008
@@ -49,6 +49,8 @@
# Specify the version of Perl to use
use 5.008000;
+no warnings 'redefine';
+
use strict;
use warnings;
use diagnostics;
@@ -94,7 +96,7 @@
#/////////////////////////////////////////////////////////////////////////////
-=head2 post_reload
+=head2 post_load
Parameters :
Returns :
@@ -102,7 +104,7 @@
=cut
-sub post_reload {
+sub post_load {
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");
@@ -112,60 +114,93 @@
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");
+
+ # Set KMS licensing
+ if (!$self->set_kms_licensing('kms.unity.ad.ncsu.edu')) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to configure node for KMS licensing");
+ return 0;
+ }
- # Run NewSID
- if (!$self->run_newsid()) {
- notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, unable to run newsid.exe on $computer_node_name");
+ # Activate Microsoft Vista software licensing
+ if (!$self->activate_licensing()) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to activate licensing");
+ return 0;
+ }
+
+ # Disable Vista's defrag scheduled task
+ if (!$self->disable_scheduled_task('\Microsoft\Windows\Defrag\ScheduledDefrag')) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable defrag scheduled task");
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");
+ # Disable system restore scheduled task
+ if (!$self->disable_scheduled_task('\Microsoft\Windows\SystemRestore\SR')) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable system restore scheduled task");
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");
+ # Disable customer improvement program consolidator scheduled task
+ if (!$self->disable_scheduled_task('\Microsoft\Windows\Customer Experience Improvement Program\Consolidator')) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable customer improvement program consolidator scheduled task");
return 0;
}
- # Activate
- if (!$self->activate_licensing()) {
- notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, failed to activate licensing");
+ # Disable customer improvement program opt-in notification scheduled task
+ if (!$self->disable_scheduled_task('\Microsoft\Windows\Customer Experience Improvement Program\OptinNotification')) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable customer improvement program opt-in notification scheduled task");
+ return 0;
+ }
+
+ # Set the computer description to the image pretty name and image name
+ if (!$self->set_computer_description()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to set the computer description");
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;
- #}
+ # Set the "My Computer" description to the image pretty name
+ if (!$self->rename_my_computer()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to rename my computer");
+ 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");
+ # Run NewSID, this initiates a reboot
+ # The run_newsid subroutine monitors the reboot and returns when it has completed
+ if (!$self->run_newsid()) {
+ notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration failed, unable to run newsid.exe on $computer_node_name");
return 0;
}
- # Disable RDP
+ # ********* node reboots *********
+
+ # Disable RDP firewall exceptions from all addresses
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;
}
+
+ # 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;
+ }
- notify($ERRORS{'WARNING'}, 0, "OS post-reload configuration successful, returning 1");
+ notify($ERRORS{'OK'}, 0, "Vista OS post-reload configuration successful, returning 1");
return 1;
}
@@ -235,8 +270,6 @@
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");
@@ -248,12 +281,6 @@
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: $NODE_CONFIGURATION_DIRECTORY");
@@ -287,9 +314,15 @@
notify($ERRORS{'WARNING'}, 0, "capture preparation failed, failed to copy $CONFIGURATION_DIRECTORY to $computer_node_name");
return 0;
}
-
- # Disagle autoadminlogon before disabling the pagefile and rebooting
- # There is no need to automatically logon after the reboot
+
+ # Create startup scheduled task to prepare computer
+ if (!$self->create_startup_scheduled_task('VCL Startup Configuration', $NODE_CONFIGURATION_DIRECTORY . '/Scripts/vcl_startup.cmd >> ' . $NODE_CONFIGURATION_DIRECTORY . '/Logs/vcl_startup.log')) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to create startup scheduled task");
+ return 0;
+ }
+
+ # Disable autoadminlogon before disabling the pagefile and rebooting
+ # There is no longer a need to automatically logon after the reboot
if (!$self->disable_autoadminlogon()) {
notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable autoadminlogon");
return 0;
@@ -307,8 +340,14 @@
return 0;
}
+ # Disable dynamic dns
+ if (!$self->disable_dynamic_dns()) {
+ notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to disable dynamic dns");
+ 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_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");
@@ -322,11 +361,11 @@
return 0;
}
-## Defragment the hard drive
-#if (!$self->defragment_hard_drive()) {
-# notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to defragment the hard drive");
-# return 0;
-#}
+ ## Defragment the hard drive
+ #if (!$self->defragment_hard_drive()) {
+ # notify($ERRORS{'WARNING'}, 0, "capture preparation failed, unable to defragment the hard drive");
+ # return 0;
+ #}
# Disable and delete the pagefile
# This will set the registry key to disable the pagefile, reboot, then delete pagefile.sys
@@ -409,18 +448,6 @@
return 0;
}
- ## 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;
- #}
-
# 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");
@@ -478,52 +505,6 @@
#/////////////////////////////////////////////////////////////////////////////
-=head2 user_exists
-
- Parameters :
- Returns :
- Description :
-
-=cut
-
-sub user_exists {
- 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_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_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_login_id exists on $computer_node_name");
- return;
- }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
=head2 logoff_users
Parameters :
@@ -579,15 +560,15 @@
#/////////////////////////////////////////////////////////////////////////////
-=head2 delete_user
+=head2 add_users
- Parameters : $node, $user, $type, $osname
- Returns : 1 success 0 failure
- Description : removes user account and profile directory from specificed node
+ Parameters :
+ Returns :
+ Description :
=cut
-sub delete_user {
+sub add_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");
@@ -597,63 +578,58 @@
my $management_node_keys = $self->data->get_management_node_keys();
my $computer_node_name = $self->data->get_computer_node_name();
- # Attempt to get the username from the arguments
- # If no argument was supplied, use the user specified in the DataStructure
- my $username = shift;
- if (!(defined($username))) {
- $username = $self->data->get_user_login_id();
- }
-
- notify($ERRORS{'OK'}, 0, "attempting to delete user $username from $computer_node_name");
-
- # Attempt to delete the user account
- my $delete_user_command = "net user $username /DELETE";
- my ($delete_user_exit_status, $delete_user_output) = run_ssh_command($computer_node_name, $management_node_keys, $delete_user_command);
- 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;
+ # Attempt to get the user array from the arguments
+ # If no argument was supplied, use the users specified in the DataStructure
+ my $user_array_ref = shift;
+ my @users;
+ if ($user_array_ref) {
+ $user_array_ref = $self->data->get_imagemeta_usergroupmembers();
+ @users = @{$user_array_ref};
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run ssh command delete user $username from $computer_node_name");
- return;
- }
-
- # Delete the user's home directory
- my $delete_profile_command = "/bin/rm -rf /cygdrive/c/Users/$username";
- my ($delete_profile_exit_status, $delete_profile_output) = run_ssh_command($computer_node_name, $management_node_keys, $delete_profile_command);
- if (defined($delete_profile_exit_status) && $delete_profile_exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "deleted profile for user $username from $computer_node_name");
+ # User list was not specified as an argument
+ # Use the imagemeta group members and the primary reservation user
+ my $user_login_id = $self->data->get_user_login_id();
+ my $user_group_members = $self->data->get_imagemeta_usergroupmembers();
+
+ push @users, $user_login_id;
+
+ foreach my $user_group_member_uid (keys(%{$user_group_members})) {
+ my $user_group_member_login_id = $user_group_members->{$user_group_member_uid};
+ push @users, $user_group_member_login_id;
+ }
}
- elsif (defined($delete_profile_exit_status)) {
- notify($ERRORS{'WARNING'}, 0, "failed to delete profile for user $username from $computer_node_name, exit status: $delete_profile_exit_status, output:\n@{$delete_profile_output}");
- return 0;
+
+ # Attempt to get the password from the arguments
+ # If no argument was supplied, use the password specified in the DataStructure
+ my $password = shift;
+ if (!$password) {
+ $password = $self->data->get_reservation_password();
}
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to run ssh command delete profile for user $username from $computer_node_name");
- return;
+
+ # Loop through the users in the imagemeta group and attempt to add them
+ for my $username (@users) {
+ if (!$self->create_user($username, $password)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to add users to $computer_node_name");
+ return 0;
+ }
}
+ notify($ERRORS{'OK'}, 0, "successfully added " . @users . " users to $computer_node_name");
return 1;
-} ## end sub del_user
+}
#/////////////////////////////////////////////////////////////////////////////
-=head2 set_password
+=head2 delete_users
- Parameters : $username, $password
+ Parameters :
Returns :
Description :
=cut
-sub set_password {
+sub delete_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");
@@ -663,44 +639,51 @@
my $management_node_keys = $self->data->get_management_node_keys();
my $computer_node_name = $self->data->get_computer_node_name();
- # 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();
+ # Attempt to get the user array from the arguments
+ # If no argument was supplied, use the users specified in the DataStructure
+ my $user_array_ref = shift;
+ my @users;
+ if ($user_array_ref) {
+ $user_array_ref = $self->data->get_imagemeta_usergroupmembers();
+ @users = @{$user_array_ref};
}
- 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;
+ else {
+ # User list was not specified as an argument
+ # Use the imagemeta group members and the primary reservation user
+ my $user_login_id = $self->data->get_user_login_id();
+ my $user_group_members = $self->data->get_imagemeta_usergroupmembers();
+
+ push @users, $user_login_id;
+
+ foreach my $user_group_member_uid (keys(%{$user_group_members})) {
+ my $user_group_member_login_id = $user_group_members->{$user_group_member_uid};
+ push @users, $user_group_member_login_id;
+ }
}
- # 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;
- }
- else {
- 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;
+ # Loop through the users and attempt to delete them
+ for my $username (@users) {
+ if (!$self->delete_user($username)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to delete user $username from $computer_node_name");
+ return 0;
+ }
}
+
+ notify($ERRORS{'OK'}, 0, "successfully deleted " . @users . " users from $computer_node_name");
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 disable_pagefile
+=head2 user_exists
- Parameters :
- Returns :
- Description :
+ Parameters :
+ Returns :
+ Description :
=cut
-sub disable_pagefile {
+sub user_exists {
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");
@@ -710,60 +693,47 @@
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 get the username from the arguments
+ # If no argument was supplied, use the user specified in the DataStructure
+ my $username = shift;
+ if (!$username) {
+ $username = $self->data->get_user_login_id();
}
- # 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");
+ notify($ERRORS{'OK'}, 0, "checking if user $username exists on $computer_node_name");
+
+ # Attempt to query the user account
+ my $query_user_command = "net user \"$username\"";
+ my ($query_user_exit_status, $query_user_output) = run_ssh_command($computer_node_name, $management_node_keys, $query_user_command);
+ if (defined($query_user_exit_status) && $query_user_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "user $username exists 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}");
+ elsif (defined($query_user_exit_status) && $query_user_exit_status == 2) {
+ notify($ERRORS{'OK'}, 0, "user $username does not exist on $computer_node_name");
+ return 0;
+ }
+ elsif (defined($query_user_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to determine if user $username exists on $computer_node_name, exit status: $query_user_exit_status, output:\n@{$query_user_output}");
return;
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to delete pagefile.sys");
+ notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to determine if user $username exists on $computer_node_name");
return;
}
-}
+} ## end sub del_user
#/////////////////////////////////////////////////////////////////////////////
-=head2 disable_pagefile
+=head2 create_user
- Parameters :
- Returns :
- Description :
+ Parameters :
+ Returns :
+ Description :
=cut
-sub enable_pagefile {
+sub create_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");
@@ -773,36 +743,78 @@
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");
+ # Attempt to get the username from the arguments
+ # If no argument was supplied, use the user specified in the DataStructure
+ my $username = shift;
+ my $password = shift;
+ if (!$username) {
+ $username = $self->data->get_user_login_id();
+ }
+ if (!$password) {
+ $password = $self->data->get_user_password();
+ }
+
+ # Check if user already exists
+ if ($self->user_exists($username)) {
+ notify($ERRORS{'OK'}, 0, "user $username already exists on $computer_node_name, attempting to delete user");
+
+ # Attempt to delete the user
+ if (!$self->delete_user($username)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to add user $username to $computer_node_name, user already exists and could not be deleted");
+ return 0;
+ }
+ }
+
+ notify($ERRORS{'OK'}, 0, "attempting to add user $username to $computer_node_name");
+
+ # Attempt to add the user account
+ my $add_user_command = "net user \"$username\" \"$password\" /ADD /EXPIRES:NEVER /COMMENT:\"Account created by VCL\"";
+ $add_user_command .= " && net localgroup \"Administrators\" \"$username\" /ADD";
+ $add_user_command .= " && net localgroup \"Remote Desktop Users\" \"$username\" /ADD";
+
+ my ($add_user_exit_status, $add_user_output) = run_ssh_command($computer_node_name, $management_node_keys, $add_user_command);
+ if (defined($add_user_exit_status) && $add_user_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "added user $username from $computer_node_name");
+ }
+ elsif (defined($add_user_exit_status) && $add_user_exit_status == 2) {
+ notify($ERRORS{'OK'}, 0, "user $username was not added, user already exists");
+ return 1;
+ }
+ elsif (defined($add_user_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to add user $username to $computer_node_name, exit status: $add_user_exit_status, output:\n@{$add_user_output}");
return 0;
}
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run ssh command add user $username to $computer_node_name");
+ return;
+ }
+
+ ## Add the user to the Administrators group
+ #if (!$self->add_user_to_group($username, 'Administrators')) {
+ # notify($ERRORS{'WARNING'}, 0, "added user $username but failed to add user to Administrators group");
+ # return 0;
+ #}
+ #
+ ## Add the user to the Remote Desktop Users group
+ #if (!$self->add_user_to_group($username, 'Remote Desktop Users')) {
+ # notify($ERRORS{'WARNING'}, 0, "added user $username but failed to add user to Remote Desktop Users group");
+ # return 0;
+ #}
return 1;
-}
+} ## end sub del_user
#/////////////////////////////////////////////////////////////////////////////
-=head2 disable_ipv6
+=head2 add_user_to_group
- Parameters :
- Returns :
- Description :
+ Parameters :
+ Returns :
+ Description :
=cut
-sub disable_ipv6 {
+sub add_user_to_group {
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");
@@ -812,39 +824,58 @@
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
+ # Attempt to get the username from the arguments
+ # If no argument was supplied, use the user specified in the DataStructure
+ my $username = shift;
+ my $group = shift;
+ if (!$username || !$group) {
+ notify($ERRORS{'WARNING'}, 0, "unable to add user to group, arguments were not passed correctly");
+ return;
+ }
- # 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");
+ # Attempt to add the user to the group using net localgroup
+ my $localgroup_user_command = "net localgroup \"$group\" $username /ADD";
+ my ($localgroup_user_exit_status, $localgroup_user_output) = run_ssh_command($computer_node_name, $management_node_keys, $localgroup_user_command);
+ if (defined($localgroup_user_exit_status) && $localgroup_user_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "added user $username to \"$group\" group on $computer_node_name");
+ }
+ elsif (defined($localgroup_user_exit_status) && $localgroup_user_exit_status == 2) {
+ # Exit status is 2, this could mean the user is already a member or that the group doesn't exist
+ # Check the output to determine what happened
+ if (grep(/error 1378/, @{$localgroup_user_output})) {
+ # System error 1378 has occurred.
+ # The specified account name is already a member of the group.
+ notify($ERRORS{'OK'}, 0, "user $username was not added to $group group, user already a member");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to add user $username to $group group on $computer_node_name, exit status: $localgroup_user_exit_status, output:\n@{$localgroup_user_output}");
+ return 0;
+ }
}
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to set the registry keys to disable IPv6");
+ elsif (defined($localgroup_user_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to add user $username to $group group on $computer_node_name, exit status: $localgroup_user_exit_status, output:\n@{$localgroup_user_output}");
return 0;
}
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to add user $username to $group group on $computer_node_name");
+ return;
+ }
return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 import_registry_file
+=head2 delete_user
- Parameters :
- Returns :
- Description :
+ Parameters : $node, $user, $type, $osname
+ Returns : 1 success 0 failure
+ Description : removes user account and profile directory from specificed node
=cut
-sub import_registry_file {
+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");
@@ -854,63 +885,56 @@
my $management_node_keys = $self->data->get_management_node_keys();
my $computer_node_name = $self->data->get_computer_node_name();
- my $registry_file_path = shift;
- if (!defined($registry_file_path) || !$registry_file_path) {
- notify($ERRORS{'WARNING'}, 0, "registry file path was not passed correctly as an argument");
- return;
+ # Attempt to get the username from the arguments
+ # If no argument was supplied, use the user specified in the DataStructure
+ my $username = shift;
+ if (!(defined($username))) {
+ $username = $self->data->get_user_login_id();
}
- my $registry_file_contents = `cat $registry_file_path`;
- notify($ERRORS{'DEBUG'}, 0, "registry file contents:\n$registry_file_contents");
- $registry_file_contents =~ s/([\"])/\\$1/gs;
-
- # Specify where on the node the temporary registry file will reside
- my $temp_registry_file_path = 'C:/Cygwin/tmp/vcl_import.reg';
+ notify($ERRORS{'OK'}, 0, "attempting to delete user $username from $computer_node_name");
- # 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");
+ # Attempt to delete the user account
+ my $delete_user_command = "net user $username /DELETE";
+ my ($delete_user_exit_status, $delete_user_output) = run_ssh_command($computer_node_name, $management_node_keys, $delete_user_command);
+ if (defined($delete_user_exit_status) && $delete_user_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "deleted user $username from $computer_node_name");
}
- 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;
+ elsif (defined($delete_user_exit_status) && $delete_user_exit_status == 2) {
+ notify($ERRORS{'OK'}, 0, "user $username was not deleted, user does not exist");
+ }
+ 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;
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to echo registry file contents to $temp_registry_file_path");
+ notify($ERRORS{'WARNING'}, 0, "failed to run ssh command delete user $username from $computer_node_name");
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 from $temp_registry_file_path, exit status: $import_registry_exit_status, output:\n@{$import_registry_output}");
- return;
+
+ # Delete the user's home directory
+ if ($self->delete_directory("C:/Users/$username")) {
+ notify($ERRORS{'OK'}, 0, "deleted profile for user $username from $computer_node_name");
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to import registry file contents from $temp_registry_file_path");
- return;
+ notify($ERRORS{'WARNING'}, 0, "failed to delete profile for user $username from $computer_node_name");
+ return 0;
}
return 1;
-}
+} ## end sub del_user
#/////////////////////////////////////////////////////////////////////////////
-=head2 import_registry_string
+=head2 set_password
- Parameters :
- Returns :
- Description :
+ Parameters : $username, $password
+ Returns :
+ Description :
=cut
-sub import_registry_string {
+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");
@@ -920,52 +944,41 @@
my $management_node_keys = $self->data->get_management_node_keys();
my $computer_node_name = $self->data->get_computer_node_name();
- my $registry_string = shift;
- if (!defined($registry_string) || !$registry_string) {
- notify($ERRORS{'WARNING'}, 0, "registry file path was not passed correctly as an argument");
- return;
- }
-
- # Escape special characters with a backslash:
- # \
- # "
- #notify($ERRORS{'DEBUG'}, 0, "registry string:\n$registry_string");
- $registry_string =~ s/([\"])/\\$1/gs;
-
- # 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';
+ # Attempt to get the username from the arguments
+ my $username = shift;
+ my $password = shift;
- # 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;
+ # 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 run SSH command to echo registry string contents to $temp_registry_file_path");
- 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;
}
- # 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 from $temp_registry_file_path, exit status: $import_registry_exit_status, output:\n@{$import_registry_output}");
- return;
+ # 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");
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to import registry string contents from $temp_registry_file_path");
- 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;
+ }
+
+ # Check if root user, must set sshd service password too
+ if ($username eq 'root') {
+ notify($ERRORS{'OK'}, 0, "root account password changed, must also change sshd service credentials");
+ if ($self->set_service_credentials('sshd', $username, $password)) {
+ notify($ERRORS{'OK'}, 0, "sshd service credentials changed to $username ($password)");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set sshd service credentials to $username ($password)");
+ return 0;
+ }
}
return 1;
@@ -973,7 +986,7 @@
#/////////////////////////////////////////////////////////////////////////////
-=head2 add_runonce_registry_value
+=head2 disable_pagefile
Parameters :
Returns :
@@ -981,7 +994,7 @@
=cut
-sub add_runonce_registry_value {
+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");
@@ -991,39 +1004,52 @@
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"
+[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 added runonce registry value, name: $command_name, command: $command");
- return 1;
+ notify($ERRORS{'OK'}, 0, "successfully set the registry key to disable the pagefile");
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to add runonce registry value, name: $command_name, command: $command");
+ 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 create_startup_scheduled_task
+=head2 disable_pagefile
Parameters :
Returns :
@@ -1031,7 +1057,7 @@
=cut
-sub create_startup_scheduled_task {
+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");
@@ -1041,229 +1067,28 @@
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";
+ 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"
+[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 enabled autoadminlogon");
- return 1;
+ notify($ERRORS{'OK'}, 0, "successfully set the registry key to enable the pagefile");
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to enable autoadminlogon");
+ notify($ERRORS{'WARNING'}, 0, "failed to set the registry key to enable the pagefile");
return 0;
}
+
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 disable_autoadminlogon
+=head2 disable_ipv6
Parameters :
Returns :
@@ -1271,7 +1096,7 @@
=cut
-sub disable_autoadminlogon {
+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");
@@ -1280,40 +1105,40 @@
my $management_node_keys = $self->data->get_management_node_keys();
my $computer_node_name = $self->data->get_computer_node_name();
-
- my $registry_string .= <<EOF;
+
+ my $registry_string .= <<'EOF';
Windows Registry Editor Version 5.00
-; This file disables autoadminlogon for the root account
+; This registry file contains the entries to disable all IPv6 components
+; http://support.microsoft.com/kb/929852
-[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon]
-"AutoAdminLogon"="0"
-"DefaultUserName"=""
-"DefaultPassword"= ""
+[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 disabled autoadminlogon");
- return 1;
+ notify($ERRORS{'OK'}, 0, "successfully set the registry keys to disable IPv6");
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to disable autoadminlogon");
+ notify($ERRORS{'WARNING'}, 0, "failed to set the registry keys to disable IPv6");
return 0;
}
+
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 set_network_location
+=head2 import_registry_file
Parameters :
Returns :
- Description :
+ Description :
=cut
-sub set_network_location {
+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");
@@ -1323,29 +1148,55 @@
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_file_path = shift;
+ if (!defined($registry_file_path) || !$registry_file_path) {
+ notify($ERRORS{'WARNING'}, 0, "registry file path was not passed correctly as an argument");
+ return;
+ }
- 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
+ my $registry_file_contents = `cat $registry_file_path`;
+ notify($ERRORS{'DEBUG'}, 0, "registry file contents:\n$registry_file_contents");
+ $registry_file_contents =~ s/([\"])/\\$1/gs;
- # Import the string into the registry
- if ($self->import_registry_string($registry_string)) {
- notify($ERRORS{'OK'}, 0, "successfully set network location");
- return 1;
+ # 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 set network location");
- return 0;
+ 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 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 from $temp_registry_file_path");
+ return;
}
+
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 set_kms_licensing
+=head2 import_registry_string
Parameters :
Returns :
@@ -1353,7 +1204,7 @@
=cut
-sub set_kms_licensing {
+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");
@@ -1363,77 +1214,60 @@
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;
+ my $registry_string = shift;
+ if (!defined($registry_string) || !$registry_string) {
+ notify($ERRORS{'WARNING'}, 0, "registry file path was not passed correctly as an argument");
+ return;
}
- # Set the default KMS port if it wasn't specified.
- $kms_port = 1688 if !$kms_port;
+ # Escape special characters with a backslash:
+ # \
+ # "
+ #notify($ERRORS{'DEBUG'}, 0, "registry string:\n$registry_string");
+ $registry_string =~ s/([\"])/\\$1/gs;
- # 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;
+ # 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");
}
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command to set kms server to $kms_server:$kms_port on $computer_node_name");
+ 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;
}
-
- return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 activate_licensing
-
- Parameters :
- Returns :
- Description :
-
-=cut
-
-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");
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to echo registry string contents to $temp_registry_file_path");
return;
}
- my $management_node_keys = $self->data->get_management_node_keys();
- my $computer_node_name = $self->data->get_computer_node_name();
-
- # 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");
+ # 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 (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;
+ elsif ($import_registry_exit_status) {
+ 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 activated licensing on $computer_node_name");
+ notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to import registry string contents from $temp_registry_file_path");
return;
}
-
+
return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 create_eventlog_entry
+=head2 add_runonce_registry_value
Parameters :
Returns :
@@ -1441,7 +1275,7 @@
=cut
-sub create_eventlog_entry {
+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");
@@ -1451,43 +1285,47 @@
my $management_node_keys = $self->data->get_management_node_keys();
my $computer_node_name = $self->data->get_computer_node_name();
- my $message = shift;
+ my $command_name = shift;
+ my $command = 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");
+ # 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
- # 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;
+ # 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 run ssh command to create event log entry on $computer_node_name: $message");
- return;
+ notify($ERRORS{'WARNING'}, 0, "failed to add runonce registry value, name: $command_name, command: $command");
+ return 0;
}
-
- return 1;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 reboot
+=head2 create_startup_scheduled_task
- Parameters : $wait_for_reboot
- Returns :
- Description :
+ Parameters :
+ Returns :
+ Description :
=cut
-sub reboot {
+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");
@@ -1497,246 +1335,1207 @@
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");
+ my $task_name = shift;
+ my $task_command = shift;
- # 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;
- }
+ # Escape backslashes, can never have enough...
+ $task_command =~ s/\\/\\\\/g;
- # 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;
- }
+ # Replace forward slashes with backslashes
+ $task_command =~ s/\//\\\\/g;
- # Initiate the shutdown.exe command to reboot the computer
- my $shutdown_command = "C:/Windows/system32/shutdown.exe -r -t 0 -f";
- my ($shutdown_exit_status, $shutdown_output) = run_ssh_command($computer_node_name, $management_node_keys, $shutdown_command);
- if (defined($shutdown_exit_status) && $shutdown_exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "successfully executed reboot command on $computer_node_name");
- }
- elsif (defined($shutdown_exit_status)) {
- notify($ERRORS{'WARNING'}, 0, "failed to execute reboot command on $computer_node_name, exit status: $shutdown_exit_status, output:\n@{$shutdown_output}");
- return 0;
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command to reboot $computer_node_name");
+ # 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;
}
- # 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;
-
- # Wait maximum of 4 minutes for the computer to go offline then come back up
- if (!$self->wait_for_ping(4)) {
- # Check if the computer was ever offline, it should have been or else reboot never happened
- notify($ERRORS{'WARNING'}, 0, "$computer_node_name never responded to ping, attempting hard power reset");
-
- # Just explicitly call xCAT's _rpower for now
- # TODO: implement public reset() subroutines in all of the provisioning modules
- # TODO: allow provisioning and OS modules access to each other's subroutines
- if (VCL::Module::Provisioning::xCAT::_rpower($computer_node_name, "cycle")) {
- notify($ERRORS{'OK'}, 0, "initiated hard power reset on $computer_node_name");
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "reboot failed, failed to initiate hard power reset on $computer_node_name");
- return 0;
- }
-
- # Wait for computer to respond to ping after initiating hard reset
- # Wait longer than the first attempt
- if (!$self->wait_for_ping(6)) {
+ #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 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 activate_licensing
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+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();
+
+ # 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");
+ }
+ 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 create_eventlog_entry
+
+ Parameters :
+ Returns :
+ Description :
+
+=cut
+
+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 $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;
+ }
+
+ # 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 : $wait_for_reboot
+ Returns :
+ Description :
+
+=cut
+
+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 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";
+ my ($shutdown_exit_status, $shutdown_output) = run_ssh_command($computer_node_name, $management_node_keys, $shutdown_command);
+ if (defined($shutdown_exit_status) && $shutdown_exit_status == 0) {
+ notify($ERRORS{'OK'}, 0, "successfully executed reboot command on $computer_node_name");
+ }
+ elsif (defined($shutdown_exit_status)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute reboot command on $computer_node_name, exit status: $shutdown_exit_status, output:\n@{$shutdown_output}");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command to reboot $computer_node_name");
+ return;
+ }
+
+ # 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;
+
+ # Wait maximum of 4 minutes for the computer to go offline then come back up
+ if (!$self->wait_for_ping(4)) {
+ # Check if the computer was ever offline, it should have been or else reboot never happened
+ notify($ERRORS{'WARNING'}, 0, "$computer_node_name never responded to ping, attempting hard power reset");
+
+ # Just explicitly call xCAT's _rpower for now
+ # TODO: implement public reset() subroutines in all of the provisioning modules
+ # TODO: allow provisioning and OS modules access to each other's subroutines
+ if (VCL::Module::Provisioning::xCAT::_rpower($computer_node_name, "cycle")) {
+ notify($ERRORS{'OK'}, 0, "initiated hard power reset on $computer_node_name");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "reboot failed, failed to initiate hard power reset on $computer_node_name");
+ return 0;
+ }
+
+ # Wait for computer to respond to ping after initiating hard reset
+ # Wait longer than the first attempt
+ if (!$self->wait_for_ping(6)) {
# Check if the computer was ever offline, it should have been or else reboot never happened
notify($ERRORS{'WARNING'}, 0, "reboot failed, $computer_node_name never responded to ping even after hard power reset");
return 0;
}
}
[... 1877 lines stripped ...]