Author: arkurth
Date: Tue May 23 23:01:09 2017
New Revision: 1795977
URL: http://svn.apache.org/viewvc?rev=1795977&view=rev
Log:
VCL-1049
Added subroutines:
* iptables.pm::nat_delete_orphaned_reservation_chains
* iptables.pm::get_table_chain_names
* utils.pm::get_all_reservation_ids
VCL-1031
Updated regex's in iptables.pm::get_table_info to detect exclamation marks
enclosed in single quotes, as may be returned by 'firewall-cmd --permanent
--direct --get-all-rules'. The quotes were throwing off the detection of a
MASQERADE rule when a CentOS 7/firewalld host is used as a NAT host.
Commented out some notify messages in iptables.pm and firewalld.pm which were
generating a lot of noise.
Modified:
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/utils.pm
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=1795977&r1=1795976&r2=1795977&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 Tue
May 23 23:01:09 2017
@@ -174,7 +174,7 @@ sub get_all_direct_rules {
# ipv4 filter INPUT 0 --jump vcl-pre_capture --match comment --comment
'VCL: jump to rules added during the pre-capture stage (2017-04-07 17:19:21)'
my @rules = grep(/^(ipv4|ipv6|eb)/, @$output);
- notify($ERRORS{'DEBUG'}, 0, "retrieved all firewalld direct rules
defined on $computer_name:\n" . join("\n", @rules));
+ #notify($ERRORS{'DEBUG'}, 0, "retrieved all firewalld direct rules
defined on $computer_name:\n" . join("\n", @rules));
return @rules;
}
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=1795977&r1=1795976&r2=1795977&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 Tue
May 23 23:01:09 2017
@@ -1380,6 +1380,37 @@ sub chain_exists {
#//////////////////////////////////////////////////////////////////////////////
+=head2 get_table_chain_names
+
+ Parameters : $table_name
+ Returns : array
+ Description : Returns an array containing the chain names defined for a table.
+
+=cut
+
+sub get_table_chain_names {
+ 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;
+ }
+
+ my ($table_name) = @_;
+ if (!defined($table_name)) {
+ notify($ERRORS{'WARNING'}, 0, "table name argument was not
specified");
+ return;
+ }
+
+ my $computer_name = $self->data->get_computer_hostname();
+
+ 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));
+ return @table_chain_names;
+}
+
+#//////////////////////////////////////////////////////////////////////////////
+
=head2 nat_sanitize_reservation
Parameters : $reservation_id (optional)
@@ -1564,6 +1595,7 @@ sub get_table_info {
if ($self->can('get_all_direct_rules')) {
# Convert:
# ipv4 filter vcl-pre_capture 0 --jump ACCEPT --protocol tcp
--match comment --comment 'VCL: ...' --match tcp --destination-port 22
+ # ipv4 nat POSTROUTING 0 '!' --destination 10.0.0.0/20
--jump MASQUERADE --out-interface eth1 --match comment --comment 'blah... blah'
# To:
# -A vcl-pre_capture -p tcp -m comment --comment "VCL: ..."
-m tcp --dport 22 -j ACCEPT
DIRECT_RULE: for my $direct_rule
($self->get_all_direct_rules()) {
@@ -1581,15 +1613,15 @@ sub get_table_info {
next DIRECT_RULE;
}
elsif ($rule_table ne $table_name) {
- notify($ERRORS{'DEBUG'}, 0, "ignoring rule,
table does not match '$table_name': $direct_rule");
+ #notify($ERRORS{'DEBUG'}, 0, "ignoring rule,
table does not match '$table_name': $direct_rule");
next DIRECT_RULE;
}
my $converted_rule = "-A $rule_chain
$rule_specification";
- notify($ERRORS{'DEBUG'}, 0, "converted iptables direct
rule to iptables format:\n" .
- "direct rule : $direct_rule\n" .
- "iptables format : $converted_rule"
- );
+ #notify($ERRORS{'DEBUG'}, 0, "converted iptables direct
rule to iptables format:\n" .
+ # "direct rule : $direct_rule\n" .
+ # "iptables format : $converted_rule"
+ #);
push @lines, $converted_rule;
}
}
@@ -1629,6 +1661,13 @@ sub get_table_info {
# Remove spaces from end of rule specification
$rule_specification_string =~ s/\s+$//;
+ #notify($ERRORS{'DEBUG'}, 0, "split iptables line:\n" .
+ # "line : '$line'\n" .
+ # "command : '$iptables_command'\n" .
+ # "chain : '$chain_name'\n" .
+ # "specification : '$rule_specification_string'"
+ #);
+
if ($iptables_command =~ /^(-P|--policy)/) {
# -P, --policy chain target (Set the policy for the
chain to the given target)
$table_info->{$chain_name}{policy} =
$rule_specification_string;
@@ -1648,13 +1687,15 @@ sub get_table_info {
$rule->{rule_specification} =
$rule_specification_string;
# Parse the rule parameters
+ # Be sure to check for ! enclosed in quotes:
+ # -A POSTROUTING '!' --destination 10.10.0.0/20
--jump MASQUERADE
my $parameters = {
- 'protocol' =>
'\s*(\!?)\s*(-p|--protocol)\s+([^\s]+)',
- 'source' =>
'\s*(\!?)\s*(-s|--source)\s+([\d\.\/]+)',
- 'destination' =>
'\s*(\!?)\s*(-d|--destination)\s+([\d\.\/]+)',
- 'in-interface' =>
'\s*(\!?)\s*(-i|--in-interface)\s+([^\s]+)',
- 'out-interface' =>
'\s*(\!?)\s*(-o|--out-interface)\s+([^\s]+)',
- 'fragment' => '\s*(\!?)\s*(-f|--fragment)',
+ 'protocol' =>
'\s*\'?(\!?)\'?\s*(-p|--protocol)\s+([^\s]+)',
+ 'source' =>
'\s*\'?(\!?)\'?\s*(-s|--source)\s+([\d\.\/]+)',
+ 'destination' =>
'\s*\'?(\!?)\'?\s*(-d|--destination)\s+([\d\.\/]+)',
+ 'in-interface' =>
'\s*\'?(\!?)\'?\s*(-i|--in-interface)\s+([^\s]+)',
+ 'out-interface' =>
'\s*\'?(\!?)\'?\s*(-o|--out-interface)\s+([^\s]+)',
+ 'fragment' =>
'\s*\'?(\!?)\'?\s*(-f|--fragment)',
};
PARAMETER: for my $parameter (keys %$parameters) {
@@ -1724,7 +1765,7 @@ sub get_table_info {
}
elsif (!$target_extension_option_name) {
# If here, the section should
be a target extension option value
- notify($ERRORS{'WARNING'}, 0,
"failed to parse iptables rule, target extension option name was not detected
before this section: '$target_extension_option_section'\n" .
+ notify($ERRORS{'WARNING'}, 0,
"failed to parse iptables rule on $computer_name, target extension option name
was not detected before this section: '$target_extension_option_section'\n" .
"output line: $line\n" .
"preceeding target
parameter: $target_parameter\n" .
"target value: $target"
@@ -1799,9 +1840,11 @@ sub get_table_info {
next MATCH_EXTENSION_SECTION;
}
else {
- notify($ERRORS{'WARNING'}, 0,
"failed to parse iptables rule, match extension module name was not detected
before this section: '$match_extension_section'\n" .
- "iptables rule
specification: $rule_specification_string\n" .
- "iptables command:
$line"
+ notify($ERRORS{'WARNING'}, 0,
"failed to parse iptables rule in $table_name table on $computer_name\n" .
+ "match extension module
name was not detected before this section:\n" .
+ "match extension
section:\n$match_extension_section\n" .
+ "iptables rule
specification:\n$rule_specification_string\n" .
+ "iptables command:
\n$line"
);
next LINE;
}
@@ -2067,6 +2110,7 @@ sub nat_configure_host {
return;
}
+ $self->save_configuration();
notify($ERRORS{'DEBUG'}, 0, "successfully configured NAT on
$computer_name");
return 1;
}
@@ -2237,6 +2281,7 @@ sub nat_add_port_forward {
}
)) {
notify($ERRORS{'OK'}, 0, "added NAT port forward on
$computer_name: $public_interface_name:$source_port -->
$destination_ip_address:$destination_port");
+ $self->save_configuration();
return 1;
}
else {
@@ -2410,6 +2455,80 @@ sub get_cluster_chain_name {
}
#//////////////////////////////////////////////////////////////////////////////
+
+=head2 nat_delete_orphaned_reservation_chains
+
+ Parameters : none
+ Returns : boolean
+ Description : Checks all of the chains that exist in the nat table on a NAT
+ host. Chains which don't begin with the vcld process name
+ followed by a hyphen (ex. 'vcld-') are ignored. Retrieves list
of
+ all reservation IDs currently in the database. If a chain exists
+ but a corresponding reservation does not, the chain is deleted.
+
+=cut
+
+sub nat_delete_orphaned_reservation_chains {
+ 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;
+ }
+
+ my $computer_name = $self->data->get_computer_hostname();
+
+ my @reservation_ids = get_all_reservation_ids();
+ if (!@reservation_ids) {
+ notify($ERRORS{'WARNING'}, 0, "not deleting orphaned
reservation chains on $computer_name, failed to retrieve all reservation IDs
from the database");
+ return;
+ }
+ my %reservation_id_hash = map { $_ => 1 } @reservation_ids;
+
+ my @chain_names = $self->get_table_chain_names('nat');
+ my @chains_ignored;
+ my @chains_with_reservation;
+ my @chains_deleted;
+
+ for my $chain_name (@chain_names) {
+ if ($chain_name !~ /^$PROCESSNAME-/) {
+ notify($ERRORS{'DEBUG'}, 0, "ignoring chain in nat
table on $computer_name: $chain_name, name does not begin with
'$PROCESSNAME-'");
+ push @chains_ignored, $chain_name;
+ next;
+ }
+ my ($chain_reservation_id) = $chain_name =~
/^$PROCESSNAME-(\d+)$/;
+ if (!defined($chain_reservation_id)) {
+ notify($ERRORS{'DEBUG'}, 0, "ignoring chain in nat
table on $computer_name: $chain_name, reservation ID could not be determined
from chain name, pattern: '$PROCESSNAME-<reservation ID>'");
+ push @chains_ignored, $chain_name;
+ next;
+ }
+ elsif (defined($reservation_id_hash{$chain_reservation_id})) {
+ notify($ERRORS{'DEBUG'}, 0, "ignoring chain in nat
table on $computer_name: $chain_name, reservation $chain_reservation_id
exists");
+ push @chains_with_reservation, $chain_name;
+ next;
+ }
+
+ notify($ERRORS{'OK'}, 0, "deleting orphaned chain in nat table
on $computer_name: $chain_name, reservation $chain_reservation_id does NOT
exist");
+ if ($self->delete_chain('nat', $chain_name)) {
+ push @chains_deleted, $chain_name;
+ }
+ else {
+ return;
+ }
+ }
+
+ if (scalar(@chains_deleted)) {
+ $self->save_configuration();
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "checked for orphaned reservation chains on
NAT host $computer_name:\n" .
+ "chains ignored (" . scalar(@chains_ignored) . "): " . join(',
', @chains_ignored) . "\n" .
+ "chains with a current reservation (" .
scalar(@chains_with_reservation) . "): " . join(', ', @chains_with_reservation)
. "\n" .
+ "chains deleted (" . scalar(@chains_deleted) . "): " . join(',
', @chains_deleted)
+ );
+ return 1;
+}
+
+#//////////////////////////////////////////////////////////////////////////////
=head2 DESTROY
Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1795977&r1=1795976&r2=1795977&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Tue May 23 23:01:09 2017
@@ -119,6 +119,7 @@ our @EXPORT = qw(
format_hash_keys
format_number
get_active_directory_domain_credentials
+ get_all_reservation_ids
get_affiliation_info
get_array_intersection
get_block_request_image_info
@@ -8234,6 +8235,24 @@ sub get_reservation_request_id {
}
#//////////////////////////////////////////////////////////////////////////////
+
+=head2 get_all_reservation_ids
+
+ Parameters : none
+ Returns : array
+ Description : Retrieves the IDs of all reservations regardless of state or any
+ other attributes.
+
+=cut
+
+sub get_all_reservation_ids {
+ my @rows = database_select('SELECT id FROM reservation');
+ my @reservation_ids = sort {$a <=> $b} map { $_->{id} } @rows;
+ notify($ERRORS{'DEBUG'}, 0, "retrieved all reservation IDs currently
defined in the database: " . join(', ', @reservation_ids));
+ return @reservation_ids;
+}
+
+#//////////////////////////////////////////////////////////////////////////////
=head2 get_reservation_request_info