Author: arkurth Date: Mon Jan 11 18:14:14 2010 New Revision: 897984 URL: http://svn.apache.org/viewvc?rev=897984&view=rev Log: VCL-145 Added get_product_key, set_product_key, get_kms_servers, and set_kms_server subroutines to Windows.pm. They get/set data from the winProductKey and winKMS tables.
Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.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=897984&r1=897983&r2=897984&view=diff ============================================================================== --- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original) +++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Mon Jan 11 18:14:14 2010 @@ -8150,6 +8150,462 @@ #///////////////////////////////////////////////////////////////////////////// +=head2 get_product_key + + Parameters : $affiliation_identifier (optional), $product_name (optional) + Returns : If successful: string containing product key + If failed: false + Description : Retrieves the Windows product key from the database. This is + stored in the winProductKey table. + + Optional affiliation identifier and product name arguments may be + passed. Either both arguments must be passed or none. The + affiliation identifier may either be an affiliation ID or name. + If passed, the only data returned will be the data matching that + specific identifier. Global affiliation data will not be + returned. + + If the affiliation identifier argument is not passed, the + affiliation is determined by the affiliation of the owner of the + image for the reservation. If a product key has not been + configured for that specific affiliation, the product key + configured for the Global affiliation is returned. + +=cut + +sub get_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; + } + + # Remember if this sub was called with arguments + # Used to determine whether or not Global activation data will be checked + # If affiliation ID argument is specified, assume caller only wants the data for that affiliation and not the Global data + my $include_global; + if (scalar(@_) == 2) { + $include_global = 0; + notify($ERRORS{'DEBUG'}, 0, "subroutine was called with arguments, global affiliation data will be ignored"); + } + elsif (scalar(@_) == 0) { + $include_global = 1; + notify($ERRORS{'DEBUG'}, 0, "subroutine was NOT called with arguments, global affiliation data will be included"); + } + else { + notify($ERRORS{'WARNING'}, 0, "subroutine argument count = " . scalar(@_) . ", it must only be called with 0 or 2 arguments"); + return; + } + + # Get the affiliation identifer, may be ID or name + my $affiliation_identifier = shift; + if (!defined($affiliation_identifier)) { + $affiliation_identifier = $self->data->get_image_affiliation_id(); + } + if (!defined($affiliation_identifier)) { + notify($ERRORS{'WARNING'}, 0, "affiliation identifier argument was not passed and could not be determined from image"); + return; + } + + # Get the product name, could be: + # "Microsoft Windows XP" + # "Microsoft Windows Server 2003" + my $product_name = shift || $self->get_product_name(); + if ($product_name) { + notify($ERRORS{'DEBUG'}, 0, "product name: $product_name"); + } + else { + notify($ERRORS{'WARNING'}, 0, "product name argument was not passed and could not be determined from computer"); + return; + } + + # Create the affiliation-specific select statement + # Check if the affiliation identifier is a number or word + # If a number, use affiliation.id directly + # If a word, reference affiliation.name + my $affiliation_select_statement; + if ($affiliation_identifier =~ /^\d+$/) { + notify($ERRORS{'DEBUG'}, 0, "affiliation identifier is a number, retrieving winProductKey.affiliationid=$affiliation_identifier"); + $affiliation_select_statement = <<EOF; +SELECT +winProductKey.* +FROM +winProductKey +WHERE +winProductKey.productname LIKE '$product_name' +AND winProductKey.affiliationid = $affiliation_identifier +EOF + } + else { + notify($ERRORS{'DEBUG'}, 0, "affiliation identifier is NOT a number, retrieving affiliation.name=$affiliation_identifier"); + $affiliation_select_statement = <<EOF; +SELECT +winProductKey.* +FROM +winProductKey, +affiliation +WHERE +winProductKey.productname LIKE '$product_name' +AND winProductKey.affiliationid = affiliation.id +AND affiliation.name LIKE '$affiliation_identifier' +EOF + } + + # Create the select statement + my $global_select_statement = <<EOF; +SELECT +winProductKey.* +FROM +winProductKey, +affiliation +WHERE +winProductKey.productname LIKE '$product_name' +AND winProductKey.affiliationid = affiliation.id +AND affiliation.name LIKE 'Global' +EOF + + # Call the database select subroutine + my @affiliation_rows = database_select($affiliation_select_statement); + + # Get the rows for the Global affiliation if this subroutine wasn't called with arguments + my @global_rows = (); + if ($include_global) { + @global_rows = database_select($global_select_statement); + } + + # Create an array containing the combined rows + my @combined_rows = (@affiliation_rows, @global_rows); + + # Check to make sure rows were returned + if (!...@combined_rows) { + notify($ERRORS{'WARNING'}, 0, "0 rows were retrieved from winProductKey table for affiliation=$affiliation_identifier, product=$product_name"); + return; + } + notify($ERRORS{'DEBUG'}, 0, "retrieved rows from winProductKey table for affiliation=$affiliation_identifier, product=$product_name:\n" . format_data(\...@combined_rows)); + + my $product_key = $combined_rows[0]->{productkey}; + notify($ERRORS{'DEBUG'}, 0, "returning product key: $product_key"); + + return $product_key; +} + +#///////////////////////////////////////////////////////////////////////////// + +=head2 set_product_key + + Parameters : $affiliation_id, $product_name, $product_key + Returns : If successful: true + If failed: false + Description : Inserts or updates a row in the winKMS table in the database. + +=cut + +sub set_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 and check the arguments + my ($affiliation_identifier, $product_name, $product_key) = @_; + if (!defined($affiliation_identifier) || !defined($product_name) || !defined($product_key)) { + notify($ERRORS{'WARNING'}, 0, "affiliation ID, product name, and product key arguments not passed correctly"); + return; + } + + # Create the insert statement + # Check if the affiliation identifier is a number or word + # If a number, set affiliation.id directly + # If a word, reference affiliation.name + my $insert_statement; + if ($affiliation_identifier =~ /^\d+$/) { + notify($ERRORS{'DEBUG'}, 0, "affiliation identifier is a number, setting winProductKey.affiliationid=$affiliation_identifier"); + $insert_statement = <<"EOF"; +INSERT INTO winProductKey +( +affiliationid, +productname, +productkey +) +VALUES +( +'$affiliation_identifier', +'$product_name', +'$product_key' +) +ON DUPLICATE KEY UPDATE +affiliationid=VALUES(affiliationid), +productname=VALUES(productname), +productkey=VALUES(productkey) +EOF + } + else { + notify($ERRORS{'DEBUG'}, 0, "affiliation identifier is NOT a number, setting affiliation.name=$affiliation_identifier"); + $insert_statement = <<"EOF"; +INSERT INTO winProductKey +( +affiliationid, +productname, +productkey +) +VALUES +( +(SELECT id FROM affiliation WHERE name='$affiliation_identifier'), +'$product_name', +'$product_key' +) +ON DUPLICATE KEY UPDATE +affiliationid=VALUES(affiliationid), +productname=VALUES(productname), +productkey=VALUES(productkey) +EOF + } + + # Execute the insert statement, the return value should be the id of the row + my $insert_result = database_execute($insert_statement); + if (defined($insert_result)) { + notify($ERRORS{'DEBUG'}, 0, "set product key in database:\naffiliation ID: $affiliation_identifier\nproduct name: $product_name\nproduct key: $product_key"); + + } + else { + notify($ERRORS{'WARNING'}, 0, "failed to set product key in database:\naffiliation ID: $affiliation_identifier\nproduct name: $product_name\nproduct key: $product_key"); + return; + } + + return 1; +} + +#///////////////////////////////////////////////////////////////////////////// + +=head2 get_kms_servers + + Parameters : $affiliation_identifier (optional) + Returns : If successful: reference to array of hashes + If failed: false + Description : Retrieves the KMS server data from the database. This is + stored in the winKMS table. + + An optional affiliation identifier argument may be passed. This + may either be an affiliation ID or name. If passed, the only data + returned will be the data matching that specific identifier. + Global affiliation data will not be returned. + + If the affiliation identifier argument is not passed, the + affiliation is determined by the affiliation of the owner of the + image for the reservation. If a KMS server has not been + configured for that specific affiliation, the KMS server + configured for the Global affiliation is returned. + + This subroutine returns an array reference. Each array element + contains a hash reference representing a row in the winKMS table. + + Example of returned data: + @{$kms_servers}[0] = + |--{address} = 'kms.affiliation.edu' + |--{affiliationid} = '1' + |--{port} = '1688' + @{$kms_servers}[1] = + |--{address} = 'kms.global.edu' + |--{affiliationid} = '0' + |--{port} = '1688' + + Example usage: + my $kms_servers = $self->os->get_kms_servers(); + my $kms_address = @{$kms_servers[0]}->{address}; + +=cut + +sub get_kms_servers { + 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; + } + + # Remember if this sub was called with arguments + # Used to determine whether or not global affiliation data will be checked + my $include_global; + if (scalar(@_) == 1) { + $include_global = 0; + notify($ERRORS{'DEBUG'}, 0, "subroutine was called with an affiliation argument, global affiliation data will be ignored"); + } + elsif (scalar(@_) == 0) { + $include_global = 1; + notify($ERRORS{'DEBUG'}, 0, "subroutine was NOT called with arguments, global affiliation data will be included"); + } + else { + notify($ERRORS{'WARNING'}, 0, "subroutine argument count = " . scalar(@_) . ", it must only be called with 0 or 1 arguments"); + return; + } + + # Get the image affiliation identifier, may be ID or name + my $affiliation_identifier = shift; + if (!defined($affiliation_identifier)) { + $affiliation_identifier = $self->data->get_image_affiliation_id(); + } + if (!defined($affiliation_identifier)) { + notify($ERRORS{'WARNING'}, 0, "affiliation argument was not passed and could not be determined from image"); + return; + } + + # Create the affiliation-specific select statement + # Check if the affiliation identifier is a number or word + # If a number, use affiliation.id directly + # If a word, reference affiliation.name + my $affiliation_select_statement; + if ($affiliation_identifier =~ /^\d+$/) { + notify($ERRORS{'DEBUG'}, 0, "affiliation identifier is a number, retrieving winKMS.affiliationid=$affiliation_identifier"); + $affiliation_select_statement = <<EOF; +SELECT +winKMS.* +FROM +winKMS +WHERE +winKMS.affiliationid = $affiliation_identifier +EOF + } + else { + notify($ERRORS{'DEBUG'}, 0, "affiliation identifier is NOT a number, retrieving affiliation.name=$affiliation_identifier"); + $affiliation_select_statement .= <<EOF; +SELECT +winKMS.* +FROM +winKMS, +affiliation +WHERE +winKMS.affiliationid = affiliation.id +AND affiliation.name LIKE '$affiliation_identifier' +EOF + } + + # Create the Global affiliation select statement + my $global_select_statement .= <<EOF; +SELECT +winKMS.* +FROM +winKMS, +affiliation +WHERE +winKMS.affiliationid = affiliation.id +AND affiliation.name LIKE 'Global' +EOF + + # Call the database select subroutine + my @affiliation_rows = database_select($affiliation_select_statement); + + # Get the rows for the Global affiliation if this subroutine wasn't called with arguments + my @global_rows = (); + if ($include_global) { + @global_rows = database_select($global_select_statement); + } + + # Create an array containing the combined rows + my @combined_rows = (@affiliation_rows, @global_rows); + + # Check to make sure rows were returned + if (!...@combined_rows) { + notify($ERRORS{'WARNING'}, 0, "0 rows were retrieved from winKMS table for affiliation=$affiliation_identifier"); + return; + } + + notify($ERRORS{'DEBUG'}, 0, "returning row array from winKMS table for affiliation=$affiliation_identifier:\n" . format_data(\...@combined_rows)); + return \...@combined_rows; +} + +#///////////////////////////////////////////////////////////////////////////// + +=head2 set_kms_server + + Parameters : $affiliation_id, $address, $port (optional) + Returns : If successful: true + If failed: false + Description : Inserts or updates a row in the winKMS table in the database. + +=cut + +sub set_kms_server { + 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 and check the arguments + my ($affiliation_identifier, $address, $port) = @_; + if (!defined($affiliation_identifier) || !defined($address)) { + notify($ERRORS{'WARNING'}, 0, "affiliation ID and KMS address arguments not passed correctly"); + return; + } + + # Set the default port if argument wasn't passed + if (!defined($port)) { + $port = 1688; + } + + # Create the insert statement + # Check if the affiliation identifier is a number or word + # If a number, set affiliation.id directly + # If a word, reference affiliation.name + my $insert_statement; + if ($affiliation_identifier =~ /^\d+$/) { + notify($ERRORS{'DEBUG'}, 0, "affiliation identifier is a number, setting winKMS.affiliationid=$affiliation_identifier"); + $insert_statement = <<"EOF"; +INSERT INTO winKMS +( +affiliationid, +address, +port +) +VALUES +( +'$affiliation_identifier', +'$address', +'$port' +) +ON DUPLICATE KEY UPDATE +affiliationid=VALUES(affiliationid), +address=VALUES(address), +port=VALUES(port) +EOF + } + else { + notify($ERRORS{'DEBUG'}, 0, "affiliation identifier is NOT a number, setting affiliation.name=$affiliation_identifier"); + $insert_statement = <<"EOF"; +INSERT INTO winKMS +( +affiliationid, +address, +port +) +VALUES +( +(SELECT id FROM affiliation WHERE name='$affiliation_identifier'), +'$address', +'$port' +) +ON DUPLICATE KEY UPDATE +affiliationid=VALUES(affiliationid), +address=VALUES(address), +port=VALUES(port) +EOF + } + + # Execute the insert statement, the return value should be the id of the row + my $insert_result = database_execute($insert_statement); + if (defined($insert_result)) { + notify($ERRORS{'OK'}, 0, "set KMS address in database:\naffiliation ID: $affiliation_identifier\naddress: $address\nport: $port"); + } + else { + notify($ERRORS{'WARNING'}, 0, "failed to set KMS address in database:\naffiliation ID: $affiliation_identifier\naddress: $address\nport: $port"); + return; + } + + return 1; +} + +#///////////////////////////////////////////////////////////////////////////// + 1; __END__