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 2015/02/11 01:03:26 UTC
svn commit: r1658846 - in /vcl/trunk/managementnode/lib/VCL/Module: OS.pm
OS/Windows.pm
Author: arkurth
Date: Wed Feb 11 00:03:26 2015
New Revision: 1658846
URL: http://svn.apache.org/r1658846
Log:
VCL-815
Reworked OS.pm::update_cluster. Each reservation now only creates a cluster_info file for itself. The firewall processes was also improved to be much more efficient.
Fixed problem with Windows code which creates the cluster_info file. The line endings were not Windows-style because the sed command in OS.pm::set_text_file_line_endings was failing. Sed under Cygwin can't handle a Windows-style file path if the "-i" switch is used. Added get_cygwin_unix_file_path subroutine. This gets called and the result gets passed to set_text_file_line_endings.
Other
Cleaned up and renamed Windows.pm::get_cygwin_path --> get_cygwin_installation_directory_path. It was messy. There were notify messages obviously copied/pasted from another subroutine which made no sense. Its name had also become vague with the addition of get_cygwin_unix_file_path, both of which call cygpath.exe.
Modified:
vcl/trunk/managementnode/lib/VCL/Module/OS.pm
vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
Modified: vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1658846&r1=1658845&r2=1658846&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Wed Feb 11 00:03:26 2015
@@ -930,7 +930,7 @@ sub is_ssh_responding {
notify($ERRORS{'DEBUG'}, 0, "$computer_node_name is NOT responding to SSH, ports 22 or 24 are both closed");
return 0;
}
-
+
if ($max_attempts) {
# Run a test SSH command
#my ($exit_status, $output) = $self->execute({
@@ -2255,7 +2255,7 @@ sub set_text_file_line_endings {
return 1;
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to set $type-style line endings for file: $file_path, exit status: $exit_status, output:\n@{$output}");
+ notify($ERRORS{'WARNING'}, 0, "failed to set $type-style line endings for file: $file_path, exit status: $exit_status, command:\n$command\noutput:\n@{$output}");
return;
}
}
@@ -3887,86 +3887,112 @@ sub firewall_compare_update {
=cut
sub update_cluster {
-
my $self = shift;
if (ref($self) !~ /VCL::Module/i) {
notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
return;
}
-
- my $reservation_id = $self->data->get_reservation_id();
+
+ my $current_reservation_id = $self->data->get_reservation_id();
+ my @reservation_ids = $self->data->get_reservation_ids();
+ my @child_reservation_ids = $self->data->get_child_reservation_ids();
+ my $parent_reservation_id = $self->data->get_parent_reservation_id();
my $computer_short_name = $self->data->get_computer_short_name();
- my $image_OS_type = $self->data->get_image_os_type();
- my $is_cluster_parent = $self->data->get_request_is_cluster_parent();
- my $is_cluster_child = $self->data->get_request_is_cluster_child();
-
- my $cluster_info = "/tmp/$computer_short_name.cluster_info";
- my @cluster_string = "";
-
- #Get all the request data
- my $request_data = $self->data->get_request_data();
-
- my @reservation_ids = sort keys %{$request_data->{reservation}};
-
- # parent reservation id lowest
- my $parent_reservation_id = min @reservation_ids;
- notify($ERRORS{'DEBUG'}, 0, "$computer_short_name is_cluster_parent = $is_cluster_parent ");
- notify($ERRORS{'DEBUG'}, 0, "$computer_short_name is_cluster_child = $is_cluster_child ");
- notify($ERRORS{'DEBUG'}, 0, "parent_reservation_id = $parent_reservation_id ");
-
- foreach my $rid (keys %{$request_data->{reservation}}) {
- if ($rid == $parent_reservation_id) {
- push(@cluster_string, "parent= $request_data->{reservation}{$rid}{computer}{IPaddress}" . "\n");
- notify($ERRORS{'DEBUG'}, 0, "writing parent= $request_data->{reservation}{$rid}{computer}{IPaddress}");
+
+ my $cluster_info_file_path = $self->get_cluster_info_file_path();
+ my $cluster_info_string = '';
+
+ my @public_ip_addresses;
+
+ for my $cluster_reservation_id (@reservation_ids) {
+ # Get a DataStructure object for each reservation
+ my $reservation_data;
+ if ($cluster_reservation_id eq $current_reservation_id) {
+ $reservation_data = $self->data();
}
else {
- push(@cluster_string, "child= $request_data->{reservation}{$rid}{computer}{IPaddress}" . "\n");
- notify($ERRORS{'DEBUG'}, 0, "writing child= $request_data->{reservation}{$rid}{computer}{IPaddress}");
+ $reservation_data = $self->data->get_reservation_data($cluster_reservation_id);
+ }
+ if (!$reservation_data) {
+ notify($ERRORS{'WARNING'}, 0, "failed to update cluster request, data could not be retrieved for reservation $cluster_reservation_id");
+ return;
}
- #Create iptables rule for each node in cluster on the node being processed
- # Could slow things down for large clusters, but they can communicate with each other
- if ($self->can('enable_firewall_port')) {
- if (!$self->enable_firewall_port("tcp", "any", $request_data->{reservation}{$rid}{computer}{IPaddress}, 0)) {
- notify($ERRORS{'DEBUG'}, 0, "adding $request_data->{reservation}{$rid}{computer}{IPaddress} to iptables");
- }
+ # Get the computer IP address
+ my $cluster_computer_public_ip_address = $reservation_data->get_computer_public_ip_address();
+ if (!$cluster_computer_public_ip_address) {
+ notify($ERRORS{'WARNING'}, 0, "failed to update cluster request, public IP address could not be retrieved for computer assigned to reservation $cluster_reservation_id");
+ return;
+ }
+
+ # Add the public IP address to the array for reservations not matching the reservation ID currently being processed
+ if ($cluster_reservation_id ne $current_reservation_id) {
+ push @public_ip_addresses, $cluster_computer_public_ip_address;
}
+
+ # Add a line to cluster_info string for each reservation
+ if ($cluster_reservation_id eq $parent_reservation_id) {
+ $cluster_info_string .= "parent= ";
+ }
+ else {
+ $cluster_info_string .= "child= ";
+ }
+ $cluster_info_string .= "$cluster_computer_public_ip_address\n";
}
-
- if (open(CLUSTERFILE, ">$cluster_info")) {
- print CLUSTERFILE @cluster_string;
- close(CLUSTERFILE);
+
+ # Remove trailing newline
+ $cluster_info_string =~ s/\n$//;
+
+ # Create the cluster_info file on the computer
+ if ($self->create_text_file($cluster_info_file_path, $cluster_info_string)) {
+ notify($ERRORS{'DEBUG'}, 0, "created $cluster_info_file_path on $computer_short_name:\n$cluster_info_string");
+ $self->set_text_file_line_endings($cluster_info_file_path);
}
else {
- notify($ERRORS{'OK'}, 0, "could not write to $cluster_info");
+ notify($ERRORS{'WARNING'}, 0, "failed to create $cluster_info_file_path on $computer_short_name");
+ return;
}
-
- my $identity;
- #scp cluster file to each node
- my $targetpath;
- foreach my $resid (keys %{$request_data->{reservation}}) {
- $identity = $request_data->{reservation}{$resid}{image}{IDENTITY};
- my $node_name = $request_data->{reservation}{$resid}{computer}{SHORTNAME};
- if ($image_OS_type =~ /linux/i) {
- $targetpath = "$node_name:/etc/cluster_info";
- }
- elsif ($image_OS_type =~ /windows/i) {
- $targetpath = "$node_name:C:\/cluster_info";
+
+ # Open the firewall allowing other cluster reservations computers access
+ if ($self->can('enable_firewall_port')) {
+ my $firewall_scope = join(",", @public_ip_addresses);
+ notify($ERRORS{'DEBUG'}, 0, "attempting to open the firewall on $computer_short_name to allow access from other cluster reservation computers: $firewall_scope");
+
+ if (!$self->enable_firewall_port("tcp", "any", $firewall_scope, 0)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to open the firewall on $computer_short_name to allow access from other cluster reservation computers via TCP: $firewall_scope");
}
- else {
- $targetpath = "$node_name:/etc/cluster_info";
+
+ if (!$self->enable_firewall_port("udp", "any", $firewall_scope, 0)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to open the firewall on $computer_short_name to allow access from other cluster reservation computers via UDP: $firewall_scope");
}
+ }
- if (run_scp_command($cluster_info, $targetpath, $identity)) {
- notify($ERRORS{'OK'}, 0, " successfully copied cluster_info file to $node_name");
- }
- } ## end foreach my $resid (keys %{$request_data->{reservation...
+ return 1;
+} ## end sub update_cluster_info
- unlink $cluster_info;
+#/////////////////////////////////////////////////////////////////////////////
- return 1;
+=head2 get_cluster_info_file_path
-} ## end sub update_cluster_info
+ Parameters : none
+ Returns : string
+ Description : Returns the location where the cluster_info files resides on the
+ computer: /etc/cluster_info. OS modules such as Windows which use
+ a different location should override this subroutine.
+
+=cut
+
+sub get_cluster_info_file_path {
+ my $self = shift;
+ if (ref($self) !~ /VCL::Module::OS/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+ return;
+ }
+ return $self->{cluster_info_file_path} if $self->{cluster_info_file_path};
+ $self->{cluster_info_file_path} = '/etc/cluster_info';
+ notify($ERRORS{'DEBUG'}, 0, "determined cluster_info file path for " . ref($self) . " OS module: $self->{cluster_info_file_path}");
+ return $self->{cluster_info_file_path};
+}
#///////////////////////////////////////////////////////////////////////////
Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1658846&r1=1658845&r2=1658846&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Wed Feb 11 00:03:26 2015
@@ -4027,7 +4027,7 @@ sub get_service_configuration {
my $services_key = 'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services';
- my $cygwin_path = $self->get_cygwin_path();
+ my $cygwin_path = $self->get_cygwin_installation_directory_path();
my $node_reg_file_path = $cygwin_path . "/tmp/services_$computer_node_name.reg";
my $mn_reg_file_path = "/tmp/vcl/services_$computer_node_name.reg";
@@ -6731,7 +6731,11 @@ sub set_text_file_line_endings {
}
$line_ending = 'win' unless $line_ending;
- return $self->SUPER::set_text_file_line_endings($file_path, $line_ending);
+ # Convert the Windows-style path to a Cygwin/Unix-style path or else the sed command in OS.pm::set_text_file_line_endings will fail with this error:
+ # sed: couldn't open temporary file C:/sedxxxxxx: No such file or directory
+ my $unix_file_path = $self->get_cygwin_unix_file_path($file_path) || $file_path;
+
+ return $self->SUPER::set_text_file_line_endings($unix_file_path, $line_ending);
}
#/////////////////////////////////////////////////////////////////////////////
@@ -6952,7 +6956,7 @@ sub clean_hard_drive {
my $computer_node_name = $self->data->get_computer_node_name();
my $system32_path = $self->get_system32_path() || return;
- my $cygwin_path = $self->get_cygwin_path();
+ my $cygwin_path = $self->get_cygwin_installation_directory_path();
# Run dism.exe
# The dism.exe file may not be present
@@ -12026,15 +12030,17 @@ sub notify_user_console {
#/////////////////////////////////////////////////////////////////////////////
-=head2 get_cygwin_path
+=head2 get_cygwin_installation_directory_path
- Parameters :
- Returns : sets $self->{CYGWIN_PATH}
- Description : sets CYGWIN_PATH, x86 and x86_64 use different paths, need to detect which path to use.
+ Parameters : none
+ Returns : string
+ Description : Retrieves the directory path where Cygwin is installed on the
+ computer. 32-bit and 64-bit versions of Cygwin may use different
+ paths.
=cut
-sub get_cygwin_path {
+sub get_cygwin_installation_directory_path {
my $self = shift;
if (ref($self) !~ /Module/i) {
notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
@@ -12044,30 +12050,114 @@ sub get_cygwin_path {
return $self->{CYGWIN_PATH} if $self->{CYGWIN_PATH};
my $computer_node_name = $self->data->get_computer_node_name();
- my $command = "cygpath -d /";
-
- my ($exit_status, $output) = $self->execute($command, 1);
+ my $default_path = 'C:/cygwin';
+
+ my $command = "cygpath.exe -m /";
+ my ($exit_status, $output) = $self->execute($command, 1);
if (!defined($output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to delete files under command: $command");
- #return default path
- $self->{CYGWIN_PATH} = "C:/cygwin";
+ notify($ERRORS{'WARNING'}, 0, "failed to execute command to determine Cygwin installation directory path on $computer_node_name, returning default path: $default_path");
+ $self->{CYGWIN_PATH} = $default_path;
return $self->{CYGWIN_PATH};
}
- elsif (@$output) {
- $self->{CYGWIN_PATH} = @$output[0];
- #fix path
- $self->{CYGWIN_PATH} =~ tr/\\/\//;
- notify($ERRORS{'DEBUG'}, 0, "command: $command cygwin_path: $self->{CYGWIN_PATH}");
- if ($self->file_exists($self->{CYGWIN_PATH})) {
- notify($ERRORS{'DEBUG'}, 0, " $self->{CYGWIN_PATH} exists");
- }
+ elsif (grep(/^cygpath:/, @$output)) {
+ notify($ERRORS{'WARNING'}, 0, "error occurred determining Cygwin installation directory path on $computer_node_name, returning default path: $default_path, output:\n" . join("\n", @$output));
+ $self->{CYGWIN_PATH} = $default_path;
+ return $self->{CYGWIN_PATH};
+ }
+
+ my ($directory_path) = grep(/^[a-z]/i, @$output);
+ if ($directory_path) {
+ notify($ERRORS{'DEBUG'}, 0, "determined Cygwin installation directory path on $computer_node_name: $directory_path");
+ $self->{CYGWIN_PATH} = $directory_path;
+ return $self->{CYGWIN_PATH};
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "error occurred determining Cygwin installation directory path on $computer_node_name, returning default path: $default_path, did not find a line beginning with a letter in the output:\n" . join("\n", @$output));
+ $self->{CYGWIN_PATH} = $default_path;
return $self->{CYGWIN_PATH};
}
}
#/////////////////////////////////////////////////////////////////////////////
+=head2 get_cygwin_unix_file_path
+
+ Parameters : $file_path
+ Returns : string
+ Description : Converts a Windows-style path to a Cygwin/Unix-style path.
+ Example: C:\Windows\file.txt --> /cygdrive/c/Windows/file.txt
+
+=cut
+
+sub get_cygwin_unix_file_path {
+ my $self = shift;
+ if (ref($self) !~ /Module/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+ return;
+ }
+
+ my $file_path_argument = shift;
+ if (!$file_path_argument) {
+ notify($ERRORS{'WARNING'}, 0, "file path argument was not specified");
+ return;
+ }
+
+ if ($file_path_argument =~ /^\//) {
+ notify($ERRORS{'DEBUG'}, 0, "file path not converted because it begins with a forward slash: $file_path_argument");
+ return $file_path_argument;
+ }
+
+ # Change backslashes to forward slashes
+ $file_path_argument =~ s/\\+/\//g;
+
+ my $command = "cygpath.exe -u \"$file_path_argument\"";
+ my ($exit_status, $output) = $self->execute($command);
+ if (!defined($output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute command to determine Cygwin/Unix-style path, returning argument: $file_path_argument");
+ return $file_path_argument;
+ }
+
+ my ($unix_file_path) = grep(/^\//, @$output);
+ if (!$unix_file_path || grep(/^cygpath:/, @$output)) {
+ notify($ERRORS{'WARNING'}, 0, "error occurred attempting to determine Cygwin/Unix-style path, returning argument: $file_path_argument, output:\n" . join("\n", @$output));
+ return $file_path_argument;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "determined Cygwin/Unix-style path: $file_path_argument --> $unix_file_path");
+ return $unix_file_path;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_cluster_info_file_path
+
+ Parameters : none
+ Returns : string
+ Description : Returns the location where the cluster_info files resides on the
+ Windows computer, normally C:/cluster_info.
+
+=cut
+
+sub get_cluster_info_file_path {
+ 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;
+ }
+
+ return $self->{cluster_info_file_path} if $self->{cluster_info_file_path};
+
+ my $systemroot_value = $self->get_environment_variable_value('SYSTEMDRIVE') || 'C:';
+ $self->{cluster_info_file_path} = "$systemroot_value/cluster_info";
+ notify($ERRORS{'DEBUG'}, 0, "determined cluster_info file path for Windows: $self->{cluster_info_file_path}");
+ return $self->{cluster_info_file_path};
+}
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 disable_set_network_location_prompt
Parameters : none
@@ -12085,7 +12175,7 @@ sub disable_set_network_location_prompt
return;
}
- my $registry_key = 'HKLM\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff';
+ my $registry_key = 'HKLM\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff';
return $self->reg_add($registry_key);
}