Author: arkurth
Date: Tue Jun 28 18:20:50 2016
New Revision: 1750551
URL: http://svn.apache.org/viewvc?rev=1750551&view=rev
Log:
VCL-953
Added subroutines:
Module.pm::get_class_variable_hierarchy
utils.pm::wrap_string
Linux.pm::start_network_interface
Linux.pm::stop_network_interface
Linux.pm::delete_default_gateway
Linux.pm::set_default_gateway
Linux.pm::clear_file
Linux.pm::update_resolv_conf
Reworked Linux.pm::get_exclude_list. Added code to allow for * wildcards in the
list entries. Added:
Linux.pm::get_exclude_regex_list
Linux.pm::is_file_in_exclude_list
Rewrote Linux.pm::generate_exclude_list_sample to explain the wildcard feature.
It was also a mess.
Rewrote Ubuntu.pm::enable_dhcp and set_static_public_address. It was clobbering
the /etc/network/interfaces file if an image had been configured with anything
other that the default interface configuration such as setting up bridge.
Rewrote Linux.pm::clean_known_files. Added $CAPTURE_DELETE_FILE_PATHS and
$CAPTURE_CLEAR_FILE_PATHS class variables to Linux.pm and Ubuntu.pm. These are
array references which list files to clear or delete.
VCL-957
Added command to set the root password in Linux.pm::pre_capture. It's currently
using the $WINDOWS_ROOT_PASSWORD variable name but that's fine for now.
Other
Removed call to process_connect_methods from Linux.pm::pre_capture. It wasn't
doing anything other than generate warning messages.
Added optional $display_output argument to Linux.pm::file_exists. This is used
from Linux.pm::delete_file to reduce vcld.log messages.
Added command to delete /etc/ssh/external_sshd_config in
Linux.pm::delete_service when the ext_sshd service is deleted. This file was
getting left.
Removed useless/sloppy code in Ubuntu.pm::clean_iptables. Set this subroutine
to always return 1. All it had been doing was displaying a warning when it
detected the iptables service didn't exist.
Modified:
vcl/trunk/managementnode/lib/VCL/Module.pm
vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm
vcl/trunk/managementnode/lib/VCL/utils.pm
Modified: vcl/trunk/managementnode/lib/VCL/Module.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module.pm?rev=1750551&r1=1750550&r2=1750551&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module.pm Tue Jun 28 18:20:50 2016
@@ -1323,6 +1323,87 @@ sub get_package_hierarchy {
#/////////////////////////////////////////////////////////////////////////////
+=head2 get_class_variable_hierarchy
+
+ Parameters : $class_variable
+ Returns : array
+ Description : VCL objects inherit from multiple parent classes:
+ Ubuntu > Linux > OS > Module
+
+ This subroutine allows a class variable which is defined in
+ multiple parent class levels to be retrieved for each level. It
+ traverse the object's parent classes from highest to lowest and
+ return an array containing the value of the variable for each
+ level. For example,
+
+ Linux.pm defines this array reference:
+ our $CAPTURE_DELETE_FILE_PATHS = [
+ '/root/.ssh/id_rsa',
+ '/root/.ssh/id_rsa.pub',
+ '/etc/udev/rules.d/70-persistent-net.rules',
+ ];
+
+ Ubuntu.pm defines this array reference with the same name:
+ our $CAPTURE_DELETE_FILE_PATHS = [
+ '/etc/network/interfaces.20*',
+ ];
+
+
$self->os->get_class_variable_hierarchy('CAPTURE_DELETE_FILE_PATHS') =
+ (
+ [
+ "/root/.ssh/id_rsa",
+ "/root/.ssh/id_rsa.pub",
+ "/etc/udev/rules.d/70-persistent-net.rules"
+ ],
+ [
+ "/etc/network/interfaces.20*"
+ ]
+ )
+
+=cut
+
+sub get_class_variable_hierarchy {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called
as a VCL module object method");
+ return;
+ }
+
+ my $class_variable_name = shift;
+ if (!defined($class_variable_name)) {
+ notify($ERRORS{'WARNING'}, 0, "class variable name argument was
not supplied");
+ return;
+ }
+
+ # Get an array containing the names of the Perl packages the OS object
is a class of
+ my @package_hierarchy = $self->get_package_hierarchy();
+
+ # Loop through each classes, retrieve any which have a matching
variable defined
+ my @values = ();
+ for my $package_name (@package_hierarchy) {
+ my $value = eval '$' . $package_name . "::$class_variable_name";
+ if ($EVAL_ERROR) {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine
value of \$$class_variable_name for $package_name, error:\n$EVAL_ERROR");
+ next;
+ }
+ elsif (!$value) {
+ notify($ERRORS{'DEBUG'}, 0, "\$$class_variable_name is
not defined for $package_name");
+ next;
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "\$$class_variable_name for
$package_name: " . format_data($value));
+
+ # Add the value to the return array
+ # Use unshift to add to the beginning to the array
+ unshift @values, $value;
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "retrieved class variable hierarchy for
'$class_variable_name':\n" . format_data(\@values));
+ return @values;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 code_loop_timeout
Parameters : 1: code reference
Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1750551&r1=1750550&r2=1750551&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Tue Jun 28 18:20:50 2016
@@ -90,6 +90,41 @@ our $SOURCE_CONFIGURATION_DIRECTORY = "$
our $NODE_CONFIGURATION_DIRECTORY = '/root/VCL';
+=head2 $CAPTURE_DELETE_FILE_PATHS
+
+ Data type : Array
+ Description : List of files to be deleted during the image capture process.
+
+=cut
+
+our $CAPTURE_DELETE_FILE_PATHS = [
+ '/root/.ssh/id_rsa',
+ '/root/.ssh/id_rsa.pub',
+ '/etc/sysconfig/iptables*old*',
+ '/etc/sysconfig/iptables_pre*',
+ '/etc/udev/rules.d/70-persistent-net.rules',
+ '/var/log/*.0',
+ '/var/log/*.gz',
+];
+
+=head2 $CAPTURE_CLEAR_FILE_PATHS
+
+ Data type : Array
+ Description : List of files to be cleared during the image capture process.
+
+=cut
+
+our $CAPTURE_CLEAR_FILE_PATHS = [
+ '/etc/hostname',
+ '/var/log/auth.log*',
+ '/var/log/boot.log*',
+ '/var/log/lastlog',
+ '/var/log/messages',
+ '/var/log/secure',
+ '/var/log/udev',
+ '/var/log/wtmp',
+];
+
#/////////////////////////////////////////////////////////////////////////////
=head2 get_node_configuration_directory
@@ -336,11 +371,8 @@ sub pre_capture {
notify($ERRORS{'OK'}, 0, "beginning Linux-specific image capture
preparation tasks");
- if (!$self->file_exists("/root/.vclcontrol/vcl_exclude_list.sample")) {
- notify($ERRORS{'DEBUG'}, 0,
"/root/.vclcontrol/vcl_exclude_list.sample does not exists");
- if (!$self->generate_vclcontrol_sample_files()) {
- notify($ERRORS{'DEBUG'}, 0, "could not create
/root/.vclcontrol/vcl_exclude_list.sample");
- }
+ if (!$self->generate_exclude_list_sample()) {
+ notify($ERRORS{'DEBUG'}, 0, "could not create
/root/.vclcontrol/vcl_exclude_list.sample");
}
# Force user off computer
@@ -353,6 +385,10 @@ sub pre_capture {
notify($ERRORS{'OK'}, 0, "deleted user from
$computer_node_name");
}
+ # Attempt to set the root password to a known value
+ # This is useful for troubleshooting image problems
+ $self->set_password("root", $WINDOWS_ROOT_PASSWORD);
+
if (!$self->configure_default_sshd()) {
return;
}
@@ -361,11 +397,6 @@ sub pre_capture {
return;
}
- # Clean up connection methods
- if ($self->process_connect_methods("any", 1)) {
- notify($ERRORS{'OK'}, 0, "processed connection methods on
$computer_node_name");
- }
-
if (!$self->clean_iptables()) {
return;
}
@@ -420,7 +451,7 @@ sub post_load {
notify($ERRORS{'OK'}, 0, "beginning Linux post_load tasks, image:
$image_name, computer: $computer_node_name");
# Wait for computer to respond to SSH
- if (!$self->wait_for_response(5, 600, 10)) {
+ if (!$self->wait_for_response(5, 600, 5)) {
notify($ERRORS{'WARNING'}, 0, "$computer_node_name never
responded to SSH");
return;
}
@@ -1000,10 +1031,106 @@ EOF
#/////////////////////////////////////////////////////////////////////////////
+=head2 start_network_interface
+
+ Parameters : $interface_name
+ Returns : boolean
+ Description : Calls ifup on the network interface.
+
+=cut
+
+sub start_network_interface {
+ my $self = shift;
+ if (ref($self) !~ /linux/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return 0;
+ }
+
+ my $interface_name = shift;
+ if (!$interface_name) {
+ notify($ERRORS{'WARNING'}, 0, "unable to start network
interface, interface name argument was not supplied");
+ return;
+ }
+
+ my $computer_name = $self->data->get_computer_short_name();
+
+ notify($ERRORS{'DEBUG'}, 0, "attempting to start network interface
$interface_name on $computer_name");
+
+ my $command = "/sbin/ifup $interface_name";
+ my ($exit_status, $output) = $self->execute($command);
+ if (!defined($output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute command to
start $interface_name interface on $computer_name");
+ return;
+ }
+ elsif (grep(/already configured/i, @$output)) {
+ notify($ERRORS{'DEBUG'}, 0, "$interface_name interface on
$computer_name is already started, output:\n" . join("\n", @$output));
+ return 1;
+ }
+ elsif ($exit_status) {
+ notify($ERRORS{'WARNING'}, 0, "failed to start $interface_name
interface on $computer_name, exit status: $exit_status, command: '$command',
output:\n" . join("\n", @$output));
+ return;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "started $interface_name interface
on $computer_name, output:\n" . join("\n", @$output));
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 stop_network_interface
+
+ Parameters : $interface_name
+ Returns : boolean
+ Description : Calls ifdown on the network interface.
+
+=cut
+
+sub stop_network_interface {
+ my $self = shift;
+ if (ref($self) !~ /linux/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return 0;
+ }
+
+ my $interface_name = shift;
+ if (!$interface_name) {
+ notify($ERRORS{'WARNING'}, 0, "unable to stop network
interface, interface name argument was not supplied");
+ return;
+ }
+
+ my $computer_name = $self->data->get_computer_short_name();
+
+ notify($ERRORS{'DEBUG'}, 0, "attempting to stop network interface
$interface_name on $computer_name");
+
+ my $command = "/sbin/ifdown $interface_name";
+ my ($exit_status, $output) = $self->execute($command);
+ if (!defined($output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute command to
stop $interface_name interface on $computer_name");
+ return;
+ }
+ elsif (grep(/not configured/i, @$output)) {
+ notify($ERRORS{'DEBUG'}, 0, "$interface_name interface on
$computer_name is already stopped, output:\n" . join("\n", @$output));
+ return 1;
+ }
+ elsif ($exit_status) {
+ notify($ERRORS{'WARNING'}, 0, "failed to stop $interface_name
interface on $computer_name, exit status: $exit_status, command: '$command',
output:\n" . join("\n", @$output));
+ return;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "stopped $interface_name interface
on $computer_name, output:\n" . join("\n", @$output));
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 restart_network_interface
Parameters : $interface_name
- Returns :
+ Returns : boolean
Description : Calls ifdown and then ifup on the network interface.
=cut
@@ -1021,23 +1148,116 @@ sub restart_network_interface {
return;
}
- my $computer_name = $self->data->get_computer_short_name();
- my $network_scripts_path = "/etc/sysconfig/network-scripts";
+ my $computer_name = $self->data->get_computer_short_name();
- # Restart the interface
notify($ERRORS{'DEBUG'}, 0, "attempting to restart network interface
$interface_name on $computer_name");
- my $interface_restart_command = "$network_scripts_path/ifdown
$interface_name ; $network_scripts_path/ifup $interface_name";
- my ($interface_restart_exit_status, $interface_restart_output) =
$self->execute($interface_restart_command);
- if (!defined($interface_restart_output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to run command to restart
interface $interface_name on $computer_name: '$interface_restart_command'");
+
+ my $command = "/sbin/ifdown $interface_name ; /sbin/ifup
$interface_name";
+ my ($exit_status, $output) = $self->execute($command);
+ if (!defined($output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute command to
restart $interface_name interface on $computer_name");
+ return;
+ }
+ elsif ($exit_status) {
+ notify($ERRORS{'WARNING'}, 0, "failed to restart
$interface_name interface on $computer_name, exit status: $exit_status,
command: '$command', output:\n" . join("\n", @$output));
+ return;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "restarted $interface_name
interface on $computer_name");
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_default_gateway
+
+ Parameters : none
+ Returns : boolean
+ Description : Deletes the existing default gateway from the routing table.
+
+=cut
+
+sub delete_default_gateway {
+ my $self = shift;
+ if (ref($self) !~ /linux/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return 0;
+ }
+
+ my $computer_name = $self->data->get_computer_short_name();
+
+ my $command = "/sbin/route del default";
+ my ($exit_status, $output) = $self->execute($command);
+ if (!defined($output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute command to
delete default gateway on $computer_name: $command");
+ return;
+ }
+ elsif (grep(/No such process/i, @$output)) {
+ notify($ERRORS{'DEBUG'}, 0, "default gateway not set on
$computer_name");
+ }
+ elsif ($exit_status ne '0') {
+ notify($ERRORS{'WARNING'}, 0, "failed to delete default gateway
on $computer_name, exit status: $exit_status, command:\n$command\noutput:\n" .
join("\n", @$output));
+ return 0;
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "deleted default gateway on
$computer_name");
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 set_default_gateway
+
+ Parameters : $default_gateway, $interface_name (optional)
+ Returns : boolean
+ Description : Sets the default route. If no interface argument is supplied,
the
+ public interface is used.
+
+=cut
+
+sub set_default_gateway {
+ my $self = shift;
+ if (ref($self) !~ /linux/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return 0;
+ }
+
+ my $default_gateway = shift;
+ if (!defined($default_gateway)) {
+ notify($ERRORS{'WARNING'}, 0, "default gateway argument not
supplied");
return;
}
- elsif ($interface_restart_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to restart network
interface $interface_name on $computer_name, exit status:
$interface_restart_exit_status, command: '$interface_restart_command',
output:\n" . join("\n", @$interface_restart_output));
+
+ my $computer_name = $self->data->get_computer_short_name();
+
+ my $interface_name = shift;
+ if (!defined($interface_name)) {
+ $interface_name = $self->get_public_interface_name();
+ if (!$interface_name) {
+ notify($ERRORS{'WARNING'}, 0, "unable to set static
default gateway on $computer_name, interface name argument was not supplied and
public interface name could not be determined");
+ return;
+ }
+ }
+
+ # Delete existing default gateway or else error will occur: SIOCADDRT:
File exists
+ $self->delete_default_gateway();
+
+ my $command = "/sbin/route add default gw $default_gateway metric 0
$interface_name";
+ my ($exit_status, $output) = $self->execute($command);
+ if (!defined($output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute command to set
default gateway on $computer_name: $command");
return;
}
+ elsif ($exit_status ne '0') {
+ notify($ERRORS{'WARNING'}, 0, "failed to set default gateway on
$computer_name to $default_gateway, interface: $interface_name, exit status:
$exit_status, command:\n$command\noutput:\n" . join("\n", @$output));
+ return 0;
+ }
else {
- notify($ERRORS{'DEBUG'}, 0, "restarted network interface
$interface_name on $computer_name");
+ notify($ERRORS{'OK'}, 0, "set default gateway on $computer_name
to $default_gateway, interface: $interface_name");
}
return 1;
@@ -1548,7 +1768,7 @@ sub run_script {
=head2 file_exists
- Parameters : $path
+ Parameters : $file_path, $display_output (optional)
Returns : boolean
Description : Checks if a file or directory exists on the Linux computer.
@@ -1562,17 +1782,22 @@ sub file_exists {
}
# Get the path from the subroutine arguments and make sure it was passed
- my $path = shift;
- if (!$path) {
+ my $file_path = shift;
+ if (!$file_path) {
notify($ERRORS{'WARNING'}, 0, "path argument was not
specified");
return 0;
}
+ my $display_output = shift;
+ if (!defined($display_output)) {
+ $display_output = 1;
+ }
+
# Remove any quotes from the beginning and end of the path
- $path = normalize_file_path($path);
+ $file_path = normalize_file_path($file_path);
# Escape all spaces in the path
- my $escaped_path = escape_file_path($path);
+ my $escaped_path = escape_file_path($file_path);
my $computer_short_name = $self->data->get_computer_short_name();
@@ -1581,15 +1806,15 @@ sub file_exists {
my $command = "stat $escaped_path";
my ($exit_status, $output) = $self->execute($command, 0);
if (!defined($output)) {
- notify($ERRORS{'DEBUG'}, 0, "failed to run command to determine
if file or directory exists on $computer_short_name:\npath: '$path'\ncommand:
'$command'");
+ notify($ERRORS{'DEBUG'}, 0, "failed to run command to determine
if file or directory exists on $computer_short_name:\npath:
'$file_path'\ncommand: '$command'");
return 0;
}
elsif (grep(/no such file/i, @$output)) {
- #notify($ERRORS{'DEBUG'}, 0, "file or directory does not exist
on $computer_short_name: '$path'");
+ notify($ERRORS{'DEBUG'}, 0, "file or directory does not exist
on $computer_short_name: '$file_path'") if $display_output;
return 0;
}
elsif (grep(/stat: /i, @$output)) {
- notify($ERRORS{'DEBUG'}, 0, "failed to determine if file or
directory exists on $computer_short_name:\npath: '$path'\ncommand:
'$command'\nexit status: $exit_status, output:\n" . join("\n", @$output));
+ notify($ERRORS{'DEBUG'}, 0, "failed to determine if file or
directory exists on $computer_short_name:\npath: '$file_path'\ncommand:
'$command'\nexit status: $exit_status, output:\n" . join("\n", @$output));
return 0;
}
@@ -1599,11 +1824,11 @@ sub file_exists {
my $links_found = grep(/^\s*Size:.*link$/i, @$output);
if ($files_found || $directories_found || $links_found) {
- notify($ERRORS{'DEBUG'}, 0, "'$path' exists on
$computer_short_name, files: $files_found, directories: $directories_found,
links: $links_found");
+ notify($ERRORS{'DEBUG'}, 0, "'$file_path' exists on
$computer_short_name, files: $files_found, directories: $directories_found,
links: $links_found") if $display_output;
return 1;
}
else {
- notify($ERRORS{'DEBUG'}, 0, "unexpected output returned while
attempting to determine if file or directory exists on $computer_short_name:
'$path'\ncommand: '$command'\nexit status: $exit_status, output:\n" .
join("\n", @$output));
+ notify($ERRORS{'DEBUG'}, 0, "unexpected output returned while
attempting to determine if file or directory exists on $computer_short_name:
'$file_path'\ncommand: '$command'\nexit status: $exit_status, output:\n" .
join("\n", @$output));
return 0;
}
}
@@ -1658,7 +1883,7 @@ sub delete_file {
}
# Make sure the path does not exist
- my $file_exists = $self->file_exists($path);
+ my $file_exists = $self->file_exists($path, 0);
if (!defined($file_exists)) {
notify($ERRORS{'WARNING'}, 0, "failed to confirm file doesn't
exist on $computer_short_name: '$path'");
return;
@@ -1675,6 +1900,63 @@ sub delete_file {
#/////////////////////////////////////////////////////////////////////////////
+=head2 clear_file
+
+ Parameters : $file_path
+ Returns : boolean
+ Description : Clears a file on the computer via 'cat /dev/null'. If the file
+ doesn't exist it is not created and true is returned.
+
+=cut
+
+sub clear_file {
+ 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;
+ }
+
+ # Get the path argument
+ my $file_path = shift;
+ if (!$file_path) {
+ notify($ERRORS{'WARNING'}, 0, "file path argument was not
specified");
+ return;
+ }
+
+ my $computer_short_name = $self->data->get_computer_short_name();
+
+ # Check if the file exists
+ if (!$self->file_exists($file_path, 0)) {
+ notify($ERRORS{'DEBUG'}, 0, "file not cleared on
$computer_short_name because it doesn't exist: $file_path");
+ return 1;
+ }
+
+ # Remove any quotes from the beginning and end of the path
+ $file_path = normalize_file_path($file_path);
+
+ # Escape all spaces in the path
+ my $escaped_file_path = escape_file_path($file_path);
+
+ # Clear the file
+ my $command = "cat /dev/null > $escaped_file_path";
+ my ($exit_status, $output) = $self->execute($command);
+ if (!defined($output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to execute command to
clear file on $computer_short_name: '$file_path'");
+ return;
+ }
+ elsif ($exit_status ne 0) {
+ notify($ERRORS{'WARNING'}, 0, "error occurred attempting to
clear file on $computer_short_name: '$file_path', exit status: $exit_status,
command: '$command', output:\n" . join("\n", @$output));
+ return;
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "cleared file on $computer_short_name:
'$file_path'");
+ }
+
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 create_directory
Parameters : $directory_path, $mode (optional)
@@ -3463,12 +3745,18 @@ sub delete_service {
my $init_module = ($self->get_init_modules())[$init_module_index];
if ($init_module->delete_service($service_name)) {
# Delete the cached service name array
+ delete $self->{service_init_module}{$service_name};
delete $init_module->{service_names};
}
else {
return;
}
+ # Delete external_sshd_config if deleting the ext_sshd service
+ if ($service_name =~ /ext_ssh/) {
+ $self->delete_file('/etc/ssh/external_sshd_config');
+ }
+
return 1;
}
@@ -4088,8 +4376,10 @@ sub save_firewall_configuration {
=head2 get_exclude_list
Parameters : none
- Returns : array, empty or contents of exclude list
- Description :
+ Returns : array
+ Description : Retrieves /root/.vclcontrol/vcl_exclude_list from the computer
+ and constructs an array. Blank lines are ommitted. Spaces at the
+ beginning or end of lines are removed.
=cut
@@ -4100,86 +4390,197 @@ sub get_exclude_list {
return;
}
- my $computer_node_name = $self->data->get_computer_node_name();
+ my $computer_name = $self->data->get_computer_node_name();
- # Does /etc/vcl_exclude_list exists
- my $filename = "/root/.vclcontrol/vcl_exclude_list";
- if (!$self->file_exists($filename)) {
- return;
+ # Check if previously retrieved
+ if (defined($self->{exclude_list_lines})) {
+ #notify($ERRORS{'DEBUG'}, 0, "returning previously retrieved
exclude list from $computer_name:\n" . join("\n",
@{$self->{exclude_list_lines}}));
+ return @{$self->{exclude_list_lines}};
}
- # Get the list
- my $command = "cat $filename";
- my ($status, $output) = $self->execute($command);
+ my $exclude_file_path = "/root/.vclcontrol/vcl_exclude_list";
- if (!defined($output)) {
- notify($ERRORS{'DEBUG'}, 0, "empty exclude_list from
$computer_node_name");
- return;
+ if (!$self->file_exists($exclude_file_path)) {
+ $self->{exclude_list_lines} = [];
+ return ();
}
- return @$output;
-
+ # Retrieve the contents of vcl_exclude_list
+ my @exclude_lines = $self->get_file_contents($exclude_file_path);
+
+ # Check for blank lines and other problems
+ my @exclude_lines_cleaned;
+ my $exclude_lines_cleaned_string = '';
+ for my $exclude_line (@exclude_lines) {
+ # Ignore blank lines
+ if ($exclude_line !~ /\w/) {
+ next;
+ }
+
+ # Remove leading and trailing spaces
+ $exclude_line =~ s/(^\s+|\s+$)//g;
+
+ push @exclude_lines_cleaned, $exclude_line;
+ $exclude_lines_cleaned_string .= "'$exclude_line'\n";
+ }
+
+ $self->{exclude_list_lines} = \@exclude_lines_cleaned;
+
+ notify($ERRORS{'DEBUG'}, 0, "retrieved and parsed $exclude_file_path on
$computer_name:\n$exclude_lines_cleaned_string");
+ return @exclude_lines_cleaned;
}
#/////////////////////////////////////////////////////////////////////////////
-=head2 generate_exclude_list_sample
+=head2 get_exclude_regex_list
Parameters : none
- Returns :boolean
- Description : Generates sample exclude list for users to assist in customizing
-
+ Returns : array
+ Description : Assembles a regular expression string based on the contents of
+ each line in /root/.vclcontrol/vcl_exclude_list on the computer.
+ If the file doesn't exist or is empty, an empty array is
+ returned.
+
=cut
-sub generate_vclcontrol_sample_files {
-
+sub get_exclude_regex_list {
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 $request_id = $self->data->get_request_id();
- my $management_node_keys = $self->data->get_management_node_keys();
- my $computer_short_name = $self->data->get_computer_short_name();
- my $computer_node_name = $self->data->get_computer_node_name();
-
- my @array2print;
+ my $computer_name = $self->data->get_computer_node_name();
- push(@array2print, '#' . "\n");
- push(@array2print, '# /root/.vclcontrol/vcl_exclude_list' . "\n");
- push(@array2print, '# List any files here that vcld should exclude
updating during the capture process' . "\n");
- push(@array2print, "# Format is one file per line including the full
path name" . "\n");
- push(@array2print, "\n");
+ # Check if previously retrieved
+ if (defined($self->{exclude_regex_list})) {
+ #notify($ERRORS{'DEBUG'}, 0, "returning previously retrieved
exclude list regex from $computer_name:\n" . join("\n",
@{$self->{exclude_regex_list}}));
+ return @{$self->{exclude_regex_list}};
+ }
- # write to tmpfile
- my $tmpfile = "/tmp/$request_id.vcl_exclude_list.sample";
- if (open(TMP, ">$tmpfile")) {
- print TMP @array2print;
- close(TMP);
+ # Retrieve exclude_list
+ my @exclude_files = $self->get_exclude_list();
+ if (!@exclude_files) {
+ $self->{exclude_regex_list} = [];
+ return ();
}
- else {
- #print "could not write $tmpfile $!\n";
- notify($ERRORS{'OK'}, 0, "could not write $tmpfile $!");
- return 0;
+
+ my @exclude_regex_list;
+ my $exclude_regex_list_string;
+ for my $exclude_file (@exclude_files) {
+ my $exclude_regex = $exclude_file;
+
+ # Add ^ to the beginning, remove any leading spaces
+ $exclude_regex =~ s/^[\s\^]*/\^/g;
+
+ # Add $ to the end, remove any trailing spaces
+ $exclude_regex =~ s/[\s\$]*$/\$/g;
+
+ # Escape forward slashes and periods
+ $exclude_regex =~ s/\\*([\/\.])/\\$1/g;
+
+ # Change asterisk to regex: * --> .*
+ $exclude_regex =~ s/\*+/\.\*/g;
+
+ push @exclude_regex_list, $exclude_regex;
+ $exclude_regex_list_string .= $exclude_regex . "\n";
}
+ chop($exclude_regex_list_string);
- # Make directory
- my $mkdir = "mkdir /root/.vclcontrol";
+ $self->{exclude_regex_list} = \@exclude_regex_list;
- if ($self->execute($mkdir)) {
- notify($ERRORS{'DEBUG'}, 0, "created /root/.vclcontrol
directory");
+ notify($ERRORS{'DEBUG'}, 0, "assembled regex list from
vcl_exclude_list:\n$exclude_regex_list_string");
+ return @exclude_regex_list;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 is_file_in_exclude_list
+
+ Parameters : $file_path
+ Returns : boolean
+ Description : Checks if the file matches any lines in
+ /root/.vclcontrol/vcl_exclude_list on the computer. If it
+ matches, true is returned meaning the file should not be
altered.
+
+
+=cut
+
+sub is_file_in_exclude_list {
+ 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;
}
- # copy to node
- if (run_scp_command($tmpfile,
"$computer_node_name:/root/.vclcontrol/vcl_exclude_list.sample",
$management_node_keys)) {
+ my $file_path = shift;
+ if (!$file_path) {
+ notify($ERRORS{'WARNING'}, 0, "file path argument was not
specified");
+ return;
}
- else {
- return 0;
+
+ my @exclude_regex_list = $self->get_exclude_regex_list();
+ return 0 unless @exclude_regex_list;
+
+ for my $exclude_regex (@exclude_regex_list) {
+ if ($file_path =~ /$exclude_regex/i) {
+ my $match = $1;
+ notify($ERRORS{'DEBUG'}, 0, "file matches line in
vcl_exclude_list:\nfile path: $file_path\nmatching regex: $exclude_regex");
+ return 1;
+ }
}
- return 1;
+ #notify($ERRORS{'DEBUG'}, 0, "file does NOT match any lines in
vcl_exclude_list: $file_path");
+ return 0;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+=head2 generate_exclude_list_sample
+
+ Parameters : none
+ Returns : boolean
+ Description : Generates /root/.vclcontrol/vcl_exclude_list.sample to help
image
+ creators utilize the file.
+
+=cut
+
+sub generate_exclude_list_sample {
+
+ 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 $exclude_file_name = "vcl_exclude_list";
+ my $exclude_file_path = "/root/.vclcontrol/$exclude_file_name";
+ my $sample_file_path = "/root/.vclcontrol/$exclude_file_name.sample";
+
+ my $sample_file_contents = <<"EOF";
+When creating an image, you may create a $exclude_file_path file to prevent
VCL from altering certain files during the image capture or load processes.
Files listed within $exclude_file_name will not be altered. The
$exclude_file_name file does not exist by default. You must create it if you
wish to utilize this feature. You can specify full, exact file paths or use
asterisk characters as wildcards within $exclude_file_name.
+
+Examples:
+/root/.ssh/id_rsa
+This would only match the file with the exact path:
+/root/.ssh/id_rsa
+
+/root/.ssh/id_rsa*
+This would match all files in the '/root/.ssh' directory with names beginning
with 'id_rsa' including:
+/root/.ssh/id_rsa
+/root/.ssh/id_rsa.pub
+
+/root/.ssh/id_rsa.*
+This would match all files in the '/root/.ssh' directory with names beginning
with 'id_rsa.' (including the period) including:
+/root/.ssh/id_rsa.pub
+
+In the previous example, '/root/.ssh/id_rsa' would not match because it does
not contain a period after 'id_rsa'.
+EOF
+
+ # Format the string and add comment characters to the beginning of each
line
+ $sample_file_contents = wrap_string($sample_file_contents, 80, '# ');
+
+ return $self->create_text_file($sample_file_path,
$sample_file_contents);
}
#/////////////////////////////////////////////////////////////////////////////
@@ -4605,65 +5006,54 @@ sub get_logged_in_users {
=head2 clean_known_files
- Parameters :
- Returns : 1
- Description : Removes or overwrites known files that are not excluded.
+ Parameters : none
+ Returns : boolean
+ Description : Clears and deletes files defined for the Linux OS module in the
+ $CAPTURE_CLEAR_FILE_PATHS and $CAPTURE_DELETE_FILE_PATHS class
+ variables.
=cut
sub clean_known_files {
my $self = shift;
- if (ref($self) !~ /linux/i) {
+ if (ref($self) !~ /Linux/i) {
notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
return;
- }
+ }
- my $computer_node_name = $self->data->get_computer_node_name();
+ my $error_count = 0;
- # Try to clear /tmp
- if ($self->execute("/usr/sbin/tmpwatch -f 0 /tmp; /bin/cp /dev/null
/var/log/wtmp")) {
- notify($ERRORS{'DEBUG'}, 0, "cleared /tmp on
$computer_node_name");
- }
-
- # Clear /etc/hostname file
- if($self->file_exists("/etc/hostname")) {
- if ($self->execute("/bin/cp /dev/null /etc/hostname")) {
- notify($ERRORS{'DEBUG'}, 0, "cleared /etc/hostname on
$computer_node_name");
+ # Clear files
+ my @class_clear_file_path_array_refs =
$self->get_class_variable_hierarchy('CAPTURE_CLEAR_FILE_PATHS');
+ for my $class_clear_file_path_array_ref
(@class_clear_file_path_array_refs) {
+ for my $file_path (@$class_clear_file_path_array_ref) {
+ if ($self->is_file_in_exclude_list($file_path)) {
+ notify($ERRORS{'DEBUG'}, 0, "file not cleared
because it is in the exclude list: $file_path");
+ next;
+ }
+ $self->clear_file($file_path) || $error_count++;
}
}
- # Clear SSH idenity keys from /root/.ssh
- if (!$self->clear_private_keys()) {
- notify($ERRORS{'WARNING'}, 0, "unable to clear known identity
keys");
- }
-
- # Fetch exclude_list
- my @exclude_list = $self->get_exclude_list();
-
- if (@exclude_list) {
- notify($ERRORS{'DEBUG'}, 0, "skipping files listed in
exclude_list\n" . join("\n", @exclude_list));
- }
-
- # Remove files
- if (!(grep(/70-persistent-net.rules/, @exclude_list))) {
- if
(!$self->delete_file("/etc/udev/rules.d/70-persistent-net.rules")) {
- notify($ERRORS{'WARNING'}, 0, "unable to remove
/etc/udev/rules.d/70-persistent-net.rules");
+ # Delete files
+ my @class_delete_file_path_array_refs =
$self->get_class_variable_hierarchy('CAPTURE_DELETE_FILE_PATHS');
+ for my $class_delete_file_path_array_ref
(@class_delete_file_path_array_refs) {
+ for my $file_path (@$class_delete_file_path_array_ref) {
+ if ($self->is_file_in_exclude_list($file_path)) {
+ notify($ERRORS{'DEBUG'}, 0, "file not deleted
because it is in the exclude list: $file_path");
+ next;
+ }
+ $self->delete_file($file_path) || $error_count++;
}
}
- if (!(grep(/\/var\/log\/secure/, @exclude_list))) {
- if (!$self->delete_file("/var/log/secure")) {
- notify($ERRORS{'WARNING'}, 0, "unable to remove
/var/log/secure");
- }
+ if ($error_count) {
+ notify($ERRORS{'WARNING'}, 0, "encountered $error_count error"
. ($error_count > 1 ? 's' : '') . " clearing and deleting files");
+ return;
}
-
- if (!(grep(/\/var\/log\/messages/, @exclude_list))) {
- if (!$self->delete_file("/var/log/messages")) {
- notify($ERRORS{'WARNING'}, 0, "unable to remove
/var/log/secure");
- }
+ else {
+ return 1;
}
-
- return 1;
}
#/////////////////////////////////////////////////////////////////////////////
@@ -5054,12 +5444,12 @@ sub configure_ext_sshd {
my $init_module = ($self->get_init_modules())[$init_module_index];
+ # Delete the cached service name array
+ delete $init_module->{service_names};
+ delete $self->{service_init_module}{ext_sshd};
+
# Add the ext_sshd service
- if ($init_module->add_ext_sshd_service()) {
- # Delete the cached service name array
- delete $init_module->{service_names};
- }
- else {
+ if (!$init_module->add_ext_sshd_service()) {
notify($ERRORS{'WARNING'}, 0, "unable to configure ext_sshd,
failed to add the ext_sshd service to $computer_node_name");
return;
}
@@ -6601,6 +6991,64 @@ sub remove_matching_fstab_lines {
return $self->create_text_file('/etc/fstab', $updated_fstab_contents);
}
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 update_resolv_conf
+
+ Parameters : none
+ Returns : boolean
+ Description : Updates /etc/resolv.conf on the computer. Existing nameserver
+ lines are removed and new nameserver lines are added based on
the
+ public DNS servers configured for the management node.
+
+=cut
+
+sub update_resolv_conf {
+ my $self = shift;
+ if (ref($self) !~ /linux/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ my $computer_name = $self->data->get_computer_short_name();
+ my $public_ip_configuration =
$self->data->get_management_node_public_ip_configuration();
+ my @public_dns_servers =
$self->data->get_management_node_public_dns_servers();
+
+ if ($public_ip_configuration !~ /static/i) {
+ notify($ERRORS{'WARNING'}, 0, "unable to update resolv.conf on
$computer_name, management node's IP configuration is set to
$public_ip_configuration");
+ return;
+ }
+ elsif (!@public_dns_servers) {
+ notify($ERRORS{'WARNING'}, 0, "unable to update resolv.conf on
$computer_name, management node's public DNS server is not configured");
+ return;
+ }
+
+ my $resolv_conf_path = "/etc/resolv.conf";
+
+ my @resolv_conf_lines_existing =
$self->get_file_contents($resolv_conf_path);
+ my @resolv_conf_lines_new;
+ for my $line (@resolv_conf_lines_existing) {
+ if ($line =~ /\sVCL/) {
+ last;
+ }
+ elsif ($line !~ /^\s*nameserver/) {
+ push @resolv_conf_lines_new, $line;
+ }
+ }
+
+ # Add a comment marking what was added by VCL
+ my $timestamp = POSIX::strftime("%m-%d-%Y %H:%M:%S", localtime);
+ push @resolv_conf_lines_new, "# $timestamp: The following was added by
VCL";
+
+ # Add a nameserver line for each configured DNS server
+ for my $public_dns_server (@public_dns_servers) {
+ push @resolv_conf_lines_new, "nameserver $public_dns_server";
+ }
+
+ my $resolv_conf_contents_new = join("\n", @resolv_conf_lines_new);
+ return $self->create_text_file($resolv_conf_path,
$resolv_conf_contents_new);
+}
+
##/////////////////////////////////////////////////////////////////////////////
1;
__END__
Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm?rev=1750551&r1=1750550&r2=1750551&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm Tue Jun 28
18:20:50 2016
@@ -72,87 +72,26 @@ use VCL::utils;
our $SOURCE_CONFIGURATION_DIRECTORY = "$TOOLS/Ubuntu";
-##############################################################################
+=head2 @CAPTURE_DELETE_FILE_PATHS
-=head1 OBJECT METHODS
+ Data type : Array
+ Description : List of files to be deleted during the image capture process.
=cut
-#/////////////////////////////////////////////////////////////////////////////
+our $CAPTURE_DELETE_FILE_PATHS = [
+ '/etc/network/interfaces.20*', # Delete backups VCL makes of
/etc/network/interfaces
+];
-=head2 clean_iptables
+##############################################################################
- Parameters :
- Returns :
- Description :
+=head1 OBJECT METHODS
=cut
-sub clean_iptables {
- my $self = shift;
- if (ref($self) !~ /ubuntu/i) {
- notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
- return;
- }
-
- # Check to see if this distro has iptables
- if (!$self->service_exists("iptables")) {
- notify($ERRORS{'WARNING'}, 0, "iptables service does not exist
on this OS");
- return 1;
- }
-
- my $computer_node_name = $self->data->get_computer_node_name();
- my $reservation_id = $self->data->get_reservation_id();
- my $management_node_keys = $self->data->get_management_node_keys();
-
- # Retrieve the iptables file to work on locally
- my $tmpfile = "/tmp/" . $reservation_id . "_iptables";
- my $source_file_path = "/etc/iptables.rules";
- if (run_scp_command("$computer_node_name:\"$source_file_path\"",
$tmpfile, $management_node_keys)) {
- my @lines;
- if (open(IPTAB_TMPFILE, $tmpfile)) {
- @lines = <IPTAB_TMPFILE>;
- close(IPTAB_TMPFILE);
- }
- foreach my $line (@lines) {
- if ($line =~ s/-A INPUT -s .*\n//) {
- }
- }
-
- #Rewrite array to tmpfile
- if (open(IPTAB_TMPFILE, ">$tmpfile")) {
- print IPTAB_TMPFILE @lines;
- close (IPTAB_TMPFILE);
- }
-
- # Copy iptables file back to node
- if (run_scp_command($tmpfile,
"$computer_node_name:\"$source_file_path\"", $management_node_keys)) {
- notify($ERRORS{'DEBUG'}, 0, "copied $tmpfile to
$computer_node_name $source_file_path");
- }
- }
-
- #restart iptables
- my $command = "iptables -P INPUT ACCEPT;iptables -P OUTPUT ACCEPT;
iptables -P FORWARD ACCEPT; iptables -F; iptables-restore <
/etc/iptables.rules";
- my ($status_iptables,$output_iptables) = $self->execute($command);
- if (defined $status_iptables && $status_iptables == 0) {
- notify($ERRORS{'DEBUG'}, 0, "executed command $command on
$computer_node_name");
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "output from iptables:" .
join("\n", @$output_iptables));
- }
-
- if ($self->wait_for_ssh(0)) {
- return 1;
- }
- else {
- notify($ERRORS{'CRITICAL'}, 0, "not able to login via ssh after
cleaning_iptables");
- return 0;
- }
-}
-
#/////////////////////////////////////////////////////////////////////////////
-=head2 clean_known_files
+=head2 clean_iptables
Parameters :
Returns :
@@ -160,102 +99,13 @@ sub clean_iptables {
=cut
-sub clean_known_files {
- my $self = shift;
- if (ref($self) !~ /ubuntu/i) {
- notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
- return 0;
- }
-
- my $computer_node_name = $self->data->get_computer_node_name();
-
- # Clear SSH idenity keys from /root/.ssh
- if (!$self->clear_private_keys()) {
- notify($ERRORS{'WARNING'}, 0, "unable to clear known identity keys");
- }
-
- # Try to clear /tmp
- if ($self->execute("/bin/cp /dev/null /var/log/wtmp")) {
- notify($ERRORS{'DEBUG'}, 0, "cleared /var/log/wtmp on
$computer_node_name");
- }
-
- #Fetch exclude_list
- my @exclude_list = $self->get_exclude_list();
-
- if (@exclude_list ) {
- notify($ERRORS{'DEBUG'}, 0, "skipping files listed in
exclude_list\n" . join("\n", @exclude_list));
- }
-
- #Remove files
- if (!(grep( /70-persistent-net.rules/ , @exclude_list ) ) ) {
- if
(!$self->delete_file("/etc/udev/rules.d/70-persistent-net.rules")) {
- notify($ERRORS{'WARNING'}, 0, "unable to remove
/etc/udev/rules.d/70-persistent-net.rules");
- }
- }
-
- if (!(grep( /\/var\/log\/auth/ , @exclude_list ) ) ) {
- if (!$self->execute("cp /dev/null /var/log/auth.log")) {
- notify($ERRORS{'WARNING'}, 0, "unable to overwrite
/var/log/auth.log");
- }
- }
-
- if (!(grep( /\/var\/log\/lastlog/ , @exclude_list ) ) ) {
- if (!$self->execute("cp /dev/null /var/log/lastlog")) {
- notify($ERRORS{'WARNING'}, 0, "unable to overwrite
/var/log/lastlog");
- }
- }
-
- return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 enable_dhcp
-
- Parameters : $interface_name (optional)
- Returns : boolean
- Description : Configures /etc/network/interfaces file so that DHCP is enabled
- for the interface. If no argument is supplied, DHCP is enabled
- for the public and private interfaces.
-
-=cut
-
-sub enable_dhcp {
+sub clean_iptables {
my $self = shift;
- if (ref($self) !~ /VCL::Module/i) {
+ if (ref($self) !~ /ubuntu/i) {
notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
return;
}
- my $computer_node_name = $self->data->get_computer_node_name();
-
- my $interface_name_argument = shift;
- my @interface_names;
- if (!$interface_name_argument) {
- push(@interface_names, $self->get_private_interface_name());
- push(@interface_names, $self->get_public_interface_name());
- }
- elsif ($interface_name_argument =~ /private/i) {
- push(@interface_names, $self->get_private_interface_name());
- }
- elsif ($interface_name_argument =~ /public/i) {
- push(@interface_names, $self->get_public_interface_name());
- }
- else {
- push(@interface_names, $interface_name_argument);
- }
-
- my $interfaces_file_path = '/etc/network/interfaces';
- for my $interface_name (@interface_names) {
- # Remove existing lines from the interfaces file which contain
the interface name
- $self->remove_lines_from_file($interfaces_file_path,
$interface_name) || return;
-
- # Add line to end of interfaces file
- my $interface_string = "auto $interface_name\n";
- $interface_string .= "iface $interface_name inet dhcp\n";
- $self->append_text_file($interfaces_file_path,
$interface_string) || return;
- }
-
return 1;
}
@@ -570,317 +420,315 @@ sub get_firewall_configuration {
#/////////////////////////////////////////////////////////////////////////////
-=head2 set_static_public_address
+=head2 enable_dhcp
Parameters : none
Returns : boolean
- Description : Configures the public interface with a static IP address.
+ Description : Configures /etc/network/interfaces file so that DHCP is enabled
+ for the public interface.
=cut
-sub set_static_public_address {
+sub enable_dhcp {
my $self = shift;
- if (ref($self) !~ /ubuntu/i) {
+ 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 0;
+ return;
}
my $computer_name = $self->data->get_computer_short_name();
- my $request_id = $self->data->get_request_id();
- my $server_request_id = $self->data->get_server_request_id();
- my $management_node_keys = $self->data->get_management_node_keys();
-
- my $server_request_fixed_ip =
$self->data->get_server_request_fixed_ip();
- # Make sure public IP configuration is static or this is a server
request
- my $ip_configuration =
$self->data->get_management_node_public_ip_configuration();
+ my $private_interface_name = $self->get_private_interface_name();
+ my $public_interface_name = $self->get_public_interface_name();
- if ($ip_configuration !~ /static/i) {
- if ( !$server_request_fixed_ip ) {
- notify($ERRORS{'WARNING'}, 0, "static public address
can only be set if IP configuration is static or is a server request, current
value: $ip_configuration \nserver_request_fixed_ip=$server_request_fixed_ip");
- return;
- }
+ # Get the current interfaces file contents
+ my $interfaces_file_path = '/etc/network/interfaces';
+ my @interfaces_lines_original =
$self->get_file_contents($interfaces_file_path);
+ if (!@interfaces_lines_original) {
+ notify($ERRORS{'WARNING'}, 0, "failed to enable DHCP on
$computer_name, contents of $interfaces_file_path could not be retrieved");
+ return;
+ }
+ my $interfaces_contents_original = join("\n",
@interfaces_lines_original);
+
+ # Make a backup of the file
+ my $timestamp = POSIX::strftime("%Y-%m-%d_%H-%M-%S", localtime);
+ $self->copy_file($interfaces_file_path,
"$interfaces_file_path.$timestamp");
+
+
+ my @stanza_types = (
+ 'iface',
+ 'mapping',
+ 'auto',
+ 'allow-',
+ 'source',
+ );
+
+ my @interfaces_lines_new;
+ my $in_iface_stanza = 0;
+ my $iface_stanza_type;
+
+ for my $line (@interfaces_lines_original) {
+ # Never add hwaddress lines
+ if ($line =~ /^\s*(hwaddress)/) {
+ notify($ERRORS{'DEBUG'}, 0, "not including hwaddress
line: $line");
+ next;
+ }
+
+ if ($line =~
/^\s*iface\s+($private_interface_name|$public_interface_name)\s+(\w+)/) {
+ my $matching_interface_name = $1;
+ my $address_family = $2;
+ $in_iface_stanza = 1;
+ $iface_stanza_type = ($matching_interface_name eq
$private_interface_name ? 'private' : 'public');
+ notify($ERRORS{'DEBUG'}, 0, "found beginning of
$iface_stanza_type iface stanza: $line");
+ push @interfaces_lines_new, "iface
$matching_interface_name $address_family dhcp";
+ }
+ elsif ($in_iface_stanza) {
+ my ($stanza_type) = grep { $line =~ /^\s*$_/ }
@stanza_types;
+ if ($stanza_type) {
+ $in_iface_stanza = 0;
+ notify($ERRORS{'DEBUG'}, 0, "found end of
$iface_stanza_type iface stanza, line begins new stanza: $line");
+
+ # Add line which begins next stanza
+ push @interfaces_lines_new, $line;
+ }
+ else {
+ # Check if line should be added or ignored
+ if ($line =~
/^\s*(address|netmask|broadcast|gateway|pointopoint)/) {
+ my $match = $1;
+ notify($ERRORS{'DEBUG'}, 0, "not
including '$match' line from $iface_stanza_type iface stanza: $line");
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "including
line from $iface_stanza_type iface stanza: $line");
+ push @interfaces_lines_new, $line;
+ }
+ }
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "line is not part of public
or private iface stanza: $line");
+ push @interfaces_lines_new, $line;
+ }
}
+ my $interfaces_contents_new = join("\n", @interfaces_lines_new);
- # Get the IP configuration
- my $interface_name = $self->get_public_interface_name() ||
'<undefined>';
- my $computer_public_ip_address =
$self->data->get_computer_public_ip_address() || '<undefined>';
- my $subnet_mask = $self->data->get_management_node_public_subnet_mask()
|| '<undefined>';
- my $default_gateway =
$self->data->get_management_node_public_default_gateway() || '<undefined>';
- my @dns_servers = $self->data->get_management_node_public_dns_servers();
-
- if ($server_request_fixed_ip) {
- $computer_public_ip_address = $server_request_fixed_ip;
- $subnet_mask = $self->data->get_server_request_netmask();
- $default_gateway = $self->data->get_server_request_router();
- @dns_servers = $self->data->get_server_request_dns_servers();
+ # Check if the interfaces content changed, update file if necessary
+ if ($interfaces_contents_new eq $interfaces_contents_original) {
+ notify($ERRORS{'OK'}, 0, "update of $interfaces_file_path on
$computer_name not necessary, $interfaces_file_path not
changed:\n$interfaces_contents_new");
}
-
- # Make sure required info was retrieved
- if ("$interface_name $computer_public_ip_address $subnet_mask
$default_gateway" =~ /undefined/) {
- notify($ERRORS{'WARNING'}, 0, "failed to retrieve required
network configuration for $computer_name");
- return;
+ elsif ($self->create_text_file($interfaces_file_path,
$interfaces_contents_new)) {
+ notify($ERRORS{'OK'}, 0, "updated $interfaces_file_path to
enable public DHCP on $computer_name\n" .
+ "original:\n$interfaces_contents_original\n" .
+ "---\n" .
+ "current:\n$interfaces_contents_new"
+ );
}
else {
- notify($ERRORS{'OK'}, 0, "attempting to set static public IP
address on $computer_name");
- }
-
- #Try to ping address to make sure it's available
- #FIXME -- need to add other tests for checking ip_address is or is not
available.
- if (_pingnode($computer_public_ip_address)) {
- notify($ERRORS{'WARNING'}, 0, "ip_address
$computer_public_ip_address is pingable, can not assign to $computer_name ");
+ notify($ERRORS{'WARNING'}, 0, "failed to update
$interfaces_file_path to enable public DHCP on $computer_name");
return;
}
+
+ delete $self->{network_configuration};
- # Assemble the ifcfg file path
- my $network_interfaces_file = "/etc/network/interfaces";
- my $network_interfaces_file_default = "/etc/network/interfaces";
- notify($ERRORS{'DEBUG'}, 0, "interface file path:
$network_interfaces_file");
-
- if ($self->execute("cp network_interfaces_file
/etc/network/interfaces_orig")) {
- notify($ERRORS{'OK'}, 0, "Created backup of
$network_interfaces_file");
- }
-
- #Get interfaces file
- my $tmpfile = "/tmp/$request_id.interfaces";
- if (run_scp_command("$computer_name:$network_interfaces_file",
$tmpfile, $management_node_keys)) {
- notify($ERRORS{'DEBUG'}, 0, "copied sshd init script from
$computer_name for local processing");
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to copied ssh init script
from $computer_name for local processing");
+ notify($ERRORS{'DEBUG'}, 0, "enabled public DHCP on $computer_name");
+ return 1;
+}
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 set_static_public_address
+
+ Parameters : none
+ Returns : boolean
+ Description : Configures the public interface with a static IP address.
+
+=cut
+
+sub set_static_public_address {
+ my $self = shift;
+ if (ref($self) !~ /ubuntu/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
return 0;
}
- my @interfaces = read_file_to_array($tmpfile);
- #Build new interfaces file
- my @new_interfaces_file;
-
- foreach my $l (@interfaces) {
- push(@new_interfaces_file, $l) if($l =~ /^(#.*)/ );
- push(@new_interfaces_file, $l) if($l =~ /^auto lo/);
- push(@new_interfaces_file, $l) if($l =~ /^\n$/);
-
- if ($l =~ /^iface/) {
- push(@new_interfaces_file, $l) if($l !~
/$interface_name/ );
- }
+ my $computer_name = $self->data->get_computer_short_name();
+ my $public_ip_configuration =
$self->data->get_management_node_public_ip_configuration();
+ my $public_ip_address =
$self->data->get_computer_public_ip_address();
+ my $public_subnet_mask =
$self->data->get_management_node_public_subnet_mask();
+ my $public_default_gateway =
$self->data->get_management_node_public_default_gateway();
+ my @public_dns_servers =
$self->data->get_management_node_public_dns_servers();
+
+ my $server_request_fixed_ip =
$self->data->get_server_request_fixed_ip();
+ if ($server_request_fixed_ip) {
+ $public_ip_address = $server_request_fixed_ip;
+ $public_subnet_mask =
$self->data->get_server_request_netmask();
+ $public_default_gateway =
$self->data->get_server_request_router();
+ @public_dns_servers =
$self->data->get_server_request_dns_servers();
- if ($l =~ /^iface $interface_name/) {
- push(@new_interfaces_file, "iface $interface_name inet
static\n");
- push(@new_interfaces_file, "address
$computer_public_ip_address\n");
- push(@new_interfaces_file, "netmask $subnet_mask\n");
- push(@new_interfaces_file, "gateway
$default_gateway\n");
+ if (!$public_subnet_mask) {
+ notify($ERRORS{'WARNING'}, 0, "unable to set static
public IP address to $public_ip_address on $computer_name, server request fixed
IP is set but server request subnet mask could not be retrieved");
+ return;
+ }
+ elsif (!$public_default_gateway) {
+ notify($ERRORS{'WARNING'}, 0, "unable to set static
public IP address to $public_ip_address on $computer_name, server request fixed
IP is set but server request default gateway could not be retrieved");
+ return;
+ }
+ elsif (!@public_dns_servers) {
+ notify($ERRORS{'WARNING'}, 0, "unable to set static
public IP address to $public_ip_address on $computer_name, server request fixed
IP is set but server request DNS servers could not be retrieved");
+ return;
}
- }
-
- notify($ERRORS{'OK'}, 0, "output:\n" .
format_data(@new_interfaces_file));
- #Clear temp file
- unlink($tmpfile);
- #Write array to file
- if (open(FILE, ">$tmpfile")) {
- print FILE @new_interfaces_file;
- close FILE;
- }
-
- #copy temp file to node
- if (run_scp_command($tmpfile, "$computer_name:/etc/network/interfaces",
$management_node_keys)) {
- notify($ERRORS{'DEBUG'}, 0, "copied $tmpfile to
$computer_name:/etc/network/interfaces");
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed to copied $tmpfile to
$computer_name:/etc/network/interfaces");
- return 0;
+ if ($public_ip_configuration !~ /static/i) {
+ notify($ERRORS{'WARNING'}, 0, "unable to set static
public IP address to $public_ip_address on $computer_name, management node's IP
configuration is set to $public_ip_configuration");
+ return;
+ }
}
- unlink($tmpfile);
-
- # Restart the interface
- if (!$self->restart_network_interface($interface_name)) {
- notify($ERRORS{'WARNING'}, 0, "failed to restart public
interface $interface_name on $computer_name");
+
+ # Get the public interface name
+ my $public_interface_name = $self->get_public_interface_name();
+ if (!$public_interface_name) {
+ notify($ERRORS{'WARNING'}, 0, "unable to set static public IP
address to $public_ip_address on $computer_name, failed to determine public
interface name");
return;
}
- # Delete existing default route
- my $route_del_command = "/sbin/route del default";
- my ($route_del_exit_status, $route_del_output) =
$self->execute($route_del_command);
- if (!defined($route_del_output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to run command to delete
the existing default route on $computer_name: '$route_del_command'");
- return;
- }
- elsif (grep(/No such process/i, @$route_del_output)) {
- notify($ERRORS{'DEBUG'}, 0, "existing default route is not
set");
- }
- elsif ($route_del_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to delete existing
default route on $computer_name, exit status: $route_del_exit_status, command:
'$route_del_command', output:\n" . join("\n", @$route_del_output));
- return;
- }
- else {
- notify($ERRORS{'DEBUG'}, 0, "deleted existing default route on
$computer_name, output:\n" . join("\n", @$route_del_output));
- }
+ # Stop the interface in case it is already assigned the static IP
otherwise ping will respond
+ $self->stop_network_interface($public_interface_name);
- # Set default route
- my $route_add_command = "/sbin/route add default gw $default_gateway
metric 0 $interface_name 2>&1 && /sbin/route -n";
- my ($route_add_exit_status, $route_add_output) =
$self->execute($route_add_command);
- if (!defined($route_add_output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to run command to add
default route to $default_gateway on public interface $interface_name on
$computer_name: '$route_add_command'");
- return;
- }
- elsif ($route_add_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to add default route to
$default_gateway on public interface $interface_name on $computer_name, exit
status: $route_add_exit_status, command: '$route_add_command', output:\n" .
join("\n", @$route_add_output));
+ # Attempt to ping the public IP address to make sure it's available
+ if (_pingnode($public_ip_address)) {
+ notify($ERRORS{'CRITICAL'}, 0, "failed to set static public IP
address to $public_ip_address on $computer_name, IP address is pingable");
return;
}
- else {
- notify($ERRORS{'DEBUG'}, 0, "added default route to
$default_gateway on public interface $interface_name on $computer_name,
output:\n" . format_data($route_add_output));
- }
-
- my $ext_sshd_config_file_path = '/etc/ssh/external_sshd_config';
-
- # Remove existing ListenAddress lines from external_sshd_config
- $self->remove_lines_from_file($ext_sshd_config_file_path,
'ListenAddress') || return;
-
- # Add ListenAddress line to the end of the file
- $self->append_text_file($ext_sshd_config_file_path, "ListenAddress
$computer_public_ip_address\n") || return;
- # Update resolv.conf if DNS server address is configured for the
management node
- my $resolv_conf_path = "/etc/resolv.conf";
- if (@dns_servers) {
- # Get the resolve.conf contents
- my $cat_resolve_command = "cat $resolv_conf_path";
- my ($cat_resolve_exit_status, $cat_resolve_output) =
$self->execute($cat_resolve_command);
- if (!defined($cat_resolve_output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to run command to
retrieve existing $resolv_conf_path contents from $computer_name");
- return;
- }
- elsif ($cat_resolve_exit_status || grep(/^(bash:|cat:)/,
@$cat_resolve_output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to retrieve
existing $resolv_conf_path contents from $computer_name, exit status:
$cat_resolve_exit_status, command: '$cat_resolve_command', output:\n" .
join("\n", @$cat_resolve_output));
- return;
- }
- else {
- notify($ERRORS{'DEBUG'}, 0, "retrieved existing
$resolv_conf_path contents from $computer_name:\n" . join("\n",
@$cat_resolve_output));
- }
-
- # Remove lines containing nameserver
- my @resolv_conf_lines = grep(!/nameserver/i,
@$cat_resolve_output);
-
- # Add a nameserver line for each configured DNS server
- for my $dns_server_address (@dns_servers) {
- push @resolv_conf_lines, "nameserver
$dns_server_address";
- }
-
- # Remove newlines for consistency
- map { chomp $_ } @resolv_conf_lines;
-
- # Assemble the lines into an array
- my $resolv_conf_contents = join("\n", @resolv_conf_lines);
-
- # Echo the updated contents to resolv.conf
- my $echo_resolve_command = "echo \"$resolv_conf_contents\" >
$resolv_conf_path 2>&1 && cat $resolv_conf_path";
- my ($echo_resolve_exit_status, $echo_resolve_output) =
$self->execute($echo_resolve_command);
- if (!defined($echo_resolve_output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to run command to
update $resolv_conf_path on $computer_name:\n$echo_resolve_command");
- return;
- }
- elsif ($echo_resolve_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to update
$resolv_conf_path on $computer_name, exit status:
$echo_resolve_exit_status\ncommand:\n$echo_resolve_command\noutput:\n" .
join("\n", @$echo_resolve_output));
- return;
+ # Get the current interfaces file contents
+ my $interfaces_file_path = '/etc/network/interfaces';
+ my @interfaces_lines_original =
$self->get_file_contents($interfaces_file_path);
+ if (!@interfaces_lines_original) {
+ notify($ERRORS{'WARNING'}, 0, "failed to set static public IP
address to $public_ip_address on $computer_name, $interfaces_file_path contents
could not be retrieved");
+ return;
+ }
+ my $interfaces_contents_original = join("\n",
@interfaces_lines_original);
+ notify($ERRORS{'DEBUG'}, 0, "retreived contents of
'$interfaces_file_path' from $computer_name:\n$interfaces_contents_original");
+
+ # Make a backup of the file
+ my $timestamp = POSIX::strftime("%Y-%m-%d_%H-%M-%S", localtime);
+ $self->copy_file($interfaces_file_path,
"$interfaces_file_path.$timestamp");
+
+ # Examples:
+ # auto eth0
+ # iface eth0 inet dhcp
+
+ # auto br1
+ # iface br1 inet dhcp
+ # bridge_ports eth1
+ # bridge_stp off
+ # bridge_fd 0
+
+ # iface eth1 inet static
+ # address 192.168.1.1
+ # netmask 255.255.255.0
+
+ my @stanza_types = (
+ 'iface',
+ 'mapping',
+ 'auto',
+ 'allow-',
+ 'source',
+ );
+
+ my @interfaces_lines_new;
+ my $in_public_iface_stanza = 0;
+
+ my @lines_to_add = (
+ " address $public_ip_address",
+ " netmask $public_subnet_mask",
+ " gateway $public_default_gateway",
+ );
+
+ for my $line (@interfaces_lines_original) {
+
+ if ($line =~ /^\s*iface\s+$public_interface_name\s+(\w+)/) {
+ my $address_family = $1;
+ $in_public_iface_stanza = 1;
+ notify($ERRORS{'DEBUG'}, 0, "found beginning of public
iface stanza: $line");
+ push @interfaces_lines_new, "iface
$public_interface_name $address_family static";
+
+ # Add static IP information
+ push @interfaces_lines_new, @lines_to_add;
+ notify($ERRORS{'DEBUG'}, 0, "adding lines:\n" .
join("\n", @lines_to_add));
+ }
+ elsif ($in_public_iface_stanza) {
+ my ($stanza_type) = grep { $line =~ /^\s*$_/ }
@stanza_types;
+ if ($stanza_type) {
+ $in_public_iface_stanza = 0;
+ notify($ERRORS{'DEBUG'}, 0, "found end of
public iface stanza, line begins new stanza: $line");
+
+ # Add line which begins next stanza
+ push @interfaces_lines_new, $line;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "line in public
iface stanza: $line");
+
+ # Check if line should be added or ignored
+ if ($line =~ /^\s*(bridge|bond|vlan)/) {
+ my $match = $1;
+ notify($ERRORS{'DEBUG'}, 0, "including
'$match' line from public iface stanza: $line");
+ push @interfaces_lines_new, $line;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "not
including line from public iface stanza: $line");
+ }
+ }
}
else {
- notify($ERRORS{'DEBUG'}, 0, "updated $resolv_conf_path
on $computer_name:\n" . join("\n", @$echo_resolve_output));
+ notify($ERRORS{'DEBUG'}, 0, "line is not part of public
iface stanza: $line");
+ push @interfaces_lines_new, $line;
}
}
- else {
- notify($ERRORS{'DEBUG'}, 0, "$resolv_conf_path not updated on
$computer_name because DNS server address is not configured for the management
node");
- }
+ my $interfaces_contents_new = join("\n", @interfaces_lines_new);
- notify($ERRORS{'OK'}, 0, "successfully set static public IP address on
$computer_name");
- return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 restart_network_interface
-
- Parameters : $interface_name
- Returns :
- Description : Calls ifdown and then ifup on the network interface.
-
-=cut
-
-sub restart_network_interface {
- my $self = shift;
- if (ref($self) !~ /linux/i) {
- notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
- return 0;
- }
- my $interface_name = shift;
- if (!$interface_name) {
- notify($ERRORS{'WARNING'}, 0, "unable to restart network
interface, interface name argument was not supplied");
- return;
+ # Check if the interfaces content changed, update file if necessary
+ if ($interfaces_contents_new eq $interfaces_contents_original) {
+ notify($ERRORS{'OK'}, 0, "update of $interfaces_file_path on
$computer_name not necessary, $interfaces_file_path not
changed:\n$interfaces_contents_new");
}
-
- my $computer_name = $self->data->get_computer_short_name();
-
- # Restart the interface
- notify($ERRORS{'DEBUG'}, 0, "attempting to restart network interface
$interface_name on $computer_name");
- my $interface_restart_command = "/sbin/ifdown $interface_name ;
/sbin/ifup $interface_name";
- my ($interface_restart_exit_status, $interface_restart_output) =
$self->execute($interface_restart_command);
- if (!defined($interface_restart_output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to run command to restart
interface $interface_name on $computer_name: '$interface_restart_command'");
- return;
- }
- elsif ($interface_restart_exit_status) {
- notify($ERRORS{'WARNING'}, 0, "failed to restart network
interface $interface_name on $computer_name, exit status:
$interface_restart_exit_status, command: '$interface_restart_command',
output:\n" . join("\n", @$interface_restart_output));
- return;
+ elsif ($self->create_text_file($interfaces_file_path,
$interfaces_contents_new)) {
+ notify($ERRORS{'OK'}, 0, "updated $interfaces_file_path to set
static public IP address to $public_ip_address on $computer_name\n" .
+ "original:\n$interfaces_contents_original\n" .
+ "---\n" .
+ "new:\n$interfaces_contents_new"
+ );
}
else {
- notify($ERRORS{'DEBUG'}, 0, "restarted network interface
$interface_name on $computer_name");
+ notify($ERRORS{'WARNING'}, 0, "failed to update
$interfaces_file_path to set static public IP address to $public_ip_address on
$computer_name");
+ return;
}
- return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 update_hostname_file
-
- Parameters : hostname
- Returns : boolean
- Description : updates the static hostname file on node, so hostname persists
across reboots
- this routine is seperated from update_public_hostname for
different locations
- and formats for different Linux distributions
-
-=cut
-
-sub update_hostname_file {
- my $self = shift;
- if (ref($self) !~ /linux/i) {
- notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
- return 0;
+ # Restart the public interface
+ if (!$self->restart_network_interface($public_interface_name)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to set static public IP
address to $public_ip_address on $computer_name, failed to restart public
interface $public_interface_name");
+ return;
}
- my $public_hostname = shift;
- if (!$public_hostname) {
- notify($ERRORS{'WARNING'}, 0, "public_hostname was not passed
correctly");
- return 0;
+ # Set the default gateway
+ if (!$self->set_default_gateway($public_default_gateway,
$public_interface_name)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to set static public IP
address to $public_ip_address on $computer_name, failed to set the default
gateway");
+ return;
}
- my $computer_node_name = $self->data->get_computer_node_name();
- my $network_file_path = '/etc/hostname';
-
- my $command = "echo \"$public_hostname\" > $network_file_path";
- my ($exit_status, $output) = $self->execute($command);
- if (!defined($output)) {
- notify($ERRORS{'WARNING'}, 0, "failed to SSH command to set
hostname on $computer_node_name to $public_hostname, command: '$command'");
+ # Update resolv.conf
+ if (!$self->update_resolv_conf()) {
+ notify($ERRORS{'WARNING'}, 0, "failed to set static public IP
address to $public_ip_address on $computer_name, failed to update resolv.conf");
return;
}
- elsif ($exit_status == 0) {
- notify($ERRORS{'OK'}, 0, "set public hostname on
$computer_node_name to $public_hostname");
- return 1;
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "failed to set public hostname on
$computer_node_name to $public_hostname, exit status: $exit_status, output:\n"
. join("\n", @ $output));
- return 0;
- }
+
+ # Delete cached network configuration info - forces next call to
get_network_configuration to retrieve changed network info from computer
+ delete $self->{network_configuration};
+
+ notify($ERRORS{'DEBUG'}, 0, "set static public IP address to
$public_ip_address on $computer_name");
+ return 1;
}
#/////////////////////////////////////////////////////////////////////////////
@@ -895,7 +743,6 @@ sub update_hostname_file {
sub activate_interfaces {
return 1;
-
}
#/////////////////////////////////////////////////////////////////////////////
Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1750551&r1=1750550&r2=1750551&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Tue Jun 28 18:20:50 2016
@@ -283,6 +283,7 @@ our @EXPORT = qw(
update_reservation_natlog
update_reservation_password
update_sublog_ipaddress
+ wrap_string
xml_string_to_hash
xmlrpc_call
yaml_deserialize
@@ -14309,6 +14310,35 @@ sub determine_remote_connection_target {
}
#/////////////////////////////////////////////////////////////////////////////
+
+=head2 wrap_string
+
+ Parameters : $string, $columns, $prefix
+ Returns : string
+ Description : Formats a string to limit the number of characters per line. The
+ $prefix argument may be used to add comment characters to the
+ beginning of each line, while still adhering to the line width
+ limit. If $prefix is set to '# ' (not including the single-quote
+ characters), the string returned will be something like:
+ # My first line...
+ # Second line...
+
+=cut
+
+sub wrap_string {
+ my ($string, $columns, $prefix) = @_;
+ return '' unless defined($string);
+ $columns = 80 unless $columns;
+ $prefix = '' unless defined($prefix);
+
+ # Wrap text for lines
+ local($Text::Wrap::columns) = $columns;
+
+ my $wrapped_string = wrap($prefix, $prefix, $string);
+ return $wrapped_string;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
1;
__END__