Author: arkurth
Date: Wed May 24 22:22:40 2017
New Revision: 1796111

URL: http://svn.apache.org/viewvc?rev=1796111&view=rev
Log:
VCL-1031

Updated Module.pm::create_nathost_os_object to check to make sure various 
things were correct before returning true, including:
* public IP and internal IP defined
* firewall object is defined
* firewall object implements nat_configure_reservation and nat_configure_host

Added code to set NAT host public and internal IP addresses in NAT host OS's 
DataStructure object. These were available to the OS object of the computer 
being loaded but not the NAT host OS or its firewall object.

Moved calls to nat_configure_host and nat_configure_reservation from 
OS.pm::process_connect_methods to OS.pm::reserve. process_connect_methods is 
called after the user clicks Connect. These NAT steps added time between 
clicking Connect and actually being able to connect. These steps can be safely 
done earlier in reserve.

Renamed Linux.pm::set_default_gateway  and Windows.pm::set_public_default_route 
to set_static_default_gateway so they match.

Updated Linux.pm::set_default_gateway to add DEFROUT=no to ifcfg files in order 
to completely override a different DHCP-assigned route.

Added call to set_static_default_gateway in OS.pm::update_public_ip_address if 
computer is assigned to a NAT host, DHCP is used, and the computer's current 
gateway isn't the NAT host's internal IP address. This forces the computer to 
use the NAT host's address as its gateway.

Added OS.pm::get_correct_default_gateway to reduce duplicate code. It checks if 
NAT is used, or public IP is static/DHCP assigned.

Added OS.pm::set_config_file_parameter to make it easier to add or modify 
settings in various types of config files.

Added code to Linux.pm::pre_capture to delete any route files that may have 
been added by set_static_default_gateway. Also added lines to clean out 
HOSTNAME and GATEWAY lines from network file if they exist.

Improved Linux.pm::enable_ip_forwarding to configure /etc/sysctl.conf rather 
than simply calling 'echo 1 > /proc/sys/net/ipv4/ip_forward'. This wasn't 
persisting across reboots which is problematic for NAT hosts.

Updated firewalld.pm::delete_chain to accept a chain name pattern argument.

Updated iptables.pm NAT host configuration to use dedicated chains.






Modified:
    vcl/trunk/managementnode/lib/VCL/Module.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS.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/Module/OS/Linux/firewall/firewalld.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.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=1796111&r1=1796110&r2=1796111&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module.pm Wed May 24 22:22:40 2017
@@ -725,22 +725,39 @@ my $self = shift;
                return;
        }
        
