From 217dfaedc72c5981b44d0d5e8bfcb9eca4f74c09 Mon Sep 17 00:00:00 2001 From: Digimer Date: Sat, 31 Mar 2018 02:01:38 -0400 Subject: [PATCH] * Created System->pids() to read in all process data and, optionally, return an array reference of PIDs matching a string (program name). * Got tools/anvil-configure-network to exit if another instance is running. If not, it now starts (barely) the process of configuring the network. Signed-off-by: Digimer --- Anvil/Tools.pm | 1 + Anvil/Tools/System.pm | 131 ++++++++++++++++++++++++++++++++++ tools/anvil-configure-network | 125 +++++++++++++++++++++++++++++--- 3 files changed, 249 insertions(+), 8 deletions(-) diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index ae745ae4..53c844f5 100755 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -775,6 +775,7 @@ sub _set_paths 'mkdir' => "/usr/bin/mkdir", ping => "/usr/bin/ping", pgrep => "/usr/bin/pgrep", + ps => "/usr/bin/ps", psql => "/usr/bin/psql", 'postgresql-setup' => "/usr/bin/postgresql-setup", pwd => "/usr/bin/pwd", diff --git a/Anvil/Tools/System.pm b/Anvil/Tools/System.pm index b8cd242f..230e7b12 100755 --- a/Anvil/Tools/System.pm +++ b/Anvil/Tools/System.pm @@ -782,6 +782,137 @@ sub manage_firewall return($open); } +=head2 pids + +This parses 'ps aux' and stores the information about running programs in C<< pids:::: >>. + +Optionally, if the C<< program_name >> parameter is set, an array of PIDs for that program will be returned. + +Parameters; + +=head3 ignore_me (optional) + +If set to '1', the PID of this program is ignored. + +=head3 program_name (optional) + +This is an option string that is searched for in the 'command' portion of the 'ps aux' call. If this string matches, the PID is added to the array reference returned by this method. + +=cut +sub pids +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + + my $ignore_me = defined $parameter->{ignore_me} ? $parameter->{ignore_me} : ""; + my $program_name = defined $parameter->{program_name} ? $parameter->{program_name} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + ignore_me => $ignore_me, + program_name => $program_name, + }}); + + # If we stored this data before, delete it as it is now stale. + if (exists $anvil->{pids}) + { + delete $anvil->{pids}; + } + my $my_pid = $$; + my $pids = []; + my $shell_call = $anvil->data->{path}{exe}{ps}." aux"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + my $output = $anvil->System->call({shell_call => $shell_call}); + foreach my $line (split/\n/, $output) + { + $line = $anvil->Words->clean_spaces({ string => $line }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); + + if ($line =~ /^\S+ \d+ /) + { + my ($user, $pid, $cpu, $memory, $virtual_memory_size, $resident_set_size, $control_terminal, $state_codes, $start_time, $time, $command) = ($line =~ /^(\S+) (\d+) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*)$/); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + user => $user, + pid => $pid, + cpu => $cpu, + memory => $memory, + virtual_memory_size => $virtual_memory_size, + resident_set_size => $resident_set_size, + control_terminal => $control_terminal, + state_codes => $state_codes, + start_time => $start_time, + 'time' => $time, + command => $command, + }}); + + if ($ignore_me) + { + if ($pid eq $my_pid) + { + # This is us! :D + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + pid => $pid, + my_pid => $my_pid, + }}); + next; + } + elsif (($command =~ /--status/) or ($command =~ /--state/)) + { + # Ignore this, it is someone else also checking the state. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { command => $command }}); + next; + } + elsif ($command =~ /\/timeout (\d)/) + { + # Ignore this, we were called by 'timeout' so the pid will be + # different but it is still us. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { command => $command }}); + next; + } + } + + # Store by PID + $anvil->{pids}{$pid}{user} = $user; + $anvil->{pids}{$pid}{cpu} = $cpu; + $anvil->{pids}{$pid}{memory} = $memory; + $anvil->{pids}{$pid}{virtual_memory_size} = $virtual_memory_size; + $anvil->{pids}{$pid}{resident_set_size} = $resident_set_size; + $anvil->{pids}{$pid}{control_terminal} = $control_terminal; + $anvil->{pids}{$pid}{state_codes} = $state_codes; + $anvil->{pids}{$pid}{start_time} = $start_time; + $anvil->{pids}{$pid}{'time'} = $time; + $anvil->{pids}{$pid}{command} = $command; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "pids::${pid}::cpu" => $anvil->{pids}{$pid}{cpu}, + "pids::${pid}::memory" => $anvil->{pids}{$pid}{memory}, + "pids::${pid}::virtual_memory_size" => $anvil->{pids}{$pid}{virtual_memory_size}, + "pids::${pid}::resident_set_size" => $anvil->{pids}{$pid}{resident_set_size}, + "pids::${pid}::control_terminal" => $anvil->{pids}{$pid}{control_terminal}, + "pids::${pid}::state_codes" => $anvil->{pids}{$pid}{state_codes}, + "pids::${pid}::start_time" => $anvil->{pids}{$pid}{start_time}, + "pids::${pid}::time" => $anvil->{pids}{$pid}{'time'}, + "pids::${pid}::command" => $anvil->{pids}{$pid}{command}, + }}); + + if ($command =~ /$program_name/) + { + # If we're calling locally and we see our own PID, skip it. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + command => $command, + program_name => $program_name, + pid => $pid, + my_pid => $my_pid, + line => $line + }}); + push @{$pids}, $pid; + } + } + } + + return($pids); +} + + =head2 ping This method will attempt to ping a target, by hostname or IP, and returns C<< 1 >> if successful, and C<< 0 >> if not. diff --git a/tools/anvil-configure-network b/tools/anvil-configure-network index cd953030..7e996a85 100755 --- a/tools/anvil-configure-network +++ b/tools/anvil-configure-network @@ -48,7 +48,7 @@ if (not $connections) pickup_job_details($anvil); - +reconfigure_network($anvil); $anvil->nice_exit({code => 0}); @@ -56,6 +56,102 @@ $anvil->nice_exit({code => 0}); # Functions # ############################################################################################################# +# This does the work of reconfiguring the network +sub reconfigure_network +{ + my ($anvil) = @_; + + my $prefix = $anvil->data->{variables}{form}{config_step1}{prefix}{value}; + my $sequence = $anvil->data->{variables}{form}{config_step1}{sequence}{value}; + my $domain = $anvil->data->{variables}{form}{config_step1}{domain}{value}; + my $organization = $anvil->data->{variables}{form}{config_step1}{organization}{value}; + my $bcn_count = 1; # TODO: This should be coming from the form, even though it's only '1' for now. + my $ifn_count = $anvil->data->{variables}{form}{config_step1}{ifn_count}{value}; + my $new_hostname = $prefix."-striker".sprintf("%02d", $sequence).".".$domain; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + prefix => $prefix, + sequence => $sequence, + domain => $domain, + organization => $organization, + bcn_count => $bcn_count, + ifn_count => $ifn_count, + new_hostname => $new_hostname, + }}); + + +=cut + print Dumper $anvil->data->{variables}; + +$VAR1 = { + 'form' => { + 'config_step2' => { + 'bcn1_subnet' => { + 'value' => '255.255.0.0' + }, + 'ifn1_iface1_mac' => { + 'value' => '52:54:00:dd:ad:8a' + }, + 'dns' => { + 'value' => '8.8.8.8, 8.8.4.4' + }, + 'gateway' => { + 'value' => '192.168.122.1' + }, + 'bcn1_iface1_mac' => { + 'value' => '52:54:00:6b:35:bc' + }, + 'striker_password' => { + 'value' => 'super secret password' + }, + 'hostname' => { + 'value' => 'an-striker01.alteeve.com' + }, + 'gateway_interface' => { + 'value' => 'ifn1' + }, + 'ifn1_subnet' => { + 'value' => '255.255.0.0' + }, + 'ifn1_ip' => { + 'value' => '192.168.122.201' + }, + 'bcn1_ip' => { + 'value' => '10.1.4.1' + }, + 'bcn1_iface2_mac' => { + 'value' => '52:54:00:5d:5d:3d' + }, + 'ifn1_iface2_mac' => { + 'value' => '52:54:00:1e:36:03' + }, + 'striker_user' => { + 'value' => 'striker' + } + }, + 'config_step1' => { + 'domain' => { + 'value' => 'alteeve.com' + }, + 'sequence' => { + 'value' => '1' + }, + 'ifn_count' => { + 'value' => '1' + }, + 'prefix' => { + 'value' => 'an' + }, + 'organization' => { + 'value' => 'Alteeve' + } + } + } + }; +=cut + + return(0); +} + # This will pick up the job, or exit. sub pickup_job_details { @@ -110,11 +206,18 @@ LIMIT 1;"; # See if the job was picked up by another running instance. if ($job_picked_up_by) { - ### TODO: Check if the PID is still active. - # Yup. + # Check if the PID is still active. + my ($pids) = $anvil->System->pids({program_name => $THIS_FILE, ignore_me => 1}); + my $count = @{$pids}; + print "count: [".$count."], my pid: [".$$."]\n"; - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0132", variables => { pid => $job_picked_up_by }}); - $anvil->nice_exit({code => 1}); + # Any other instance running?. + if ($count) + { + # Yup, exit. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0146", variables => { pid => $job_picked_up_by }}); + $anvil->nice_exit({code => 1}); + } } # This will store the variables from the database @@ -138,9 +241,11 @@ AND AND variable_source_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($anvil->Get->host_uuid)." ;"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); + $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); @@ -148,7 +253,7 @@ AND { my $this_variable = $row->[0]; my $this_value = defined $row->[1] ? $row->[1] : ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { this_variable => $this_variable, this_value => $this_value, }}); @@ -156,7 +261,11 @@ AND $anvil->_make_hash_reference($anvil->data->{variables}, $this_variable, $this_value); } - print Dumper $anvil->data->{variables}; + # Record that we've picked up this job. + $query = "UPDATE jobs SET job_picked_up_by = ".$$.", job_progress = 1, job_picked_up_at = ".time." WHERE job_uuid = ".$anvil->data->{sys}{use_db_fh}->quote($job_uuid).";"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); + + $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); return(0); }