Author: arkurth
Date: Wed Feb 1 18:20:13 2017
New Revision: 1781293
URL: http://svn.apache.org/viewvc?rev=1781293&view=rev
Log:
VCL-1000
Moved the code for the execution of scripts on the management node to
ManagementNode.pm because it's more appropriate. Updated calls in OS.pm to
$self->mn_os.
VCL-867
Added subroutines to OS.pm, used to configure static DNS servers for the Active
Directory code:
* get_dns_servers
* get_private_dns_servers
* get_public_dns_servers
Modified:
vcl/trunk/managementnode/lib/VCL/Module/OS.pm
vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.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=1781293&r1=1781292&r2=1781293&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Wed Feb 1 18:20:13 2017
@@ -60,26 +60,6 @@ use VCL::utils;
##############################################################################
-=head1 CLASS VARIABLES
-
-=cut
-
-=head2 $MN_STAGE_SCRIPTS_DIRECTORY
-
- Data type : String
- Description : Location on the management node where scripts reside which are
- executed on the management node at various stages of a
- reservation.
-
- Example:
- /usr/local/vcl/tools/mn_stage_scripts
-
-=cut
-
-our $MN_STAGE_SCRIPTS_DIRECTORY = "$TOOLS/mn_stage_scripts";
-
-##############################################################################
-
=head1 OBJECT METHODS
=cut
@@ -153,7 +133,7 @@ sub pre_capture {
# Run custom pre_capture scripts on the management node
my $enable_experimental_features =
get_variable('enable_experimental_features', 0);
if ($enable_experimental_features) {
- $self->run_management_node_stage_scripts('pre_capture');
+ $self->mn_os->run_management_node_stage_scripts('pre_capture');
}
# Run custom pre_capture scripts on the computer
@@ -186,7 +166,7 @@ sub post_capture {
# Run custom post_capture scripts on the management node
my $enable_experimental_features =
get_variable('enable_experimental_features', 0);
if ($enable_experimental_features) {
- $self->run_management_node_stage_scripts('post_capture');
+ $self->mn_os->run_management_node_stage_scripts('post_capture');
}
return 1;
@@ -2513,6 +2493,98 @@ sub get_public_default_gateway {
#/////////////////////////////////////////////////////////////////////////////
+=head2 get_dns_servers
+
+ Parameters : $network_type
+ Returns : array
+ Description : Retrieves a list of DNS servers currently configured on the
+ computer. The $network_type argument may either be 'private' or
+ 'public'. The default is to retrieve the DNS servers configured
+ for the public interface.
+
+=cut
+
+sub get_dns_servers {
+ 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;
+ }
+
+ # Check if a 'public' or 'private' network type argument was specified
+ # Assume 'public' if not specified
+ my $network_type = lc(shift()) || 'public';
+ if ($network_type && $network_type !~ /(public|private)/i) {
+ notify($ERRORS{'WARNING'}, 0, "network type argument can only
be 'public' or 'private'");
+ return;
+ }
+
+ # Get the public or private network configuration
+ # Use 'eval' to construct the appropriate subroutine name
+ my $network_configuration = eval
"\$self->get_$network_type\_network_configuration()";
+ if ($EVAL_ERROR || !$network_configuration) {
+ notify($ERRORS{'WARNING'}, 0, "unable to retrieve $network_type
network configuration");
+ return;
+ }
+
+ if (!defined($network_configuration->{dns_servers})) {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine
$network_type DNS servers, 'dns_servers' key does not exist in the network
configuration info: \n" . format_data($network_configuration));
+ return;
+ }
+ elsif (!ref($network_configuration->{dns_servers}) ||
ref($network_configuration->{dns_servers}) ne 'ARRAY') {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine
$network_type DNS servers, 'dns_servers' key is not an array reference in the
network configuration info: \n" . format_data($network_configuration));
+ return;
+ }
+
+ my @dns_servers = @{$network_configuration->{dns_servers}};
+ notify($ERRORS{'DEBUG'}, 0, "returning $network_type DNS servers: " .
join(", ", @dns_servers));
+ return @dns_servers;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_private_dns_servers
+
+ Parameters : none
+ Returns : array
+ Description : Retrieves a list of DNS servers currently configured for the
+ private interface on the computer.
+
+=cut
+
+sub get_private_dns_servers {
+ 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;
+ }
+
+ return $self->get_dns_servers('private');
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_public_dns_servers
+
+ Parameters : none
+ Returns : array
+ Description : Retrieves a list of DNS servers currently configured for the
+ public interface on the computer.
+
+=cut
+
+sub get_public_dns_servers {
+ 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;
+ }
+
+ return $self->get_dns_servers('public');
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 create_text_file
Parameters : $file_path, $file_contents, $append
@@ -3472,8 +3544,7 @@ sub process_connect_methods {
}
}
else {
- notify($ERRORS{'CRITICAL'}, 0, "NAT not
configured on $nathost_hostname, " . ref($self->nathost_os->firewall) . " does
not implement a 'configure_nat' subroutine");
- return;
+ notify($ERRORS{'DEBUG'}, 0, "NAT not configured
on $nathost_hostname, " . ref($self->nathost_os->firewall) . " does not
implement a 'configure_nat' subroutine");
}
}
else {
@@ -3488,8 +3559,7 @@ sub process_connect_methods {
}
}
else {
- notify($ERRORS{'CRITICAL'}, 0, "NAT not configured on
$nathost_hostname for this reservation, " . ref($self->nathost_os->firewall) .
" does not implement a 'configure_nat_reservation' subroutine");
- return;
+ notify($ERRORS{'DEBUG'}, 0, "NAT not configured on
$nathost_hostname for this reservation, " . ref($self->nathost_os->firewall) .
" does not implement a 'configure_nat_reservation' subroutine");
}
}
@@ -4332,111 +4402,6 @@ sub run_management_node_tools_scripts {
#/////////////////////////////////////////////////////////////////////////////
-=head2 run_management_node_stage_scripts
-
- Parameters : $stage
- Returns : boolean
- Description : Runs scripts on the management node intended for the state
- specified by the argument. This is useful if you need to
- configure something such as a storage unit or firewall device
- specifically for each reservation.
-
- The stage argument may be any of the
- following:
- -pre_capture
- -post_capture
- -post_load
- -post_reserve
- -post_initial_connection
- -post_reservation
-
- The scripts are stored on the management node under:
- /usr/local/vcl/tools/mn_stage_scripts
-
- No scripts exist by default. When the vcld process reaches the
- stage specified by the argument, it will check the subdirectory
- with a name that matches the stage name. For example:
- /usr/local/vcl/tools/mn_stage_scripts/post_capture
-
- It will attempt to execute any files under this directory.
-
- Prior to executing the scripts, a JSON file is created under
/tmp
- with information regarding the reservation. The actual file path
- will be:
- /tmp/<reservation ID>.json
-
- Information about the reservation can be retrieved within the
- script by simply using grep or using something to parse JSON
such
- as jsawk. Sample script:
-
- JSON_FILE="$1"
- echo "JSON file: ${JSON_FILE}"
- PRIVATE_IP=`cat ${JSON_FILE} | jsawk 'return
this.computer.privateIPaddress'`
- echo "computer private IP: ${PRIVATE_IP}"
-
-=cut
-
-sub run_management_node_stage_scripts {
- my $self = shift;
- if (ref($self) !~ /VCL::/i) {
- notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
- return;
- }
-
- # Get the stage argument
- my $stage = shift;
- if (!$stage) {
- notify($ERRORS{'WARNING'}, 0, "stage argument was not
supplied");
- return;
- }
- elsif ($stage !~
/(pre_capture|post_capture|post_load|post_reserve|post_initial_connection|post_reservation)/)
{
- notify($ERRORS{'WARNING'}, 0, "invalid stage argument was
supplied: $stage");
- return;
- }
-
- # Override the die handler
- local $SIG{__DIE__} = sub{};
-
- my $reservation_id = $self->data->get_reservation_id();
- my $management_node_short_name =
$self->data->get_management_node_short_name();
-
- my $scripts_directory_path = "$MN_STAGE_SCRIPTS_DIRECTORY/$stage";
- my @script_file_paths =
$self->mn_os->find_files($scripts_directory_path, '*');
- if (!@script_file_paths) {
- notify($ERRORS{'DEBUG'}, 0, "no files exist in directory:
$scripts_directory_path");
- return 1;
- }
-
- # Sort the files so they can be executed in a known order
- @script_file_paths = sort_by_file_name(@script_file_paths);
-
- my $script_count = scalar(@script_file_paths);
- notify($ERRORS{'DEBUG'}, 0, "found $script_count files under
$scripts_directory_path:\n" . join("\n", @script_file_paths));
-
- # Create a JSON file on the management node containing reservation info
- $self->create_management_node_reservation_info_json_file();
-
- my $mn_json_file_path =
$self->get_management_node_reservation_info_json_file_path();
-
- # Execute the scripts
- for my $script_file_path (@script_file_paths) {
- my $command = "chmod +x $script_file_path && $script_file_path
$mn_json_file_path";
- my ($exit_status, $output) = $self->mn_os->execute($command);
- if (!defined($output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to execute script
on management node: $command");
- return;
- }
- else {
- notify($ERRORS{'DEBUG'}, 0, "executed script on
management node $management_node_short_name, exit status: $exit_status,
command:\n$command\noutput:\n" . join("\n", @$output));
- }
- }
-
- #$self->delete_management_node_reservation_info_json_file();
- return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
=head2 get_connect_method_remote_ip_addresses
Parameters : none
@@ -4811,79 +4776,6 @@ sub delete_reservation_info_json_file {
return $self->delete_file($json_file_path);
}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_management_node_reservation_info_json_file_path
-
- Parameters : none
- Returns : string
- Description : Returns the location where the files resides on the management
- node that contains JSON formatted information about the
- reservation. For Linux computers, the location is:
- /tmp/<reservation ID>.json.
-
-=cut
-
-sub get_management_node_reservation_info_json_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;
- }
- my $reservation_id = $self->data->get_reservation_id();
- return "/tmp/$reservation_id.json";
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 create_management_node_reservation_info_json_file
-
- Parameters : none
- Returns : boolean
- Description : Creates a text file on the the management node containing
- reservation data in JSON format.
-
-=cut
-
-sub create_management_node_reservation_info_json_file {
- 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;
- }
-
- # Note: it would make sense to put this and the related subroutines in
ManagementNode.pm
- # However, this sub in particular needs to remain here or else the
information returned by get_reservation_info_json_string will be wrong
- # The DataStructure available in $self->mn_os gets altered. Computer
info is replaced with info for the management node.
-
- my $json_file_path =
$self->get_management_node_reservation_info_json_file_path();
- my $json_string = $self->data->get_reservation_info_json_string() ||
return;
- return $self->mn_os->create_text_file($json_file_path, $json_string);
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 delete_management_node_reservation_info_json_file
-
- Parameters : none
- Returns : boolean
- Description : Deletes the text file on the management node containing
- reservation data in JSON format.
-
-=cut
-
-sub delete_management_node_reservation_info_json_file {
- 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;
- }
-
- my $json_file_path =
$self->get_management_node_reservation_info_json_file_path();
- return $self->mn_os->delete_file($json_file_path);
-}
-
#///////////////////////////////////////////////////////////////////////////
1;
__END__
Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm?rev=1781293&r1=1781292&r2=1781293&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm Wed Feb
1 18:20:13 2017
@@ -57,6 +57,26 @@ use VCL::utils;
##############################################################################
+=head1 CLASS VARIABLES
+
+=cut
+
+=head2 $MN_STAGE_SCRIPTS_DIRECTORY
+
+ Data type : String
+ Description : Location on the management node where scripts reside which are
+ executed on the management node at various stages of a
+ reservation.
+
+ Example:
+ /usr/local/vcl/tools/mn_stage_scripts
+
+=cut
+
+our $MN_STAGE_SCRIPTS_DIRECTORY = "$TOOLS/mn_stage_scripts";
+
+##############################################################################
+
=head1 OBJECT METHODS
=cut
@@ -281,6 +301,183 @@ sub get_file_contents {
}
#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_management_node_reservation_info_json_file_path
+
+ Parameters : none
+ Returns : string
+ Description : Returns the location where the files resides on the management
+ node that contains JSON formatted information about the
+ reservation. For Linux computers, the location is:
+ /tmp/<reservation ID>.json.
+
+=cut
+
+sub get_management_node_reservation_info_json_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;
+ }
+ my $reservation_id = $self->data->get_reservation_id();
+ return "/tmp/$reservation_id.json";
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 create_management_node_reservation_info_json_file
+
+ Parameters : none
+ Returns : boolean
+ Description : Creates a text file on the the management node containing
+ reservation data in JSON format.
+
+=cut
+
+sub create_management_node_reservation_info_json_file {
+ 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;
+ }
+
+ my $json_file_path =
$self->get_management_node_reservation_info_json_file_path();
+
+ # IMPORTANT: Use $self->os->data here to retrieve DataStructure info
for the computer being loaded
+ # If $self->data->get_reservation_info_json_string is used, the
computer info will be that of the management node, not the computer being loaded
+ my $json_string = $self->os->data->get_reservation_info_json_string()
|| return;
+
+ return $self->create_text_file($json_file_path, $json_string);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_management_node_reservation_info_json_file
+
+ Parameters : none
+ Returns : boolean
+ Description : Deletes the text file on the management node containing
+ reservation data in JSON format.
+
+=cut
+
+sub delete_management_node_reservation_info_json_file {
+ 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;
+ }
+
+ my $json_file_path =
$self->get_management_node_reservation_info_json_file_path();
+ return $self->delete_file($json_file_path);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 run_management_node_stage_scripts
+
+ Parameters : $stage
+ Returns : boolean
+ Description : Runs scripts on the management node intended for the state
+ specified by the argument. This is useful if you need to
+ configure something such as a storage unit or firewall device
+ specifically for each reservation.
+
+ The stage argument may be any of the
+ following:
+ -pre_capture
+ -post_capture
+ -post_load
+ -post_reserve
+ -post_initial_connection
+ -post_reservation
+
+ The scripts are stored on the management node under:
+ /usr/local/vcl/tools/mn_stage_scripts
+
+ No scripts exist by default. When the vcld process reaches the
+ stage specified by the argument, it will check the subdirectory
+ with a name that matches the stage name. For example:
+ /usr/local/vcl/tools/mn_stage_scripts/post_capture
+
+ It will attempt to execute any files under this directory.
+
+ Prior to executing the scripts, a JSON file is created under
/tmp
+ with information regarding the reservation. The actual file path
+ will be:
+ /tmp/<reservation ID>.json
+
+ Information about the reservation can be retrieved within the
+ script by simply using grep or using something to parse JSON
such
+ as jsawk. Sample script:
+
+ JSON_FILE="$1"
+ echo "JSON file: ${JSON_FILE}"
+ PRIVATE_IP=`cat ${JSON_FILE} | jsawk 'return
this.computer.privateIPaddress'`
+ echo "computer private IP: ${PRIVATE_IP}"
+
+=cut
+
+sub run_management_node_stage_scripts {
+ my $self = shift;
+ if (ref($self) !~ /VCL::/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the stage argument
+ my $stage = shift;
+ if (!$stage) {
+ notify($ERRORS{'WARNING'}, 0, "stage argument was not
supplied");
+ return;
+ }
+ elsif ($stage !~
/(pre_capture|post_capture|post_load|post_reserve|post_initial_connection|post_reservation)/)
{
+ notify($ERRORS{'WARNING'}, 0, "invalid stage argument was
supplied: $stage");
+ return;
+ }
+
+ # Override the die handler
+ local $SIG{__DIE__} = sub{};
+
+ my $reservation_id = $self->data->get_reservation_id();
+ my $management_node_short_name =
$self->data->get_management_node_short_name();
+
+ my $scripts_directory_path = "$MN_STAGE_SCRIPTS_DIRECTORY/$stage";
+ my @script_file_paths = $self->find_files($scripts_directory_path, '*');
+ if (!@script_file_paths) {
+ notify($ERRORS{'DEBUG'}, 0, "no files exist in directory:
$scripts_directory_path");
+ return 1;
+ }
+
+ # Sort the files so they can be executed in a known order
+ @script_file_paths = sort_by_file_name(@script_file_paths);
+
+ my $script_count = scalar(@script_file_paths);
+ notify($ERRORS{'DEBUG'}, 0, "found $script_count files under
$scripts_directory_path:\n" . join("\n", @script_file_paths));
+
+ # Create a JSON file on the management node containing reservation info
+ $self->create_management_node_reservation_info_json_file();
+
+ my $mn_json_file_path =
$self->get_management_node_reservation_info_json_file_path();
+
+ # Execute the scripts
+ for my $script_file_path (@script_file_paths) {
+ my $command = "chmod +x $script_file_path && $script_file_path
$mn_json_file_path";
+ my ($exit_status, $output) = $self->execute($command);
+ if (!defined($output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute script
on management node: $command");
+ return;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "executed script on
management node $management_node_short_name, exit status: $exit_status,
command:\n$command\noutput:\n" . join("\n", @$output));
+ }
+ }
+
+ #$self->delete_management_node_reservation_info_json_file();
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
=head2 check_private_ip_addresses