-       # Make sure computer is mapped to a NAT host
-       my $nathost_id = $self->data->get_nathost_id();
-       if (!$nathost_id) {
-               notify($ERRORS{'WARNING'}, 0, "NAT host OS object not created, 
computer is not mapped to a NAT host");
-               return;
-       }
-       
        my $request_data = $self->data->get_request_data();
        my $reservation_id = $self->data->get_reservation_id();
        
+       my $nathost_id = $self->data->get_nathost_id();
        my $nathost_hostname = $self->data->get_nathost_hostname();
+       my $nathost_public_ip_address = 
$self->data->get_nathost_public_ip_address(0);
+       my $nathost_internal_ip_address = 
$self->data->get_nathost_internal_ip_address(0);
        my $nathost_resource_subid = $self->data->get_nathost_resource_subid();
        my $nathost_resource_type = $self->data->get_nathost_resource_type();
+       
+       # Make sure computer is mapped to a NAT host and all the required 
variables are set
+       if (!defined($nathost_id)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to create NAT host OS 
object, NAT host ID is not defined");
+               return;
+       }
+       elsif (!defined($nathost_hostname)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to create NAT host OS 
object, NAT host hostname is not defined");
+               return;
+       }
+       elsif (!defined($nathost_public_ip_address)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to create NAT host OS 
object, NAT host public IP address is not defined");
+               return;
+       }
+       elsif (!defined($nathost_internal_ip_address)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to create NAT host OS 
object, NAT host internal IP address is not defined");
+               return;
+       }
+       
+       my $nathost_os;
+       
        if ($nathost_resource_type eq 'managementnode') {
                notify($ERRORS{'DEBUG'}, 0, "NAT host resource type is 
$nathost_resource_type, returning management node OS object to control 
$nathost_hostname");
-               return $self->mn_os();
+               $nathost_os = $self->mn_os();
        }
        elsif ($nathost_resource_type eq 'computer') {
                # Get the computer info in order to determine the OS module to 
use
@@ -760,15 +777,12 @@ my $self = shift;
                        notify($ERRORS{'DEBUG'}, 0, "NAT host resource type is 
$nathost_resource_type, creating $computer_os_package OS object to control 
$nathost_hostname based its current computer.currentimagerevision value");
                }
                
-               my $nathost_os = $self->create_object($computer_os_package, {
+               $nathost_os = $self->create_object($computer_os_package, {
                        #request_data => $request_data,
                        reservation_id => $reservation_id,
                        computer_identifier => $nathost_resource_subid
                });
-               if ($nathost_os) {
-                       return $nathost_os;
-               }
-               else {
+               if (!$nathost_os) {
                        notify($ERRORS{'WARNING'}, 0, "failed to create NAT 
host OS object to control $nathost_hostname");
                        return;
                }
@@ -777,6 +791,29 @@ my $self = shift;
                notify($ERRORS{'WARNING'}, 0, "unable to create NAT host OS 
object to control $nathost_hostname, NAT host resource type is not supported: 
$nathost_resource_type, NAT host info:\n" . 
format_data($self->data->get_nathost_info()));
                return;
        }
+       
+       # All of the following should always be configured
+       my $nathost_os_type = ref($nathost_os);
+       if (!$nathost_os->firewall()) {
+               notify($ERRORS{'WARNING'}, 0, "created $nathost_os_type NAT 
host OS object but firewall object is not available");
+               return;
+       }
+       
+       my $firewall_type = ref($nathost_os->firewall());
+       if (!$nathost_os->firewall->can('nat_configure_host')) {
+               notify($ERRORS{'WARNING'}, 0, "created $nathost_os_type NAT 
host OS object but NAT host OS's $firewall_type firewall object does NOT 
implement a 'nat_configure_host' method");
+               return;
+       }
+       elsif (!$nathost_os->firewall->can('nat_configure_reservation')) {
+               notify($ERRORS{'WARNING'}, 0, "created $nathost_os_type NAT 
host OS object but NAT host OS's $firewall_type firewall object does NOT 
implement a 'nat_configure_reservation' method");
+               return;
+       }
+       
+       # Set NAT host DataStructure values so they can be accessed from 
$self->nathost_os and $self->nathost_os->firewall
+       
$nathost_os->data->set_nathost_public_ip_address($nathost_public_ip_address);
+       
$nathost_os->data->set_nathost_internal_ip_address($nathost_internal_ip_address);
+       
+       return $nathost_os
 }
 
 #//////////////////////////////////////////////////////////////////////////////

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1796111&r1=1796110&r2=1796111&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Wed May 24 22:22:40 2017
@@ -193,10 +193,17 @@ sub post_load {
 
  Parameters  : none
  Returns     : boolean
- Description : Performs common OS steps to reserve the computer for a user. The
-               public IP address is updated if necessary. User accounts are
-               added. The 'reserve' subroutine should never open the firewall
-               for a connection. This is done by the 'grant_access' subroutine.
+ Description : Performs common OS steps to reserve the computer for a user:
+               * The public IP address is updated if necessary
+                                       * If the computer is mapped to a NAT 
host:
+                                       ** General NAT host configuration is 
performed if not previously
+                                          done.
+                                       ** The NAT host is prepared for the 
reservation but specific port
+                                          forwardings are not added.
+                                       * User accounts are added
+                                       
+                                       Note: The 'reserve' subroutine should 
never open the firewall for
+                                       a connection. This is done by the 
'grant_access' subroutine.
 
 =cut
 
@@ -207,12 +214,32 @@ sub reserve {
                return;
        }
        
+       my $computer_node_name = $self->data->get_computer_node_name();
+       my $nathost_hostname = $self->data->get_nathost_hostname(0);
+       
        # Make sure the public IP address assigned to the computer matches the 
database
        if (!$self->update_public_ip_address()) {
                notify($ERRORS{'WARNING'}, 0, "unable to reserve computer, 
failed to update IP address");
                return;
        }
        
+       
+       # Check if the computer is mapped to a NAT host
+       if ($nathost_hostname) {
+               # Perform general NAT host configuration - this only needs to 
be done once, nat_configure_host checks if it was already done 
+               if (!$self->nathost_os->firewall->nat_configure_host()) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to reserve 
$computer_node_name, failed to configure NAT on $nathost_hostname");
+                       return;
+               }
+               
+               # Perform reservation-specific NAT configuration
+               if (!$self->nathost_os->firewall->nat_configure_reservation()) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to reserve 
$computer_node_name, failed to configure NAT on $nathost_hostname for this 
reservation");
+                       return;
+               }
+       }
+       
+       
        # Add user accounts to the computer
        if (!$self->add_user_accounts()) {
                notify($ERRORS{'WARNING'}, 0, "unable to reserve computer, 
failed add user accounts");
@@ -1441,6 +1468,8 @@ sub update_public_ip_address {
        my $image_os_type = $self->data->get_image_os_type() || return;
        my $computer_public_ip_address = 
$self->data->get_computer_public_ip_address();
        my $public_ip_configuration = 
$self->data->get_management_node_public_ip_configuration() || return;
+       my $nathost_hostname = $self->data->get_nathost_hostname(0);
+       my $nathost_internal_ip_address = 
$self->data->get_nathost_internal_ip_address(0);
        
        if ($public_ip_configuration =~ /dhcp/i) {
                notify($ERRORS{'DEBUG'}, 0, "IP configuration is set to 
$public_ip_configuration, attempting to retrieve dynamic public IP address from 
$computer_node_name");
@@ -1481,6 +1510,19 @@ sub update_public_ip_address {
                        notify($ERRORS{'DEBUG'}, 0, "public IP address in 
computer table is already correct for $computer_node_name: 
$computer_public_ip_address");
                }
                
+               # If the computer is assigned to a NAT host, make sure default 
gateway is correct
+               if ($nathost_hostname && $nathost_internal_ip_address) {
+                       my $current_default_gateway = 
$self->get_default_gateway();
+                       if ($current_default_gateway) {
+                               if ($current_default_gateway eq 
$nathost_internal_ip_address) {
+                                       notify($ERRORS{'DEBUG'}, 0, "static 
default gateway does NOT need to be set on $computer_node_name, default gateway 
assigned by DHCP matches NAT host internal IP address: 
$current_default_gateway");
+                               }
+                               else {
+                                       notify($ERRORS{'OK'}, 0, "static 
default gateway needs to be set on $computer_node_name, default gateway 
assigned by DHCP ($current_default_gateway) does NOT match NAT host internal IP 
address: $nathost_internal_ip_address");
+                                       $self->set_static_default_gateway();
+                               }
+                       }
+               }
        }
        elsif ($public_ip_configuration =~ /static/i) {
                notify($ERRORS{'DEBUG'}, 0, "IP configuration is set to 
$public_ip_configuration, attempting to set public IP address");
@@ -1510,6 +1552,68 @@ sub update_public_ip_address {
 
 #//////////////////////////////////////////////////////////////////////////////
 
+=head2 get_correct_default_gateway
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Determines which IP address should be used for the computer's
+               default gateway:
+               * If the computer is configured to use a NAT host, the 
computer's
+                 default gateway should be set to the NAT host's internal IP
+                 address
+               * If NAT is not used and the management node profile is
+                 configured to use static public IP addresses, the computer's
+                 default gateway should be set to the management node profile's
+                 "Public Gateway" setting
+               * If NAT is not used and the management node profile is
+                 configured to use DHCP-assigned public IP addresses, the
+                 computer's current default gateway should continue to be used
+
+=cut
+
+sub get_correct_default_gateway {
+       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 0;
+       }
+       
+       my $computer_name = $self->data->get_computer_short_name();
+       my $nathost_hostname = $self->data->get_nathost_hostname(0);
+       my $nathost_internal_ip_address = 
$self->data->get_nathost_internal_ip_address(0);
+       my $management_node_ip_configuration = 
$self->data->get_management_node_public_ip_configuration();
+       
+       if ($nathost_internal_ip_address) {
+               notify($ERRORS{'DEBUG'}, 0, "$computer_name is configured to 
use NAT host $nathost_hostname, default gateway should be set to NAT host's 
internal IP address: $nathost_internal_ip_address");
+               return $nathost_internal_ip_address;
+       }
+       elsif ($management_node_ip_configuration =~ /static/i) {
+               my $management_node_public_default_gateway = 
$self->data->get_management_node_public_default_gateway();
+               if ($management_node_public_default_gateway) {
+                       notify($ERRORS{'DEBUG'}, 0, "management node public IP 
mode is set to $management_node_ip_configuration, default gateway should be set 
to management node profile's default gateway setting: 
$management_node_public_default_gateway");
+                       return $management_node_public_default_gateway;
+               }
+               else {
+                       notify($ERRORS{'WARNING'}, 0, "unable to determine 
correct default gateway to use on $computer_name, management node public IP 
mode is set to $management_node_ip_configuration but management node profile's 
default gateway setting could not be determined");
+                       return;
+               }
+       }
+       else {
+               # Management node configured to use DHCP for public IP addresses
+               # Get default gateway address assigned to computer
+               my $current_default_gateway = 
$self->get_public_default_gateway();
+               if ($current_default_gateway) {
+                       notify($ERRORS{'DEBUG'}, 0, "management node public IP 
mode is set to $management_node_ip_configuration, default gateway currently 
configured on $computer_name should be used: $current_default_gateway");
+               }
+               else {
+                       notify($ERRORS{'WARNING'}, 0, "unable to determine 
correct default gateway to use on $computer_name, management node public IP 
mode is set to $management_node_ip_configuration but default gateway currently 
configured on $computer_name could not be determined");
+                       return;
+               }
+       }
+}
+
+#//////////////////////////////////////////////////////////////////////////////
+
 =head2 get_current_image_tag
 
  Parameters  : $tag_name
@@ -3013,6 +3117,11 @@ sub remove_lines_from_file {
        my @lines_removed;
        my @lines_retained;
        
+       if (!$self->file_exists($file_path)) {
+               notify($ERRORS{'DEBUG'}, 0, "lines containing '$pattern' not 
removed because file does NOT exist: $file_path");
+               return 1;
+       }
+       
        my @lines = $self->get_file_contents($file_path);
        for my $line (@lines) {
                if ($line =~ /$pattern/) {
@@ -3664,60 +3773,7 @@ sub process_connect_methods {
                $overwrite = 0;
        }
        
-       # Check if NAT is used
-       my $computer_ip_address;
-       if ($nathost_hostname) {
-               if (!$self->nathost_os(0)) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, $computer_node_name is assigned to NAT host $nathost_hostname 
but NAT host OS object is not available");
-                       return;
-               }
-               elsif (!$self->nathost_os->firewall()) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, $computer_node_name is assigned to NAT host $nathost_hostname 
but NAT host OS's firewall object is not available");
-                       return;
-               }
-               elsif (!$nathost_public_ip_address) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, $computer_node_name is assigned to NAT host $nathost_hostname 
but NAT host public IP address could not be determined from the nathost table");
-                       return;
-               }
-               elsif (!$nathost_internal_ip_address) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, $computer_node_name is assigned to NAT host $nathost_hostname 
but NAT host internal IP address could not be determined from the nathost 
table");
-                       return;
-               }
-               
-               # Get the IP address used to communicate between the NAT host 
and computer
-               $computer_ip_address = $self->get_public_ip_address();
-               if (!$computer_ip_address) {
-                       notify($ERRORS{'WARNING'}, 0, "unable to process 
connect methods, failed to retrieve public (internal NAT) IP address of 
computer $computer_node_name, unable to configure NAT port forwarding");
-                       return;
-               }
-               
-               # Perform general NAT configuration
-               if ($nathost_internal_ip_address) {
-                       if 
($self->nathost_os->firewall->can('nat_configure_host')) {
-                               if 
(!$self->nathost_os->firewall->nat_configure_host($nathost_public_ip_address, 
$nathost_internal_ip_address)) {
-                                       notify($ERRORS{'WARNING'}, 0, "unable 
to process connect methods, failed to configure NAT on $nathost_hostname");
-                                       return;
-                               }
-                       }
-                       else {
-                               notify($ERRORS{'DEBUG'}, 0, "NAT not configured 
on $nathost_hostname, " . ref($self->nathost_os->firewall) . " does not 
implement a 'nat_configure_host' subroutine");
-                       }
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "unable to configure NAT, 
nathost.publicIPaddress is not set in the database for $nathost_hostname");
-               }
-               
-               # Perform reservation-specific NAT configuration
-               if 
($self->nathost_os->firewall->can('nat_configure_reservation')) {
-                       if 
(!$self->nathost_os->firewall->nat_configure_reservation()) {
-                               notify($ERRORS{'WARNING'}, 0, "unable to 
process connect methods, failed to configure NAT on $nathost_hostname for this 
reservation");
-                               return;
-                       }
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "NAT not configured on 
$nathost_hostname for this reservation, " . ref($self->nathost_os->firewall) . 
" does not implement a 'nat_configure_reservation' subroutine");
-               }
-       }
+       my $computer_ip_address = $self->get_public_ip_address();
        
        CONNECT_METHOD: for my $connect_method_id (sort keys 
%{$connect_method_info} ) {
                my $connect_method = $connect_method_info->{$connect_method_id};
@@ -3805,11 +3861,7 @@ sub process_connect_methods {
                                                notify($ERRORS{'WARNING'}, 0, 
"$computer_node_name is assigned to NAT host $nathost_hostname but connect 
method info does not contain NAT port information:\n" . 
format_data($connect_method));
                                                return;
                                        }
-                                       
-                                       if 
($self->nathost_os->firewall->nat_add_port_forward($protocol, $nat_public_port, 
$computer_ip_address, $port)) {
-                                               notify($ERRORS{'OK'}, 0, "NAT 
port forwarding configured on $nathost_hostname for '$name' connect method: 
$nathost_public_ip_address:$nat_public_port --> $computer_ip_address:$port 
($protocol)");
-                                       }
-                                       else {
+                                       elsif 
(!$self->nathost_os->firewall->nat_add_port_forward($protocol, 
$nat_public_port, $computer_ip_address, $port)) {
                                                notify($ERRORS{'WARNING'}, 0, 
"failed to configure NAT port forwarding on $nathost_hostname for '$name' 
connect method: $nathost_public_ip_address:$nat_public_port --> 
$computer_ip_address:$port ($protocol)");
                                                return;
                                        }
@@ -5261,6 +5313,86 @@ sub unmount_nfs_shares {
 }
 
 #//////////////////////////////////////////////////////////////////////////////
+
+=head2 set_config_file_parameter
+
+ Parameters  : $file_path, $parameter_name_argument, $delimiter, 
$parameter_value_argument
+ Returns     : boolean
+ Description : Adds a parameter/value line to a text-based config file. If a
+               line already exists that matches the parameter name, it will be
+               modified if the value is different. If no line already exists
+               that matches the parameter name, a line will be added to the end
+               of the file.
+               
+               The $delimiter argument may contain spaces if a line should be
+               formatted such as: myParam = myValue
+               
+               For this example, the $delimiter argument should be ' = '.
+
+=cut
+
+sub set_config_file_parameter {
+       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 ($file_path, $parameter_name_argument, $delimiter, 
$parameter_value_argument) = @_;
+       if (!defined($file_path)) {
+               notify($ERRORS{'WARNING'}, 0, "file path argument was not 
supplied");
+               return;
+       }
+       elsif (!defined($parameter_name_argument)) {
+               notify($ERRORS{'WARNING'}, 0, "parameter name argument was not 
supplied");
+               return;
+       }
+       elsif (!defined($delimiter)) {
+               notify($ERRORS{'WARNING'}, 0, "$delimiter character argument 
was not supplied");
+               return;
+       }
+       elsif (!defined($parameter_value_argument)) {
+               notify($ERRORS{'WARNING'}, 0, "parameter value argument was not 
supplied");
+               return;
+       }
+       
+       (my $delimiter_cleaned = $delimiter) =~ s/(^\s+|\s+$)//g;
+       
+       my @original_lines = $self->get_file_contents($file_path);
+       my @updated_lines;
+       my $parameter_found = 0;
+       for my $original_line (@original_lines) {
+               if ($original_line =~ 
/^\s*$parameter_name_argument\s*$delimiter_cleaned/i) {
+                       if (!$parameter_found) {
+                               $parameter_found = 1;
+                               my $updated_line = $parameter_name_argument . 
$delimiter . $parameter_value_argument;
+                               if ($original_line ne $updated_line) {
+                                       notify($ERRORS{'DEBUG'}, 0, "updating 
line in $file_path: '$original_line' --> '$updated_line'");
+                                       push @updated_lines, $updated_line;
+                               }
+                               else {
+                                       notify($ERRORS{'DEBUG'}, 0, "existing 
line in $file_path does not need to be modified: '$original_line'");
+                                       push @updated_lines, $original_line;
+                               }
+                       }
+                       else {
+                               notify($ERRORS{'DEBUG'}, 0, "omitting duplicate 
'$parameter_name_argument' line in $file_path: '$original_line'");
+                       }
+                       next;
+               }
+               else {
+                       push @updated_lines, $original_line;
+               }
+       }
+       
+       if (!$parameter_found) {
+               push @updated_lines, $parameter_name_argument . $delimiter . 
$parameter_value_argument;
+       }
+       
+       return $self->create_text_file($file_path, join("\n", @updated_lines));
+}
+
+#//////////////////////////////////////////////////////////////////////////////
 1;
 __END__
 

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=1796111&r1=1796110&r2=1796111&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Wed May 24 22:22:40 2017
@@ -342,9 +342,11 @@ sub firewall {
                        notify($ERRORS{'DEBUG'}, 0, "$firewall_perl_package 
object could not be initialized");
                }
                else {
-                       my $address = sprintf('%x', $firewall_object);
-                       notify($ERRORS{'DEBUG'}, 0, "$firewall_perl_package 
object created, address: $address");
                        $self->{firewall} = $firewall_object;
+                       my $linux_address = sprintf('%x', $self);
+                       my $firewall_object_address = sprintf('%x', 
$firewall_object);
+                       my $self_firewall_address = sprintf('%x', 
$self->{firewall});
+                       notify($ERRORS{'DEBUG'}, 0, "$firewall_perl_package 
object created for $computer_node_name, Linux object address: $linux_address, 
firewall object address: $firewall_object_address, \$self->{firewall} address: 
$self_firewall_address");
                        return $firewall_object;
                }
        }
@@ -433,15 +435,26 @@ sub pre_capture {
        }
        
        # Configure the private and public interfaces to use DHCP
-       if (!$self->enable_dhcp($self->get_private_interface_name())) {
+       my $private_interface_name = $self->get_private_interface_name();
+       my $public_interface_name = $self->get_public_interface_name();
+       
+       if (!$self->enable_dhcp($private_interface_name)) {
                notify($ERRORS{'WARNING'}, 0, "failed to enable DHCP on the 
private interface");
                return;
        }
-       if (!$self->enable_dhcp($self->get_public_interface_name())) {
+       if (!$self->enable_dhcp($public_interface_name)) {
                notify($ERRORS{'WARNING'}, 0, "failed to enable DHCP on the 
public interface");
                return;
        }
        
+       # Delete route files if they exist for either the private or public 
interface
+       
$self->delete_file("/etc/sysconfig/network-scripts/route-$private_interface_name");
+       
$self->delete_file("/etc/sysconfig/network-scripts/route-$public_interface_name");
+       
+       # Remove computer/reservation specific lines from network file
+       $self->remove_lines_from_file('/etc/sysconfig/network', 'HOSTNAME');
+       $self->remove_lines_from_file('/etc/sysconfig/network', 'GATEWAY');
+       
        # Shut the computer down
        if ($self->{end_state} =~ /off/i) {
                notify($ERRORS{'DEBUG'}, 0, "shutting down $computer_node_name, 
provisioning module specified end state: $self->{end_state}");
@@ -926,7 +939,7 @@ sub set_static_public_address {
        }
        
        # Set default gateway
-       if (!$self->set_default_gateway($default_gateway, 
$public_interface_name)) {
+       if (!$self->set_static_default_gateway($default_gateway, 
$public_interface_name)) {
                notify($ERRORS{'WARNING'}, 0, "failed to set static public IP 
address on $computer_name, default gateway could not be set");
                return;
        }
@@ -1127,42 +1140,45 @@ sub delete_default_gateway {
 
 #//////////////////////////////////////////////////////////////////////////////
 
-=head2 set_default_gateway
+=head2 set_static_default_gateway
 
- Parameters  : $default_gateway, $interface_name (optional)
+ Parameters  : $default_gateway (optional)
  Returns     : boolean
  Description : Sets the default route. If no interface argument is supplied, 
the
                public interface is used.
 
 =cut
 
-sub set_default_gateway {
+sub set_static_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");
+       my $computer_name = $self->data->get_computer_short_name();
+       
+       my $default_gateway = shift || $self->get_correct_default_gateway();
+       if (!$default_gateway) {
+               notify($ERRORS{'WARNING'}, 0, "unable to set static default 
gateway on $computer_name, argument was not supplied and correct default 
gateway IP address could not be determined");
                return;
        }
        
-       my $computer_name = $self->data->get_computer_short_name();
+       my $current_default_gateway = $self->get_public_default_gateway();
+       if ($current_default_gateway eq $default_gateway) {
+               notify($ERRORS{'OK'}, 0, "default gateway on $computer_name is 
already set to $current_default_gateway");
+               return 1;
+       }
        
-       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;
-               }
+       my $interface_name = $self->get_public_interface_name();
+       if (!$interface_name) {
+               notify($ERRORS{'WARNING'}, 0, "unable to set static default 
gateway on $computer_name, 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)) {
@@ -1176,9 +1192,26 @@ sub set_default_gateway {
        
        # Create a route file so default route persists across reboots
        my $route_file_path = 
"/etc/sysconfig/network-scripts/route-$interface_name";
+       # For testing:
+       #$self->delete_file($route_file_path);
        my $route_file_contents = "default via $default_gateway dev 
$interface_name";
        $self->create_text_file($route_file_path, $route_file_contents);
        
+       # Adding a route-* file does not prevent computer from obtaining a 
default route via DHCP
+       # Add a 'DEFROUTE=no' line to the ifcfg-<interface> file
+       my $interface_file = 
"/etc/sysconfig/network-scripts/ifcfg-$interface_name";
+       # For testing:
+       #$self->remove_lines_from_file($interface_file, 'DEFROUTE');
+       if ($self->file_exists($interface_file)) {
+               $self->set_config_file_parameter($interface_file, 'DEFROUTE', 
'=', 'no');
+       }
+       
+       # Note: leave for future reference, this doesn't seem to work on 
CentOS/RHEL 7
+       # Add a 'GATEWAY=' line to /etc/sysconfig/network
+       #my $network_file = "/etc/sysconfig/network";
+       # For testing: $self->remove_lines_from_file($network_file, 'GATEWAY');
+       #$self->set_config_file_parameter($network_file, 'GATEWAY', '=', 
$default_gateway);
+       
        notify($ERRORS{'OK'}, 0, "set default gateway on $computer_name to 
$default_gateway, interface: $interface_name");
        return 1;
 }
@@ -5284,8 +5317,8 @@ sub get_port_connection_info {
 
  Parameters  : none
  Returns     : boolean
- Description : Enables IP forwarding by executing:
-               echo 1 > /proc/sys/net/ipv4/ip_forward
+ Description : Adds 'net.ipv4.ip_forward=1' to /etc/sysctl.conf if it doesn't
+               already exist. Executes 'sysctl -p' to apply the setting.
 
 =cut
 
@@ -5298,19 +5331,25 @@ sub enable_ip_forwarding {
        
        my $computer_node_name = $self->data->get_computer_node_name();
        
-       my $command = "echo 1 > /proc/sys/net/ipv4/ip_forward";
-       my ($exit_status, $output) = $self->execute($command, 0);
+       my $sysctl_conf_path = '/etc/sysctl.conf';
+       $self->set_config_file_parameter($sysctl_conf_path, 
'net.ipv4.ip_forward', '=', '1');
+       
+       my $command = "sysctl -p";
+       my ($exit_status, $output) = $self->execute($command);
        if (!defined($output)) {
                notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
enable IP forwarding on $computer_node_name: $command");
                return;
        }
-       elsif ($exit_status ne '0') {
-               notify($ERRORS{'WARNING'}, 0, "failed to enable IP forwarding 
on $computer_node_name, command: '$command', exit status: $exit_status, 
output:\n" . join("\n", @$output));
-               return 0;
+       
+       # Output should contain:
+       # net.ipv4.ip_forward = 1
+       if ($exit_status eq '0' || grep(/net.ipv4.ip_forward.*1/, @$output)) {
+               notify($ERRORS{'OK'}, 0, "IP forwarding is enabled on 
$computer_node_name:\n" . join("\n", @$output));
+               return 1;
        }
        else {
-               notify($ERRORS{'OK'}, 0, "verified IP forwarding is enabled on 
$computer_node_name");
-               return 1;
+               notify($ERRORS{'WARNING'}, 0, "failed to enable IP forwarding 
on $computer_node_name, command: '$command', exit status: $exit_status, 
output:\n" . join("\n", @$output));
+               return 0;
        }
 }
 

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=1796111&r1=1796110&r2=1796111&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm Wed May 24 
22:22:40 2017
@@ -534,7 +534,7 @@ sub set_static_public_address {
        }
        
        # Set the default gateway
-       if (!$self->set_default_gateway($public_default_gateway, 
$public_interface_name)) {
+       if (!$self->set_static_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;
        }

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm?rev=1796111&r1=1796110&r2=1796111&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/firewalld.pm Wed 
May 24 22:22:40 2017
@@ -392,50 +392,67 @@ sub delete_chain {
                return 0;
        }
        
-       my ($table_name, $chain_name) = @_;
+       my ($table_name, $chain_name_argument) = @_;
        if (!defined($table_name)) {
                notify($ERRORS{'WARNING'}, 0, "table name argument was not 
specified");
                return;
        }
-       elsif (!defined($chain_name)) {
+       elsif (!defined($chain_name_argument)) {
                notify($ERRORS{'WARNING'}, 0, "chain name argument was not 
specified");
                return;
        }
        
        my $computer_name = $self->data->get_computer_hostname();
        
-       # Delete all rules which reference the chain being deleted or else the 
chain can't be deleted
-       # Do this BEFORE checking if the chain exists to clean up leftover 
references in direct.xml
-       if (!$self->delete_chain_references($table_name, $chain_name)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to delete '$chain_name' 
chain from '$table_name' table on $computer_name, failed to delete all rules 
which reference the chain prior to deletion");
-               return;
-       }
-
-       $self->remove_direct_chain_rules($table_name, $chain_name) || return;
+       my @chains_deleted;
+       my @chain_names = $self->get_table_chain_names($table_name);
+       for my $chain_name (@chain_names) {
+               if ($chain_name !~ /^$chain_name_argument$/) {
+                       next;
+               }
+               
+               # Delete all rules which reference the chain being deleted or 
else the chain can't be deleted
+               # Do this BEFORE checking if the chain exists to clean up 
leftover references in direct.xml
+               if (!$self->delete_chain_references($table_name, $chain_name)) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to delete 
'$chain_name' chain from '$table_name' table on $computer_name, failed to 
delete all rules which reference the chain prior to deletion");
+                       return;
+               }
        
-       my $command = "firewall-cmd --permanent --direct --remove-chain ipv4 
$table_name $chain_name";
-       my ($exit_status, $output) = $self->os->execute($command, 0);
-       if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to execute command 
$computer_name: $command");
-               return;
-       }
-       elsif (grep(/NOT_ENABLED/i, @$output)) {
-               notify($ERRORS{'OK'}, 0, "'$chain_name' chain in '$table_name' 
does not exist on $computer_name");
-       }
-       elsif ($exit_status ne '0') {
-               notify($ERRORS{'WARNING'}, 0, "failed to delete '$chain_name' 
chain in '$table_name' table on $computer_name, exit status: $exit_status, 
command:\n$command\noutput:\n" . join("\n", @$output));
-               return 0;
-       }
-       elsif (!grep(/success/, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "potentially failed to delete 
'$chain_name' chain in '$table_name' table on $computer_name, output does not 
contain 'success', exit status: $exit_status, command:\n$command\noutput:\n" . 
join("\n", @$output));
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "deleted '$chain_name' chain in 
'$table_name' table on $computer_name");
-               #$self->save_configuration();
+               $self->remove_direct_chain_rules($table_name, $chain_name) || 
return;
+               
+               my $command = "firewall-cmd --permanent --direct --remove-chain 
ipv4 $table_name $chain_name";
+               my ($exit_status, $output) = $self->os->execute($command, 0);
+               if (!defined($output)) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to execute 
command $computer_name: $command");
+                       return;
+               }
+               elsif (grep(/NOT_ENABLED/i, @$output)) {
+                       notify($ERRORS{'OK'}, 0, "'$chain_name' chain in 
'$table_name' does not exist on $computer_name");
+               }
+               elsif ($exit_status ne '0') {
+                       notify($ERRORS{'WARNING'}, 0, "failed to delete 
'$chain_name' chain in '$table_name' table on $computer_name, exit status: 
$exit_status, command:\n$command\noutput:\n" . join("\n", @$output));
+                       return 0;
+               }
+               elsif (!grep(/success/, @$output)) {
+                       notify($ERRORS{'WARNING'}, 0, "potentially failed to 
delete '$chain_name' chain in '$table_name' table on $computer_name, output 
does not contain 'success', exit status: $exit_status, 
command:\n$command\noutput:\n" . join("\n", @$output));
+               }
+               else {
+                       notify($ERRORS{'OK'}, 0, "deleted '$chain_name' chain 
in '$table_name' table on $computer_name");
+                       #$self->save_configuration();
+               }
+               
+               if (!$self->clean_direct_xml($table_name . '.*jump\s+' . 
$chain_name)) {
+                       return;
+               }
+               
+               notify($ERRORS{'OK'}, 0, "deleted '$chain_name' chain from 
'$table_name' table on $computer_name");
+               push @chains_deleted, $chain_name;
        }
        
-       return $self->clean_direct_xml($table_name . '.*jump\s+' . $chain_name);
-       #$self->delete_chain_references($table_name, $chain_name);
+       if (!@chains_deleted) {
+               notify($ERRORS{'DEBUG'}, 0, "no chains exist in '$table_name' 
table on $computer_name matching argument: '$chain_name_argument'");
+       }
+       return 1;
 }
 
 #//////////////////////////////////////////////////////////////////////////////

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm?rev=1796111&r1=1796110&r2=1796111&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/firewall/iptables.pm Wed 
May 24 22:22:40 2017
@@ -930,10 +930,10 @@ sub get_matching_rules {
                return @matching_rules;
        }
        elsif (!defined($table_info->{$chain_name}{rules})) {
-               notify($ERRORS{'DEBUG'}, 0, "no rules match on $computer_name, 
$chain_name chain in $table_name table contains no rules");
+               notify($ERRORS{'DEBUG'}, 0, "no rules match on $computer_name, 
$chain_name chain in $table_name table contains no rules") if ($self->{debug});
                return @matching_rules;
        }
-       
+
        # This sub was designed to accept a hash reference argument to match 
other
        # parts of this module. However, we need to compare the hash reference
        # argument to the hash reference which contains current rule info. 
Comparing
@@ -952,7 +952,7 @@ sub get_matching_rules {
                notify($ERRORS{'WARNING'}, 0, "failed to determine if any rules 
match on $computer_name, attempt to collapse the rule specification hash 
reference argument produced a result with no keys:\n" . 
format_data($rule_specification_hashref));
                return;
        }
-       #notify($ERRORS{'DEBUG'}, 0, "checking if $chain_name chain in 
$table_name table on $computer_name has any rules matching specifications:\n" . 
format_data($collapsed_specification));
+       notify($ERRORS{'DEBUG'}, 0, "checking if $chain_name chain in 
$table_name table on $computer_name has any rules matching specifications:\n" . 
format_data($collapsed_specification)) if ($self->{debug});
        
        # Some iptables options may take multiple forms
        # Attempt to try all forms
@@ -962,6 +962,8 @@ sub get_matching_rules {
        };
        
        RULE: for my $rule (@{$table_info->{$chain_name}{rules}}) {
+               my $rule_specification = $rule->{rule_specification};
+               
                for my $specification_key (keys %$collapsed_specification) {
                        # Ignore comments when comparing
                        if ($specification_key =~ /(comment)/i) {
@@ -997,17 +999,22 @@ sub get_matching_rules {
                                return;
                        }
                        elsif (!defined($rule_value)) {
-                               #notify($ERRORS{'DEBUG'}, 0, "ignoring rule on 
$computer_name, it does not contain a $specification_key value");
+                               notify($ERRORS{'DEBUG'}, 0, "ignoring rule on 
$computer_name, it does not contain a $specification_key value, rule 
specification: '$rule_specification'") if ($self->{debug});
                                next RULE;
                        }
                        
                        if ($rule_value ne $specification_value && $rule_value 
!~ /^$specification_value(\/32)?$/i) {
-                               #notify($ERRORS{'DEBUG'}, 0, "ignoring rule on 
$computer_name, $specification_key value does not match, rule: '$rule_value', 
argument:'$specification_value'");
+                               #notify($ERRORS{'DEBUG'}, 0, "ignoring rule on 
$computer_name:\n" .
+                               #       "rule_specification : 
'$rule_specification'\n" .
+                               #       "specification key  : 
'$specification_key'\n" .
+                               #       "argument value     : 
'$specification_value'\n" .
+                               #       "rule value         : '$rule_value'"
+                               #);
                                next RULE;
                        }
                }
                
-               notify($ERRORS{'DEBUG'}, 0, "rule matches: " . 
$rule->{rule_specification});
+               notify($ERRORS{'DEBUG'}, 0, "rule matches: 
$rule_specification");
                push @matching_rules, $rule;
        }
        
@@ -1239,56 +1246,63 @@ sub delete_chain {
                return 0;
        }
        
-       my ($table_name, $chain_name) = @_;
+       my ($table_name, $chain_name_argument) = @_;
        if (!defined($table_name)) {
                notify($ERRORS{'WARNING'}, 0, "table name argument was not 
specified");
                return;
        }
-       elsif (!defined($chain_name)) {
+       elsif (!defined($chain_name_argument)) {
                notify($ERRORS{'WARNING'}, 0, "chain name argument was not 
specified");
                return;
        }
        
        my $computer_name = $self->data->get_computer_hostname();
        
-       my $table_info = $self->get_table_info($table_name);
-       if (!defined($table_info->{$chain_name})) {
-               notify($ERRORS{'DEBUG'}, 0, "'$chain_name' chain in 
'$table_name' table does not exist on $computer_name");
-               return 1;
-       }
-       
-       # Flush the chain first - delete will fail if the chain still contains 
rules
-       if (!$self->flush_chain($table_name, $chain_name)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to delete '$chain_name' 
chain from '$table_name' table on $computer_name, failed to flush chain prior 
to deletion");
-               return;
-       }
-       
-       # Delete all rules which reference the chain being deleted or else the 
chain can't be deleted
-       if (!$self->delete_chain_references($table_name, $chain_name)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to delete '$chain_name' 
chain from '$table_name' table on $computer_name, failed to delete all rules 
which reference the chain prior to deletion");
-               return;
+       my @chains_deleted;
+       my @chain_names = $self->get_table_chain_names($table_name);
+       for my $chain_name (@chain_names) {
+               if ($chain_name !~ /^$chain_name_argument$/) {
+                       next;
+               }
+               
+               # Flush the chain first - delete will fail if the chain still 
contains rules
+               if (!$self->flush_chain($table_name, $chain_name)) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to delete 
'$chain_name' chain from '$table_name' table on $computer_name, failed to flush 
chain prior to deletion");
+                       return;
+               }
+               
+               # Delete all rules which reference the chain being deleted or 
else the chain can't be deleted
+               if (!$self->delete_chain_references($table_name, $chain_name)) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to delete 
'$chain_name' chain from '$table_name' table on $computer_name, failed to 
delete all rules which reference the chain prior to deletion");
+                       return;
+               }
+               
+               my $command = "/sbin/iptables --delete-chain $chain_name 
--table $table_name";
+               
+               my $semaphore = $self->get_iptables_semaphore();
+               my ($exit_status, $output) = $self->os->execute($command, 0);
+               if (!defined($output)) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to execute 
command $computer_name: $command");
+                       return;
+               }
+               elsif (grep(/Too many links/i, @$output)) {
+                       notify($ERRORS{'WARNING'}, 0, "unable to delete 
'$chain_name' chain from '$table_name' table on $computer_name, the chain is 
referenced by another rule");
+                       return;
+               }
+               elsif ($exit_status ne '0') {
+                       notify($ERRORS{'WARNING'}, 0, "failed to delete 
'$chain_name' chain from '$table_name' table on $computer_name, exit status: 
$exit_status, command:\n$command\noutput:\n" . join("\n", @$output));
+                       return;
+               }
+               else {
+                       notify($ERRORS{'OK'}, 0, "deleted '$chain_name' chain 
from '$table_name' table on $computer_name");
+                       push @chains_deleted, $chain_name;
+               }
        }
        
-       my $command = "/sbin/iptables --delete-chain $chain_name --table 
$table_name";
-       
-       my $semaphore = $self->get_iptables_semaphore();
-       my ($exit_status, $output) = $self->os->execute($command, 0);
-       if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to execute command 
$computer_name: $command");
-               return;
-       }
-       elsif (grep(/Too many links/i, @$output)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to delete '$chain_name' 
chain from '$table_name' table on $computer_name, the chain is referenced by 
another rule");
-               return 0;
-       }
-       elsif ($exit_status ne '0') {
-               notify($ERRORS{'WARNING'}, 0, "failed to delete '$chain_name' 
chain from '$table_name' table on $computer_name, exit status: $exit_status, 
command:\n$command\noutput:\n" . join("\n", @$output));
-               return 0;
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "deleted '$chain_name' chain from 
'$table_name' table on $computer_name");
-               return 1;
+       if (!@chains_deleted) {
+               notify($ERRORS{'DEBUG'}, 0, "no chains exist in '$table_name' 
table on $computer_name matching argument: '$chain_name_argument'");
        }
+       return 1;
 }
 
 #//////////////////////////////////////////////////////////////////////////////
@@ -1405,7 +1419,7 @@ sub get_table_chain_names {
        
        my $table_info = $self->get_table_info($table_name, 1) || return;
        my @table_chain_names = sort keys %$table_info;
-       notify($ERRORS{'DEBUG'}, 0, "retrieved chain names defined in 
$table_name table on $computer_name:\n" . join("\n", @table_chain_names));
+       notify($ERRORS{'DEBUG'}, 0, "retrieved chain names defined in 
$table_name table on $computer_name: " . join(', ', @table_chain_names)) if 
($self->{debug});
        return @table_chain_names;
 }
 
@@ -1428,7 +1442,7 @@ sub nat_sanitize_reservation {
        }
        
        my $reservation_id = shift || $self->data->get_reservation_id();
-       my $reservation_chain_name = 
$self->get_reservation_chain_name($reservation_id);
+       my $reservation_chain_name = 
$self->get_nat_reservation_chain_name($reservation_id);
        
        if (!$self->delete_chain('nat', $reservation_chain_name)) {
                return;
@@ -1908,7 +1922,7 @@ sub get_table_info {
 
 =head2 nat_configure_host
 
- Parameters  : $public_ip_address, $internal_ip_address
+ Parameters  : none
  Returns     : boolean
  Description : Configures the iptables firewall to pass NAT traffic.
 
@@ -1922,16 +1936,10 @@ sub nat_configure_host {
        }
        
        my $computer_name = $self->data->get_computer_hostname();
+       my $public_ip_address = $self->data->get_nathost_public_ip_address();
+       my $internal_ip_address = 
$self->data->get_nathost_internal_ip_address();
        
-       my ($public_ip_address, $internal_ip_address) = @_;
-       if (!$public_ip_address) {
-               notify($ERRORS{'WARNING'}, 0, "unable to automatically 
configure NAT, nathost public IP address argument was not specified");
-               return;
-       }
-       if (!$internal_ip_address) {
-               notify($ERRORS{'WARNING'}, 0, "unable to automatically 
configure NAT, nathost internal IP address argument was not specified");
-               return;
-       }
+       my $nat_host_chain_name = $self->get_nat_host_chain_name();
        
        # Enable IP port forwarding
        if (!$self->os->enable_ip_forwarding()) {
@@ -1954,11 +1962,18 @@ sub nat_configure_host {
        }
        
        # Check if NAT has previously been configured
-       for my $rule (@{$nat_table_info->{POSTROUTING}{rules}}) {
-               my $rule_specification_string = $rule->{rule_specification};
-               if ($rule_specification_string =~ /MASQUERADE/) {
-                       notify($ERRORS{'DEBUG'}, 0, "POSTROUTING chain in nat 
table contains a MASQUERADE rule, assuming NAT has already been configured: 
$rule_specification_string");
-                       return 1;
+       if (defined($nat_table_info->{$nat_host_chain_name})) {
+               notify($ERRORS{'DEBUG'}, 0, "NAT has already been configured on 
$computer_name, '$nat_host_chain_name' chain exists in nat table");
+               return 1;
+       }
+       else {
+               # Before VCL 2.5, dedicated NAT host chain wasn't created, 
check if MASQUERADE rule exists
+               for my $rule (@{$nat_table_info->{POSTROUTING}{rules}}) {
+                       my $rule_specification_string = 
$rule->{rule_specification};
+                       if ($rule_specification_string =~ /MASQUERADE/) {
+                               notify($ERRORS{'DEBUG'}, 0, "POSTROUTING chain 
in nat table contains a MASQUERADE rule, assuming NAT has already been 
configured: $rule_specification_string");
+                               return 1;
+                       }
                }
        }
        
@@ -2011,16 +2026,64 @@ sub nat_configure_host {
                $destination_ports .= "$start_port:$end_port";
        }
        
+       
+       $self->create_chain('filter', $nat_host_chain_name);
+       $self->create_chain('nat', $nat_host_chain_name);
+       if (!$self->insert_rule('filter', 'INPUT',
+               {
+                       'parameters' => {
+                               'jump' => $nat_host_chain_name,
+                       },
+                       'match_extensions' => {
+                               'comment' => {
+                                       'comment' => "VCL: jump from filter 
table INPUT chain to NAT host $nat_host_chain_name chain",
+                               },
+                       },
+               }
+       )) {
+               return;
+       }
+       
+       if (!$self->insert_rule('filter', 'FORWARD',
+               {
+                       'parameters' => {
+                               'jump' => $nat_host_chain_name,
+                       },
+                       'match_extensions' => {
+                               'comment' => {
+                                       'comment' => "VCL: jump from filter 
table FORWARD chain to NAT host $nat_host_chain_name chain",
+                               },
+                       },
+               }
+       )) {
+               return;
+       }
+       
        if (!$self->insert_rule('nat', 'POSTROUTING',
                {
                        'parameters' => {
+                               'jump' => $nat_host_chain_name,
+                       },
+                       'match_extensions' => {
+                               'comment' => {
+                                       'comment' => "VCL: jump from nat table 
POSTROUTING chain to to NAT host $nat_host_chain_name chain",
+                               },
+                       },
+               }
+       )) {
+               return;
+       }
+       
+       if (!$self->insert_rule('nat', $nat_host_chain_name,
+               {
+                       'parameters' => {
                                'out-interface' => $public_interface_name,
                                '!destination' => 
"$internal_network_address/$internal_network_bits",
                                'jump' => 'MASQUERADE',
                        },
                        'match_extensions' => {
                                'comment' => {
-                                       'comment' => "change IP of outbound 
$public_interface_name packets to NAT host IP address $public_ip_address",
+                                       'comment' => "VCL: change IP of 
outbound $public_interface_name packets to NAT host IP address 
$public_ip_address",
                                },
                        },
                }
@@ -2028,7 +2091,7 @@ sub nat_configure_host {
                return;
        }
        
-       if (!$self->insert_rule('filter', 'INPUT',
+       if (!$self->insert_rule('filter', $nat_host_chain_name,
                {
                        'parameters' => {
                                'in-interface' => $public_interface_name,
@@ -2049,7 +2112,7 @@ sub nat_configure_host {
                return;
        }
        
-       if (!$self->insert_rule('filter', 'INPUT',
+       if (!$self->insert_rule('filter', $nat_host_chain_name,
                {
                        'parameters' => {
                                'in-interface' => $public_interface_name,
@@ -2070,7 +2133,7 @@ sub nat_configure_host {
                return;
        }
        
-       if (!$self->insert_rule('filter', 'FORWARD',
+       if (!$self->insert_rule('filter', $nat_host_chain_name,
                {
                        'parameters' => {
                                'in-interface' => $public_interface_name,
@@ -2090,7 +2153,7 @@ sub nat_configure_host {
                return;
        }
        
-       if (!$self->insert_rule('filter', 'FORWARD',
+       if (!$self->insert_rule('filter', $nat_host_chain_name,
                {
                        'parameters' => {
                                'in-interface' => $internal_interface_name,
@@ -2109,6 +2172,7 @@ sub nat_configure_host {
        )) {
                return;
        }
+
        
        $self->save_configuration();
        notify($ERRORS{'DEBUG'}, 0, "successfully configured NAT on 
$computer_name");
@@ -2143,7 +2207,7 @@ sub nat_configure_reservation {
                return;
        }
        
-       my $chain_name = $self->get_reservation_chain_name();
+       my $chain_name = $self->get_nat_reservation_chain_name();
        
        # Check if chain for reservation has already been created
        if (defined($nat_table_info->{$chain_name})) {
@@ -2216,7 +2280,7 @@ sub nat_add_port_forward {
                return;
        }
        
-       my $chain_name = $self->get_reservation_chain_name();
+       my $chain_name = $self->get_nat_reservation_chain_name();
        
        $protocol = lc($protocol);
        
@@ -2400,7 +2464,28 @@ sub get_reserved_chain_name {
 
 #//////////////////////////////////////////////////////////////////////////////
 
-=head2 get_reservation_chain_name
+=head2 get_nat_host_chain_name
+
+ Parameters  : none
+ Returns     : string
+ Description : Returns the name of the iptables chain on the NAT host 
containing
+               rules for NAT to function. Returns 'vcl-nat_host'.
+
+=cut
+
+sub get_nat_host_chain_name {
+       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 0;
+       }
+       
+       return 'vcl-nat_host';
+}
+
+#//////////////////////////////////////////////////////////////////////////////
+
+=head2 get_nat_reservation_chain_name
 
  Parameters  : $reservation_id (optional)
  Returns     : string
@@ -2409,7 +2494,7 @@ sub get_reserved_chain_name {
 
 =cut
 
-sub get_reservation_chain_name {
+sub get_nat_reservation_chain_name {
        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");

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=1796111&r1=1796110&r2=1796111&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Wed May 24 22:22:40 
2017
@@ -851,7 +851,7 @@ sub post_load {
                                notify($ERRORS{'DEBUG'}, 0, "computer initially 
failed to obtain a public IP address from DHCP, executed 'ipconfig /renew', 
public IP address could then be determined");
                        }
                }
-               else { 
+               else {
                        notify($ERRORS{'WARNING'}, 0, "management node failed 
to set a static public IP address on the computer");
                        return;
                }
@@ -863,7 +863,7 @@ sub post_load {
 
 =cut
 
-       if (!$self->set_public_default_route()) {
+       if (!$self->set_static_default_gateway()) {
                notify($ERRORS{'WARNING'}, 0, "unable to set persistent public 
default route");
        }
 
@@ -8568,7 +8568,7 @@ EOF
                notify($ERRORS{'OK'}, 0, "set static public IP address: 
$computer_public_ip_address/$subnet_mask, default gateway: $default_gateway");
        }
 
-       $self->set_public_default_route() || return;
+       $self->set_static_default_gateway() || return;
        
        $self->set_static_dns_servers() || return;
        
@@ -8747,42 +8747,27 @@ sub delete_default_routes {
 
 #//////////////////////////////////////////////////////////////////////////////
 
-=head2 set_public_default_route
+=head2 set_static_default_gateway
 
- Parameters  : None
- Returns     : If successful: true
-               If failed: false
+ Parameters  : $default_gateway (optional)
+ Returns     : boolean
  Description : Adds a persistent route to the default gateway for the public
                network.
 
 =cut
 
-sub set_public_default_route {
+sub set_static_default_gateway {
        my $self = shift;
        unless (ref($self) && $self->isa('VCL::Module')) {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called 
as a VCL::Module module object method");
                return;
        }
        
-       # Check the management node's DHCP IP configuration mode
-       # Get the default gateway address
-       my $default_gateway;
-       my $ip_configuration = 
$self->data->get_management_node_public_ip_configuration();
-       if ($ip_configuration && $ip_configuration =~ /static/i) {
-               # Static addresses used, get default gateway address configured 
for management node
-               $default_gateway = 
$self->data->get_management_node_public_default_gateway();
-       }
-       else {
-               # Dynamic addresses used, get default gateway address assigned 
to computer
-               $default_gateway = $self->get_public_default_gateway();
-               if (!$default_gateway) {
-                       $default_gateway = 
$self->data->get_management_node_public_default_gateway();
-               }
-       }
+       my $computer_name = $self->data->get_computer_short_name();
        
-       # Make sure default gateway was retrieved
+       my $default_gateway = shift || $self->get_correct_default_gateway();
        if (!$default_gateway) {
-               notify($ERRORS{'WARNING'}, 0, "unable to retrieve default 
gateway address");
+               notify($ERRORS{'WARNING'}, 0, "unable to set static default 
gateway on $computer_name, argument was not supplied and correct default 
gateway IP address could not be determined");
                return;
        }
        
@@ -8794,7 +8779,7 @@ sub set_public_default_route {
        }
        
        # Add a persistent route to the public default gateway
-       my $route_add_command    = "route -p ADD 0.0.0.0 MASK 0.0.0.0 
$default_gateway METRIC 1";
+       my $route_add_command = "route -p ADD 0.0.0.0 MASK 0.0.0.0 
$default_gateway METRIC 1";
        my ($route_add_exit_status, $route_add_output) = 
$self->execute($route_add_command);
        if (!defined($route_add_output)) {
                notify($ERRORS{'WARNING'}, 0, "failed to execute command to add 
persistent route to public default gateway: $default_gateway");

Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1796111&r1=1796110&r2=1796111&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Wed May 24 22:22:40 2017
@@ -1228,7 +1228,7 @@ sub check_time {
                }
                else {
                        # End time is now or in the future
-                       notify($ERRORS{'DEBUG'}, 0, "reservation end time is 
either right now or in the future ($end_diff_minutes), returning 0");
+                       #notify($ERRORS{'DEBUG'}, 0, "reservation end time is 
either right now or in the future ($end_diff_minutes), returning 0");
                        return "0";
                }
        }    # Close if state is complete or failed


Reply via email to