Author: arkurth
Date: Fri Jan 15 17:41:26 2010
New Revision: 899730

URL: http://svn.apache.org/viewvc?rev=899730&view=rev
Log:
VCL-145
Removed old run_sysprep and prepare_drivers subroutines from Windows.pm. These 
have been replaced by subroutines in Version_5.pm.

Updated Version_6.pm to utilize the product key and KMS server information now 
stored in the winProductKey and winKMS tables.

The subroutines in Version_6.pm which call slmgr.vbs were not working for 
64-bit OS's. This has been fixed.

Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=899730&r1=899729&r2=899730&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Fri Jan 15 
17:41:26 2010
@@ -5990,231 +5990,6 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 run_sysprep
-
- Parameters  : None
- Returns     : 1 if successful, 0 otherwise
- Description : -Calls subroutine to prepare the hardware drivers
-               -Copies Sysprep files to C:\Sysprep
-                                       -Clears out the setupapi.log file
-                                       -Calls Sysprep.exe with the options to 
seal and shutdown the computer
-                                       -Waits for computer to become 
unresponsive
-                                       -Waits 3 additional minutes
-                                       -Calls provisioning module's 
power_off() subroutine to make sure the computer is powered off
-
-=cut
-
-sub run_sysprep {
-       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();
-
-       # Remove old C:\Sysprep directory if it exists
-       notify($ERRORS{'DEBUG'}, 0, "attempting to remove old C:/Sysprep 
directory if it exists");
-       if (!$self->delete_file('C:/Sysprep')) {
-               notify($ERRORS{'WARNING'}, 0, "unable to remove existing 
C:/Sysprep directory");
-               return 0;
-       }
-
-       # Fix the path, xcopy.exe requires backslashes
-       (my $node_configuration_directory = $NODE_CONFIGURATION_DIRECTORY) =~ 
s/\//\\/g;
-
-       # Copy Sysprep files to C:\Sysprep
-       my $xcopy_command = "xcopy.exe /E /C /I /Q /H /K /O /Y 
\"$node_configuration_directory\\Utilities\\Sysprep\" \"C:\\Sysprep\"";
-       my ($xcopy_status, $xcopy_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $xcopy_command);
-       if (defined($xcopy_status) && $xcopy_status == 0) {
-               notify($ERRORS{'OK'}, 0, "copied Sysprep files to C:/Sysprep");
-       }
-       elsif (defined($xcopy_status)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to copy Sysprep files to 
C:/Sysprep, exit status: $xcopy_status, output:\...@{$xcopy_output}");
-               return 0;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to 
copy Sysprep files to C:/Sysprep");
-               return 0;
-       }
-       
-       # Copy and scan drivers
-       notify($ERRORS{'DEBUG'}, 0, "attempting to copy and scan drivers");
-       if (!$self->prepare_drivers()) {
-               notify($ERRORS{'WARNING'}, 0, "unable to copy and scan 
drivers");
-               return 0;
-       }
-       
-       # Configure the firewall to allow the sessmgr.exe program
-       # Sysprep may hang with a dialog box asking to allow this program
-       if (!$self->firewall_enable_sessmgr()) {
-               notify($ERRORS{'WARNING'}, 0, "unable to configure firewall to 
allow sessmgr.exe program, Sysprep may hang");
-               return 0;
-       }
-
-       # Clear out setupapi.log
-       my $setupapi_command = "/bin/cat C:/Windows/setupapi.log >> 
C:/Windows/setupapi_save.log && /bin/cp /dev/null C:/Windows/setupapi.log";
-       my ($setupapi_status, $setupapi_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $setupapi_command);
-       if (defined($setupapi_status) && $setupapi_status == 0) {
-               notify($ERRORS{'OK'}, 0, "cleared out setupapi.log");
-       }
-       elsif (defined($setupapi_status)) {
-               notify($ERRORS{'OK'}, 0, "failed to clear out setupapi.log, 
exit status: $setupapi_status, output:\...@{$setupapi_output}");
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to 
clear out setupapi.log");
-               return 0;
-       }
-       
-       # Run Sysprep.exe, use cygstart to lauch the .exe and return immediately
-       my $sysprep_command = '/bin/cygstart.exe cmd.exe /c 
"C:/Sysprep/sysprep.exe /forceshutdown /quiet /reseal /mini"';
-       my ($sysprep_status, $sysprep_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $sysprep_command);
-       if (defined($sysprep_status) && $sysprep_status == 0) {
-               notify($ERRORS{'OK'}, 0, "initiated Sysprep.exe, waiting for 
$computer_node_name to become unresponsive");
-       }
-       elsif (defined($sysprep_status)) {
-               notify($ERRORS{'OK'}, 0, "failed to initiate Sysprep.exe, exit 
status: $sysprep_status, output:\...@{$sysprep_output}");
-               return 0;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to 
initiate Sysprep.exe");
-               return 0;
-       }
-
-       # Wait maximum of 5 minutes for the computer to become unresponsive
-       if (!$self->wait_for_no_ping(5)) {
-               # Computer never stopped responding to ping
-               notify($ERRORS{'WARNING'}, 0, "$computer_node_name never became 
unresponsive to ping");
-               return 0;
-       }
-
-       # Wait for 3 minutes then call provisioning module's power_off() 
subroutine
-       # Sysprep does not always shut down the computer when it is done
-       notify($ERRORS{'OK'}, 0, "sleeping for 3 minutes to allow Sysprep.exe 
to finish");
-       sleep 180;
-
-       # Call power_off() to make sure computer is shut down
-       if (!$self->provisioner->power_off()) {
-               # Computer could not be shut off
-               notify($ERRORS{'WARNING'}, 0, "unable to power off 
$computer_node_name");
-               return 0;
-       }
-
-       return 1;
-} ## end sub run_sysprep
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 prepare_drivers
-
- Parameters  : 
- Returns     :
- Description : 
-
-=cut
-
-sub prepare_drivers {
-       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 $imagemeta_sysprep = $self->data->get_imagemeta_sysprep();
-       
-       my $driver_directory;
-       if ($imagemeta_sysprep) {
-               $driver_directory = 'C:/Sysprep/Drivers';
-       }
-       else {
-               $driver_directory = 'C:/Drivers';
-       }
-       
-
-       # Remove old driver directories if they exists
-       notify($ERRORS{'DEBUG'}, 0, "attempting to remove old 
C:/Sysprep\\Drivers directory if it exists");
-       if (!$self->delete_file("C:/Sysprep/Drivers")) {
-               notify($ERRORS{'WARNING'}, 0, "unable to remove existing 
C:/Sysprep/Drivers directory");
-       }
-       notify($ERRORS{'DEBUG'}, 0, "attempting to remove old C:/Drivers 
directory if it exists");
-       if (!$self->delete_file("C:/Drivers")) {
-               notify($ERRORS{'WARNING'}, 0, "unable to remove existing 
C:/Drivers directory");
-       }
-       
-       # Copy driver files to C:/Drivers
-       my $cp_command = "mkdir -p \"$driver_directory\" && cp -rf -T 
\"$NODE_CONFIGURATION_DIRECTORY/Drivers\" \"$driver_directory\"";
-       my ($cp_status, $cp_output) = run_ssh_command($computer_node_name, 
$management_node_keys, $cp_command);
-       if (defined($cp_status) && $cp_status == 0) {
-               notify($ERRORS{'DEBUG'}, 0, "copied driver files to 
$driver_directory");
-       }
-       elsif (defined($cp_status)) {
-               notify($ERRORS{'OK'}, 0, "failed to copy driver files to 
$driver_directory, exit status: $cp_status, output:\...@{$cp_output}");
-               return 0;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to 
drivers files to $driver_directory");
-               return 0;
-       }
-       
-       # Delete existing DevicePath key
-       my $reg_del_command = $self->get_system32_path() . '/reg.exe DELETE 
"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion" /v DevicePath /f';
-       my ($reg_del_status, $reg_del_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $reg_del_command);
-       if (defined($reg_del_status) && $reg_del_status == 0) {
-               notify($ERRORS{'DEBUG'}, 0, "deleted existing DevicePath key");
-       }
-       elsif (defined($reg_del_status)) {
-               notify($ERRORS{'OK'}, 0, "failed to delete existing DevicePath 
key, exit status: $reg_del_status, output:\...@{$reg_del_output}");
-               return 0;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to 
delete existing DevicePath key");
-               return 0;
-       }
-
-       # Run spdrvscn.exe
-       my $spdrvscn_command = 
"$NODE_CONFIGURATION_DIRECTORY/Utilities/SPDrvScn/spdrvscn.exe /p 
\"$driver_directory\" /e inf /d \$SYSTEMROOT\\\\inf /a /s /q";
-       my ($spdrvscn_status, $spdrvscn_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $spdrvscn_command);
-       if (defined($spdrvscn_status) && $spdrvscn_status == 0) {
-               notify($ERRORS{'OK'}, 0, "executed spdrvscn.exe");
-       }
-       elsif (defined($spdrvscn_status)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to execute spdrvscn.exe, 
exit status: $spdrvscn_status, output:\...@{$spdrvscn_output}");
-               return 0;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to 
execute spdrvscn.exe");
-               return 0;
-       }
-       
-       # Query the DevicePath registry value in order to save it in the log 
for troubleshooting
-       my $reg_query_command = $self->get_system32_path() . '/reg.exe QUERY 
"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion" /v DevicePath';
-       my ($reg_query_status, $reg_query_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $reg_query_command, 
'', '', 1);
-       if (defined($reg_query_status) && $reg_query_status == 0) {
-               notify($ERRORS{'DEBUG'}, 0, "queried DevicePath registry 
key:\n" . join("\n", @{$reg_query_output}));
-       }
-       elsif (defined($reg_query_status)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to query DevicePath 
registry key, exit status: $reg_query_status, output:\...@{$reg_query_output}");
-               return 0;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to 
query DevicePath registry key");
-               return 0;
-       }
-       
-       # Format the string for the log output
-       my ($device_path_string) = grep(/devicepath\s+(reg_.*sz)/i, 
@{$reg_query_output});
-       $device_path_string =~ s/.*(devicepath\s+reg_.*sz)\s*/$1\n/i;
-       $device_path_string =~ s/;/\n/g;
-       notify($ERRORS{'OK'}, 0, "device path string: $device_path_string");
-       
-       return 1;
-} ## end sub prepare_drivers
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 clean_hard_drive
 
  Parameters  : 
@@ -7743,7 +7518,7 @@
        # Get the PROCESSOR_IDENTIFIER environment variable to determine if OS 
is 32 or 64-bit
        my ($set_exit_status, $set_output) = 
run_ssh_command($computer_node_name, $management_node_keys, 'set', '', '', 1);
        if (defined($set_exit_status) && $set_exit_status == 0) {
-               notify($ERRORS{'OK'}, 0, "executed set command to determine 
architecture on $computer_node_name");
+               notify($ERRORS{'DEBUG'}, 0, "executed set command to determine 
architecture on $computer_node_name");
        }
        elsif (defined($set_exit_status)) {
                notify($ERRORS{'WARNING'}, 0, "failed to execute set command to 
determine architecture on $computer_node_name, exit status: $set_exit_status, 
output:\...@{$set_output}");
@@ -7820,6 +7595,14 @@
  Description : Retrieves the Windows product name from the registry. This is
                stored at:
                HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProductName
+               
+               The product name stored in the registry is used in the
+               winProductKey table to match a product key up with a product. It
+               must match exactly. Known strings for some versions of Windows:
+               "Microsoft Windows XP"
+               "Microsoft Windows Server 2003"
+               "Windows Server (R) 2008 Datacenter"
+               "Windows Vista (TM) Enterprise"
 
 =cut
 
@@ -8150,14 +7933,9 @@
                return;
        }
        
-       # Get the product name, could be:
-       # "Microsoft Windows XP"
-       # "Microsoft Windows Server 2003"
+       # Get the product name from the registry on the computer
        my $product_name = shift || $self->get_product_name();
-       if ($product_name) {
-               notify($ERRORS{'DEBUG'}, 0, "product name: $product_name");
-       }
-       else {
+       if (!$product_name) {
                notify($ERRORS{'WARNING'}, 0, "product name argument was not 
passed and could not be determined from computer");
                return;
        }

Modified: 
incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm?rev=899730&r1=899729&r2=899730&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm 
(original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm 
Fri Jan 15 17:41:26 2010
@@ -249,10 +249,11 @@
  Parameters  : None
  Returns     : If successful: true
                If failed: false
- Description : Runs cscript.exe slmgr.vbs -skms to set the KMS server address
-               stored on the computer.
-               Runs cscript.exe slmgr.vbs -ato to activate licensing on the
-               computer.
+ Description : Activates Microsoft Windows. A first attempt is made using a
+               MAK key if one has been configured in the winProductKey table
+               for the version of Windows installed on the computer. If unable
+               to activate using a MAK key, activation is attempting using a
+               KMS server configured in the winKMS table.
 
 =cut
 
@@ -263,136 +264,180 @@
                return;
        }
        
-       my $management_node_keys     = $self->data->get_management_node_keys();
-       my $computer_node_name       = $self->data->get_computer_node_name();
-       my $product_name             = $self->get_product_name();
+       # Check if Windows has already been activated
+       my $license_status = $self->get_license_status();
+       if ($license_status && $license_status =~ /licensed/i) {
+               notify($ERRORS{'OK'}, 0, "Windows has already been activated");
+               return 1;
+       }
+       
+       ## Attempt to activate using MAK product key
+       #return 1 if $self->activate_mak();
        
-       # Get the image affiliation name
-       my $image_affiliation_name = $self->data->get_image_affiliation_name();
-       if ($image_affiliation_name) {
-               notify($ERRORS{'DEBUG'}, 0, "image affiliation name: 
$image_affiliation_name");
+       # Attempt to activate using KMS server
+       return 1 if $self->activate_kms();
+       
+       notify($ERRORS{'WARNING'}, 0, "failed to activate Windows using MAK or 
KMS methods");
+       return;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 activate_mak
+
+ Parameters  : None
+ Returns     : If successful: true
+               If failed: false
+ Description : Attempts to activate Windows using a MAK key stored in the
+               winProductKey table.
+
+=cut
+
+sub activate_mak {
+       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;
+       }
+       
+       # Attempt to get the product key stored in the winProductKey table
+       # This will return the correct key for the affiliation and version of 
Windows installed on the computer
+       my $product_key = $self->get_product_key();
+       if ($product_key) {
+               notify($ERRORS{'DEBUG'}, 0, "retrieved MAK product key from the 
winProductKey table: $product_key");
        }
        else {
-               notify($ERRORS{'WARNING'}, 0, "image affiliation name could not 
be retrieved, using default licensing configuration");
-               $image_affiliation_name = 'default';
+               notify($ERRORS{'OK'}, 0, "MAK product key could not be 
retrieved from the winProductKey table");
+               return;
        }
        
-       # Get the Windows activation data from the windows-activation variable
-       my $activation_data = $self->data->get_variable('windows-activation');
-       if ($activation_data) {
-               notify($ERRORS{'DEBUG'}, 0, "activation data:\n" . 
format_data($activation_data));
+       # Attempt to install the MAK product key
+       if ($self->run_slmgr_ipk($product_key)) {
+               notify($ERRORS{'DEBUG'}, 0, "installed MAK product key: 
$product_key");
        }
        else {
-               notify($ERRORS{'WARNING'}, 0, "activation data could not be 
retrieved");
+               notify($ERRORS{'WARNING'}, 0, "failed to install MAK product 
key: $product_key");
                return;
        }
        
-       # Get the activation data specific to the image affiliation
-       my $affiliation_config = $activation_data->{$image_affiliation_name};
-       if ($affiliation_config) {
-               notify($ERRORS{'DEBUG'}, 0, "$image_affiliation_name 
affiliation activation configuration:\n" . format_data($affiliation_config));
+       # Attempt to activate the license
+       if ($self->run_slmgr_ato()) {
+               notify($ERRORS{'OK'}, 0, "activated Windows using MAK product 
key: $product_key");
+               return 1;
        }
        else {
-               notify($ERRORS{'WARNING'}, 0, "activation configuration does 
not exist for affiliation: $image_affiliation_name, attempting to retrieve 
default configuration");
-               
-               $affiliation_config = $activation_data->{'default'};
-               if ($affiliation_config) {
-                       notify($ERRORS{'DEBUG'}, 0, "default activation 
configuration:\n" . format_data($affiliation_config));
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "default activation 
configuration does not exist");
-                       return;
-               }
+               notify($ERRORS{'WARNING'}, 0, "failed to activate Windows using 
MAK product key: $product_key");
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 activate_kms
+
+ Parameters  : None
+ Returns     : If successful: true
+               If failed: false
+ Description : Attempts to activate Windows using a KMS server configured in
+               the winKMS table.
+
+=cut
+
+sub activate_kms {
+       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;
+       }
+       
+       # Get the KMS server info from the winKMS table
+       my $kms_server_info = $self->get_kms_servers();
+       if (!$kms_server_info) {
+               notify($ERRORS{'WARNING'}, 0, "KMS server information could not 
be retrieved");
+               return;
+       }
+       
+       # Attempt to get the KMS client product key
+       # This is a publically available key that needs to be installed in 
order to activate via KMS
+       my $product_key = $self->get_kms_client_product_key();
+       if ($product_key) {
+               notify($ERRORS{'DEBUG'}, 0, "retrieved KMS client product key: 
$product_key");
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "KMS client product key could not 
be retrieved");
+               return;
        }
        
+       # Attempt to install the KMS client product key
+       if ($self->run_slmgr_ipk($product_key)) {
+               notify($ERRORS{'DEBUG'}, 0, "installed KMS client product key: 
$product_key");
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to install KMS client 
product key: $product_key");
+               return;
+       }
        
-       # Loop through the activation methods for the affiliation
-       for my $activation_config (@$affiliation_config) {
-               my $activation_method = $activation_config->{method};
+       # Loop through the KMS servers, set KMS server, attempt to activate
+       for my $kms_server (@{$kms_server_info}) {
+               my $kms_address = $kms_server->{address};
+               my $kms_port = $kms_server->{port};
+               notify($ERRORS{'DEBUG'}, 0, "attempting to set KMS server: 
$kms_address:$kms_port");
                
-               if ($activation_method =~ /kms/i) {
-                       my $kms_address = $activation_config->{address};
-                       my $kms_port = $activation_config->{port} || 1688;
-                       notify($ERRORS{'DEBUG'}, 0, "attempting to set kms 
server: $kms_address, port: $kms_port");
-                       
-                       # Attempt to install the KMS client product key
-                       # This must be done or else the slmgr.vbs -skms option 
won't be available
-                       if ($self->install_kms_client_product_key()) {
-                               notify($ERRORS{'DEBUG'}, 0, "installed the KMS 
client product key");
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "failed to 
install the KMS client product key");
-                               next;
-                       }
+               # Run slmgr.vbs -skms to configure the computer to use the KMS 
server
+               if ($self->run_slmgr_skms($kms_address, $kms_port)) {
+                       notify($ERRORS{'OK'}, 0, "set KMS server: 
$kms_address:$kms_port");
                        
-                       # Run slmgr.vbs -skms to configure the computer to use 
the KMS server
-                       if ($self->set_kms($kms_address, $kms_port)) {
-                               notify($ERRORS{'DEBUG'}, 0, "set KMS address");
+                       # Attempt to activate the license
+                       if ($self->run_slmgr_ato()) {
+                               notify($ERRORS{'OK'}, 0, "activated Windows 
using KMS server: $kms_address:$kms_port");
+                               return 1;
                        }
                        else {
-                               notify($ERRORS{'WARNING'}, 0, "failed to set 
KMS address");
+                               notify($ERRORS{'WARNING'}, 0, "failed to 
activate Windows using KMS server: $kms_address:$kms_port");
                                next;
                        }
                }
-               elsif ($activation_method =~ /mak/i) {
-                       my $mak_key = $activation_config->{key};
-                       my $mak_product = $activation_config->{product};
-                       
-                       if ($mak_product eq $product_name) {
-                               notify($ERRORS{'DEBUG'}, 0, "attempting to set 
install MAK key for $mak_product: $mak_key");
-                       }
-                       else {
-                               notify($ERRORS{'DEBUG'}, 0, "MAK key product 
($mak_product) does not match installed version of Windows ($product_name)");
-                               next;
-                       }
-                       
-                       # Attempt to install the MAK product key
-                       if ($self->install_product_key($mak_key)) {
-                               notify($ERRORS{'DEBUG'}, 0, "installed MAK 
product key: $mak_key");
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "failed to 
install MAK product key: $mak_key");
-                               next;
-                       }
-               }
-               else  {
-                       notify($ERRORS{'WARNING'}, 0, "unsupported activation 
method: $activation_method");
-                       next;
-               }
-               
-               # Attempt to activate the license
-               if ($self->activate_license()) {
-                       notify($ERRORS{'OK'}, 0, "activated license");
-                       return 1;
-               }
                else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to activate 
license");
+                       notify($ERRORS{'WARNING'}, 0, "failed to set KMS 
server: $kms_address:$kms_port");
                        next;
                }
        }
        
-       notify($ERRORS{'WARNING'}, 0, "failed to activate license on 
$computer_node_name using any configured method");
+       notify($ERRORS{'WARNING'}, 0, "failed to activate Windows using any KMS 
servers configured in the winKMS table");
        return;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 install_kms_client_product_key
+=head2 get_kms_client_product_key
 
- Parameters  : None
- Returns     : If successful: true
+ Parameters  : $product_name (optional
+ Returns     : If successful: string
                If failed: false
- Description : 
+ Description : Returns a KMS client product key based on the version of Windows
+               either specified as an argument or installed on the computer. A
+               KMS client product key is a publically shared product key which
+               must be installed before activating using a KMS server.
 
 =cut
 
-sub install_kms_client_product_key {
+sub get_kms_client_product_key {
        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;
        }
        
+       # Get the product name
+       my $product_name = shift || $self->get_product_name();
+       if (!$product_name) {
+               notify($ERRORS{'WARNING'}, 0, "product name was not passed as 
an argument and could not be retrieved from computer");
+               return;
+       }
+       
+       # Remove (TM) or (R) from the product name
+       $product_name =~ s/ \([tmr]*\)//ig;
+       
        # Create a hash of KMS setup product keys
        # These are publically available from Microsoft's Volume Activation 2.0 
Deployment Guide
        my %kms_product_keys = (
@@ -410,42 +455,28 @@
                'Windows Web Server 2008'                        => 
'WYR28-R7TFJ-3X2YQ-YCY4H-M249D',
        );
        
-       # Get the KMS setup product key from the hash
-       my $product_name = $self->get_product_name();
-       
-       # Remove (TM) or (R) from the product name
-       $product_name =~ s/ \([tmr]*\)//ig;
-       
+       # Get the matching product key from the hash for the product name
        my $product_key = $kms_product_keys{$product_name};
        if (!$product_key) {
-               notify($ERRORS{'WARNING'}, 0, "failed to retrieve KMS setup key 
for Windows product: $product_name");
-               return;
-       }
-       notify($ERRORS{'DEBUG'}, 0, "KMS client setup key for $product_name: 
$product_key");
-       
-       # Install the KMS client product key
-       if ($self->install_product_key($product_key)) {
-               notify($ERRORS{'OK'}, 0, "installed KMS client product key");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to install KMS client 
product key");
+               notify($ERRORS{'WARNING'}, 0, "unsupported product name: 
$product_name, KMS client product key is not known");
                return;
        }
+       notify($ERRORS{'DEBUG'}, 0, "returning KMS client setup key for 
$product_name: $product_key");
+       return $product_key;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 install_product_key
+=head2 run_slmgr_ipk
 
  Parameters  : None
  Returns     : If successful: true
                If failed: false
- Description : 
+ Description : Runs slmgr.vbs -ipk to install a product key.
 
 =cut
 
-sub install_product_key {
+sub run_slmgr_ipk {
        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");
@@ -454,6 +485,7 @@
        
        my $management_node_keys     = $self->data->get_management_node_keys();
        my $computer_node_name       = $self->data->get_computer_node_name();
+       my $system32_path = $self->get_system32_path();
        
        # Get the arguments
        my $product_key = shift;
@@ -463,7 +495,7 @@
        }
        
        # Run cscript.exe slmgr.vbs -ipk to install the product key
-       my $ipk_command = 'cscript.exe //NoLogo $SYSTEMROOT/System32/slmgr.vbs 
-ipk ' . $product_key;
+       my $ipk_command = "$system32_path/cmd.exe /c cscript.exe //NoLogo 
C:/Windows/System32/slmgr.vbs -ipk $product_key";
        my ($ipk_exit_status, $ipk_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $ipk_command);
        if (defined($ipk_exit_status) && $ipk_exit_status == 0 && 
grep(/successfully/i, @$ipk_output)) {
                notify($ERRORS{'OK'}, 0, "installed product key: $product_key");
@@ -482,16 +514,16 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 set_kms
+=head2 run_slmgr_skms
 
  Parameters  : None
  Returns     : If successful: true
                If failed: false
- Description : 
+ Description : Runs slmgr.vbs -skms to set the KMS server on a Windows client.
 
 =cut
 
-sub set_kms {
+sub run_slmgr_skms {
        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");
@@ -500,6 +532,7 @@
        
        my $management_node_keys     = $self->data->get_management_node_keys();
        my $computer_node_name       = $self->data->get_computer_node_name();
+       my $system32_path = $self->get_system32_path();
        
        # Get the KMS address argument
        my $kms_address = shift;
@@ -512,7 +545,8 @@
        my $kms_port = shift || 1688;
        
        # Run slmgr.vbs -skms to configure the computer to use the KMS server
-       my $skms_command = 'cscript.exe //NoLogo $SYSTEMROOT/System32/slmgr.vbs 
-skms ' . "$kms_address:$kms_port";
+       # slmgr.vbs must be run in a command shell using the correct System32 
path or the task it's supposed to do won't really take effect
+       my $skms_command = "$system32_path/cmd.exe /c cscript.exe //NoLogo 
C:/Windows/System32/slmgr.vbs -skms $kms_address:$kms_port";
        my ($skms_exit_status, $skms_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $skms_command);
        if (defined($skms_exit_status) && $skms_exit_status == 0 && 
grep(/successfully/i, @$skms_output)) {
                notify($ERRORS{'OK'}, 0, "set kms server to 
$kms_address:$kms_port");
@@ -531,16 +565,16 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 activate_license
+=head2 run_slmgr_ato
 
  Parameters  : None
  Returns     : If successful: true
                If failed: false
- Description : 
+ Description : Runs slmgr.vbs -ato to activate Windows.
 
 =cut
 
-sub activate_license {
+sub run_slmgr_ato {
        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");
@@ -549,9 +583,10 @@
        
        my $management_node_keys     = $self->data->get_management_node_keys();
        my $computer_node_name       = $self->data->get_computer_node_name();
+       my $system32_path = $self->get_system32_path();
        
        # Run cscript.exe slmgr.vbs -ato to install the product key
-       my $ato_command = 'cscript.exe //NoLogo $SYSTEMROOT/System32/slmgr.vbs 
-ato';
+       my $ato_command = "$system32_path/cmd.exe /c cscript.exe //NoLogo 
C:/Windows/System32/slmgr.vbs -ato";
        my ($ato_exit_status, $ato_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $ato_command);
        if (defined($ato_exit_status) && $ato_exit_status == 0 && 
grep(/successfully/i, @$ato_output)) {
                notify($ERRORS{'OK'}, 0, "activated license");
@@ -570,6 +605,50 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_license_status
+
+ Parameters  : None
+ Returns     : If successful: string
+               If failed: false
+ Description : Runs slmgr.vbs -dlv to determine the licensing status. The value
+               of the "License Status" line is returned.
+
+=cut
+
+sub get_license_status {
+       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 $system32_path = $self->get_system32_path();
+       
+       # Run cscript.exe slmgr.vbs -dlv to get the activation status
+       my $dlv_command = "$system32_path/cmd.exe /c cscript.exe //NoLogo 
C:/Windows/System32/slmgr.vbs -dlv";
+       my ($dlv_exit_status, $dlv_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $dlv_command, '', 
'', 0);
+       if ($dlv_output && grep(/License Status/i, @$dlv_output)) {
+               #notify($ERRORS{'DEBUG'}, 0, "retrieved license information");
+       }
+       elsif (defined($dlv_exit_status)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve activation 
status, exit status: $dlv_exit_status, output:\...@{$dlv_output}");
+               return;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute ssh command to 
retrieve activation status");
+               return;
+       }
+       
+       my ($license_status_line) = grep(/License Status/i, @$dlv_output);
+       my ($license_status) = $license_status_line =~ /: (\w+)/;
+       notify($ERRORS{'DEBUG'}, 0, "retrieved license status: 
$license_status");
+       return $license_status;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 deactivate
 
  Parameters  : None
@@ -590,6 +669,7 @@
        
        my $management_node_keys     = $self->data->get_management_node_keys();
        my $computer_node_name       = $self->data->get_computer_node_name();
+       my $system32_path = $self->get_system32_path();
        
        my $registry_string .= <<'EOF';
 Windows Registry Editor Version 5.00
@@ -610,7 +690,7 @@
        }
        
        # Run slmgr.vbs -rearm
-       my $rearm_command = 'cscript.exe //NoLogo 
$SYSTEMROOT/System32/slmgr.vbs -rearm';
+       my $rearm_command = "$system32_path/cmd.exe /c cscript.exe //NoLogo 
C:/Windows/System32/slmgr.vbs -rearm";
        my ($rearm_exit_status, $rearm_output) = 
run_ssh_command($computer_node_name, $management_node_keys, $rearm_command);
        if (defined($rearm_exit_status) && $rearm_exit_status == 0 && 
grep(/successfully/i, @$rearm_output)) {
                notify($ERRORS{'OK'}, 0, "rearmed licensing");
@@ -1157,97 +1237,6 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 add_kms_server
-
- Parameters  : $affiliation_name, $kms_address, $kms_port
- Returns     : If successful: true
-               If failed: false
- Description : Adds a kms server to the windows-activation variable for the
-               specified affiliation name.
-               If a KMS server with the same address is already saved in the
-               windows-activation variable, it is deleted and the KMS server
-               specified in the subroutine arguments is added to the end of the
-               configuration list.
-
-=cut
-
-sub add_kms_server {
-       my ($affiliation_name, $kms_address, $kms_port) = @_;
-       
-       # Check the arguments
-       unless ($affiliation_name && $kms_address) {
-               notify($ERRORS{'WARNING'}, 0, "affiliation name and kms server 
address must be specified as arguments");
-               return;
-       }
-       
-       # Set the default KMS port to 1688 if the argument was not specified
-       $kms_port = 1688 unless $kms_port;
-       
-       # Get a new DataStructure object
-       my $data = VCL::DataStructure->new();
-       if ($data) {
-               notify($ERRORS{'DEBUG'}, 0, "created new DataStructure object");
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to create new 
DataStructure object");
-               return;
-       }
-       
-       # Get the Windows activation data from the windows-activation variable
-       my $activation_data = $data->get_variable('windows-activation');
-       if ($activation_data) {
-               notify($ERRORS{'DEBUG'}, 0, "existing activation data:\n" . 
format_data($activation_data));
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "activation data could not be 
retrieved, hopefully this is the first entry being added");
-       }
-       
-       # Loop through the existing configurations for the affiliation
-       for (my $i=0; $i<(@{$activation_data->{$affiliation_name}}); $i++) {
-               my $affiliation_configuration = 
@{$activation_data->{$affiliation_name}}[$i];
-               
-               # Remove the configuration if it's not defined
-               if (!defined $affiliation_configuration) {
-                       splice @{$activation_data->{$affiliation_name}}, $i--, 
1;
-                       next;
-               }
-               
-               # Check if an identical existing address already exists, if so, 
delete it
-               my $existing_affiliation_kms_address = 
$affiliation_configuration->{address};
-               if ($existing_affiliation_kms_address eq $kms_address) {
-                       splice @{$activation_data->{$affiliation_name}}, $i--, 
1;
-                       notify($ERRORS{'DEBUG'}, 0, "deleted identical existing 
address for $affiliation_name: $existing_affiliation_kms_address");
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "found existing address for 
$affiliation_name: $existing_affiliation_kms_address");
-               }
-       }
-       
-       # Add the KMS configuration to the activation data
-       push @{$activation_data->{$affiliation_name}}, {
-                                                                               
                                                method => 'kms',
-                                                                               
                                                address => $kms_address,
-                                                                               
                                                port => $kms_port,
-                                                                               
                                          };
-       
-       # Set the variable with the updated data
-       $data->set_variable('windows-activation', $activation_data);
-       
-       # Retrieve the updated configuration data
-       $activation_data = $data->get_variable('windows-activation');
-       if ($activation_data) {
-               notify($ERRORS{'DEBUG'}, 0, "updated activation data:\n" . 
format_data($activation_data));
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "updated activation data could 
not be retrieved");
-               return;
-       }
-       
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 run_sysprep
 
  Parameters  : None


Reply via email to