#!/usr/bin/perl # # This keeps an eye on the network configuration and ensures the firewall is configured appropriately. What # exactly that means depends on why kind of machine the local host is. # # Exit codes; # 0 = Normal exit. # 1 = Failed to unlink an unneeded file. # 2 = Failed to write or update a file. # # TODO: # # # Allow routing/masq'ing through the IFN1 (provide net access to the BCN) # firewall-cmd --zone=IFN1 --add-masquerade # # Check # firewall-cmd --zone=IFN1 --query-masquerade # #[yes|no] # # Disable # # NOTE: Doesn't break existing connections # firewall-cmd --zone=IFN1 --remove-masquerade # use strict; use warnings; use Anvil::Tools; use Data::Dumper; use Text::Diff; # Disable buffering $| = 1; my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; if (($running_directory =~ /^\./) && ($ENV{PWD})) { $running_directory =~ s/^\./$ENV{PWD}/; } my $anvil = Anvil::Tools->new(); # Read switches $anvil->Get->switches({list => [ 'job-uuid', "server"], man => $THIS_FILE}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }}); $anvil->Database->connect(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132" }); if (not $anvil->data->{sys}{database}{connections}) { # No databases, exit. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, priority => "err", key => "error_0003"}); $anvil->nice_exit({exit_code => 1}); } # Log our start. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0134"}); # If we've been passed a job UUID, pick up the details. if ($anvil->data->{switches}{'job-uuid'}) { $anvil->Job->clear(); $anvil->Job->get_job_details(); # $anvil->Job->update_progress({ # progress => 1, # job_picked_up_by => $$, # job_picked_up_at => time, # message => "message_0134", # }); $anvil->Job->update_progress({ progress => 100, job_picked_up_by => $$, job_picked_up_at => time, message => "message_0134", }); exit(0); if ($anvil->data->{jobs}{job_data} =~ /server=(.*)$/) { $anvil->data->{switches}{server} = $1 if not $anvil->data->{switches}{server}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'switches::server' => $anvil->data->{switches}{server}, }}); wait_for_server($anvil); } } exit(0); # If the user has disabled auto-management of the firewall, exit. if (not $anvil->data->{sys}{manage}{firewall}) { # Do nothing. $anvil->nice_exit({exit_code => 0}); } $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); # This used to do all the work, but that's now moved to the method below. So all we do here now is call it. $anvil->Network->manage_firewall(); if ($anvil->data->{switches}{'job-uuid'}) { $anvil->Job->update_progress({ progress => 100, message => "job_0281", }); } # We're done $anvil->nice_exit({exit_code => 0}); ############################################################################################################# # Private functions. # ############################################################################################################# # This simple watches 'virsh list' until the named server appears. sub wait_for_server { ($anvil) = @_; $anvil->Job->update_progress({ progress => 25, message => "job_0401,!!server!".$anvil->data->{switches}{server}."!!", }); my $wait_until = time + 60; my $waiting = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { wait_until => $wait_until, }}); while($waiting) { my $shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." list --name"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { shell_call => $shell_call }}); my ($output, $return_code) = $anvil->System->call({debug => 3, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { 's1:output' => $output, 's2:return_code' => $return_code, }}); foreach my $server (split/\n/, $output) { $server = $anvil->Words->clean_spaces({string => $server}); next if not $server; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { server => $server }}); if ($server eq $anvil->data->{switches}{server}) { # Found it. $waiting = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { waiting => $waiting }}); } } if ($waiting) { if (time > $wait_until) { # timed out $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, priority => "err", key => "job_0402", variables => { server => $anvil->data->{switches}{server} }}); $anvil->Job->update_progress({ progress => 75, message => "job_0402,!!server!".$anvil->data->{switches}{server}."!!", }); } else { sleep 3; my $time_left = $wait_until - time; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "job_0403", variables => { server => $anvil->data->{switches}{server}, time_left => $time_left, }}); $anvil->Job->update_progress({ progress => 50, message => "job_0403,!!server!".$anvil->data->{switches}{server}."!!,!!time_left!".$time_left."!!", }); } } } return(0); }