You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
926 lines
32 KiB
926 lines
32 KiB
#!/usr/bin/perl |
|
# |
|
# This runs on striker dashboards and syncs files under /mnt/shared on all known systems. It reaches out and |
|
# pulls over any files under /mnt/shared/files/ to the same on the local system. It then pushes files out to |
|
# all members of the same Anvil!. |
|
# |
|
# If this is called with a job-uuid, file-specific tasks will be handled, like moving files uploaded over a |
|
# browser or deleting / purging a file. |
|
# |
|
# NOTE: This file is NOT responsible for sync'ing definition files! That is handles in scan-server. |
|
# |
|
# TODO: |
|
# - Handle deleting files by user input, or if a given file that was on an Anvil! has been removed for both |
|
# nodes and DR, where applicable. |
|
# - |
|
|
|
use strict; |
|
use warnings; |
|
use Anvil::Tools; |
|
use Data::Dumper; |
|
|
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
|
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
|
{ |
|
$running_directory =~ s/^\./$ENV{PWD}/; |
|
} |
|
|
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. |
|
$| = 1; |
|
|
|
my $anvil = Anvil::Tools->new(); |
|
|
|
# Read switches (target ([user@]host[:port]) and the file with the target's password. |
|
$anvil->data->{switches}{'job-uuid'} = ""; |
|
$anvil->Get->switches; |
|
|
|
### TODO: Remove this |
|
$anvil->Log->level({set => 2}); |
|
$anvil->Log->secure({set => 1}); |
|
|
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }}); |
|
|
|
# Connect to the database(s). |
|
$anvil->Database->connect; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0132"}); |
|
|
|
# If we have a job-uuid, process it. |
|
if ($anvil->data->{switches}{'job-uuid'}) |
|
{ |
|
# Load the job data. |
|
$anvil->Database->get_anvils({debug => 3}); |
|
$anvil->Job->get_job_details({debug => 3}); |
|
$anvil->Job->clear({debug => 3}); |
|
|
|
$anvil->data->{sys}{progress} = 1; |
|
if ($anvil->data->{jobs}{job_name} eq "storage::move_incoming") |
|
{ |
|
process_incoming_file($anvil); |
|
} |
|
if ($anvil->data->{jobs}{job_name} eq "storage::pull_file") |
|
{ |
|
process_pull_file($anvil); |
|
} |
|
if ($anvil->data->{jobs}{job_name} eq "storage::purge") |
|
{ |
|
process_purge_file($anvil); |
|
} |
|
if ($anvil->data->{jobs}{job_name} eq "storage::rename") |
|
{ |
|
process_rename_file($anvil); |
|
} |
|
if ($anvil->data->{jobs}{job_name} eq "storage::check_mode") |
|
{ |
|
process_file_mode($anvil); |
|
} |
|
} |
|
|
|
$anvil->nice_exit({exit_code => 0}); |
|
|
|
|
|
############################################################################################################# |
|
# Functions # |
|
############################################################################################################# |
|
|
|
sub process_file_mode |
|
{ |
|
my ($anvil) = @_; |
|
|
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0205", |
|
}); |
|
|
|
# We have to include deleted because purges will already have the file flagged as deleted. |
|
$anvil->Database->get_files({debug => 3, include_deleted => 1}); |
|
$anvil->Database->get_file_locations({debug => 3}); |
|
|
|
my $file_uuid = ($anvil->data->{jobs}{job_data} =~ /file_uuid=(.*)$/)[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }}); |
|
|
|
if (not $file_uuid) |
|
{ |
|
# Can't do anything, file wasn't parsed. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0185,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0185", variables => { job_uuid => $anvil->data->{switches}{'job-uuid'} }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
elsif (not exists $anvil->data->{files}{file_uuid}{$file_uuid}) |
|
{ |
|
# File UUID doesn't appear to be valid. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0186,!!file_uuid!".$file_uuid."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0186", variables => { file_uuid => $file_uuid }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; |
|
my $file_directory = $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory}; |
|
my $file_path = $file_directory."/".$file_name; |
|
my $file_type = $anvil->data->{files}{file_uuid}{$file_uuid}{file_type}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:file_name' => $file_name, |
|
's2:file_directory' => $file_directory, |
|
's3:file_path' => $file_path, |
|
's4:file_type' => $file_type, |
|
}}); |
|
|
|
# From here, we'll unlink if it exists. If it doesn't exist, we still exit sucessfully. |
|
if (-e $file_path) |
|
{ |
|
# Change the mode, if need it. |
|
my $new_mode = "a-x"; |
|
if ($file_type eq "script") |
|
{ |
|
$new_mode = "a+x"; |
|
} |
|
$anvil->Storage->change_mode({ |
|
path => $file_path, |
|
mode => $new_mode, |
|
}); |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "job_0145,!!file_path!".$file_path."!!,!!new_mode!".$new_mode."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "job_0145", variables => { |
|
file_path => $file_path, |
|
new_mode => $new_mode, |
|
}}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
else |
|
{ |
|
# Doesn't exist, nothing to do. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "job_0146,!!file_path!".$file_path."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "job_0146", variables => { file_path => $file_path }}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
sub process_rename_file |
|
{ |
|
my ($anvil) = @_; |
|
|
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0204", |
|
}); |
|
|
|
$anvil->Database->get_files({debug => 3}); |
|
$anvil->Database->get_file_locations({debug => 3}); |
|
|
|
my $file_uuid = ""; |
|
my $old_name = ""; |
|
my $new_name = ""; |
|
foreach my $line (split/\n/, $anvil->data->{jobs}{job_data}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); |
|
if ($line =~ /file_uuid=(.*)$/) |
|
{ |
|
$file_uuid = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }}); |
|
} |
|
if ($line =~ /old_name=(.*)$/) |
|
{ |
|
$old_name = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_name => $old_name }}); |
|
} |
|
if ($line =~ /new_name=(.*)$/) |
|
{ |
|
$new_name = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_name => $new_name }}); |
|
} |
|
} |
|
|
|
if (not $file_uuid) |
|
{ |
|
# Can't do anything, file wasn't parsed. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0181,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0181", variables => { job_uuid => $anvil->data->{switches}{'job-uuid'} }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
elsif (not exists $anvil->data->{files}{file_uuid}{$file_uuid}) |
|
{ |
|
# File UUID doesn't appear to be valid. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0182,!!file_uuid!".$file_uuid."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0182", variables => { file_uuid => $file_uuid }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; |
|
my $file_directory = $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory}; |
|
my $old_file_path = $file_directory."/".$old_name; |
|
my $new_file_path = $file_directory."/".$new_name; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:file_name' => $file_name, |
|
's2:file_directory' => $file_directory, |
|
's3:old_file_path' => $old_file_path, |
|
's4:new_file_path' => $new_file_path, |
|
}}); |
|
|
|
if (not $new_name) |
|
{ |
|
# Can't do anything, file wasn't parsed. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0183,!!file_name!".$new_file_path."!!,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0183", variables => { |
|
file_name => $new_file_path, |
|
job_uuid => $anvil->data->{switches}{'job-uuid'}, |
|
}}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
# If the file doesn't exist, there's nothing to do (and that's OK). |
|
if (-e $old_file_path) |
|
{ |
|
# Move the file. |
|
$anvil->Job->update_progress({ |
|
progress => 50, |
|
message => "job_0141,!!old_file!".$old_file_path."!!,!!new_file!".$new_file_path."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "job_0141", variables => { |
|
old_file => $old_file_path, |
|
new_file => $new_file_path, |
|
}}); |
|
$anvil->Storage->move_file({ |
|
source_file => $old_file_path, |
|
target_file => $new_file_path, |
|
}); |
|
|
|
if ((not -e $old_file_path) && (-e $new_file_path)) |
|
{ |
|
# Success! |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "job_0142", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "job_0142"}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
elsif ((-e $old_file_path) && (not -e $new_file_path)) |
|
{ |
|
# Move failed |
|
$anvil->Job->update_progress({ |
|
progress => 1, |
|
message => "error_0184", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0184"}); |
|
sleep 60; |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
} |
|
else |
|
{ |
|
# Nothing to do |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "job_0140,!!file_path!".$old_file_path."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "job_0140", variables => { file_path => $old_file_path }}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
sub process_purge_file |
|
{ |
|
my ($anvil) = @_; |
|
|
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0203", |
|
}); |
|
|
|
# We have to include deleted because purges will already have the file flagged as deleted. |
|
$anvil->Database->get_files({debug => 3, include_deleted => 1}); |
|
$anvil->Database->get_file_locations({debug => 3}); |
|
|
|
my $file_uuid = ($anvil->data->{jobs}{job_data} =~ /file_uuid=(.*)$/)[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }}); |
|
|
|
if (not $file_uuid) |
|
{ |
|
# Can't do anything, file wasn't parsed. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0178,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0178", variables => { job_uuid => $anvil->data->{switches}{'job-uuid'} }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
elsif (not exists $anvil->data->{files}{file_uuid}{$file_uuid}) |
|
{ |
|
# File UUID doesn't appear to be valid. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0179,!!file_uuid!".$file_uuid."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0179", variables => { file_uuid => $file_uuid }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; |
|
my $file_directory = $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory}; |
|
my $file_path = $file_directory."/".$file_name; |
|
my $file_type = $anvil->data->{files}{file_uuid}{$file_uuid}{file_type}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:file_name' => $file_name, |
|
's2:file_directory' => $file_directory, |
|
's3:file_path' => $file_path, |
|
's4:file_type' => $file_type, |
|
}}); |
|
|
|
# From here, we'll unlink if it exists. If it doesn't exist, we still exit sucessfully. |
|
if (-e $file_path) |
|
{ |
|
# Remove it |
|
unlink $file_path; |
|
if (-e $file_path) |
|
{ |
|
# Failed. |
|
my $error = $!; |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0180,!!file_path!".$file_path."!!,!!error!".$error."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0180", variables => { |
|
file_path => $file_path, |
|
error => $error, |
|
}}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
else |
|
{ |
|
# Success! |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "job_0134,!!file_path!".$file_path."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "job_0134", variables => { file_path => $file_path }}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
} |
|
else |
|
{ |
|
# Doesn't exist, nothing to do. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "job_0135,!!file_path!".$file_path."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "job_0135", variables => { file_path => $file_path }}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
sub process_incoming_file |
|
{ |
|
my ($anvil) = @_; |
|
|
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0191", |
|
}); |
|
|
|
my $file = ($anvil->data->{jobs}{job_data} =~ /file=(.*)$/)[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file => $file }}); |
|
if (not $file) |
|
{ |
|
# Can't do anything, file wasn't parsed. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0170,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0170", variables => { job_uuid => $anvil->data->{switches}{'job-uuid'} }}); |
|
|
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
elsif (not -e $file) |
|
{ |
|
# Can't do anything, file doesn't exist |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0171,!!file!".$file."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0171", variables => { file => $file }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
# Make sure the file actually done uploading. |
|
$anvil->data->{sys}{progress} = 5; |
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0309,!!file!".$file."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0309", variables => { file => $file }}); |
|
$anvil->Storage->_wait_if_changing({ |
|
debug => 2, |
|
file => $file, |
|
}); |
|
|
|
# Move it over to files. |
|
$anvil->data->{sys}{progress} = 5; |
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0192,!!file!".$file."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0192", variables => { file => $file }}); |
|
$anvil->Storage->move_file({ |
|
debug => 2, |
|
overwrite => 1, |
|
source_file => $file, |
|
target_file => $anvil->data->{path}{directories}{shared}{files}."/", |
|
}); |
|
|
|
my $file_name = ($file =~ /\/.*\/(.*?)$/)[0]; |
|
my $target_file = $anvil->data->{path}{directories}{shared}{files}."/".$file_name; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
file_name => $file_name, |
|
target_file => $target_file, |
|
}}); |
|
|
|
if (not -e $target_file) |
|
{ |
|
# Failed to move. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0172,!!file!".$file."!!,!!target_directory!".$anvil->data->{path}{directories}{shared}{files}."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0171", variables => { file => $file }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
# Change the owner as it'll be apache, which won't be a valid users on anvil members. |
|
$anvil->Storage->change_owner({ |
|
debug => 2, |
|
path => $target_file, |
|
user => "root", |
|
group => "root", |
|
}); |
|
|
|
# Calculate the md5sum. |
|
$anvil->data->{sys}{progress} = 20; |
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0193", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0193"}); |
|
|
|
my ($string, $return_code) = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{md5sum}." ".$target_file}); |
|
my $md5sum = ($string =~ /^(.*?)\s/)[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
string => $string, |
|
md5sum => $md5sum, |
|
return_code => $return_code, |
|
}}); |
|
|
|
# Store the file details! |
|
$anvil->data->{sys}{progress} = 30; |
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0194,!!md5sum!".$md5sum."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0194", variables => { md5sum => $md5sum }}); |
|
|
|
$anvil->Storage->get_file_stats({ |
|
debug => 2, |
|
file_path => $target_file, |
|
}); |
|
|
|
my $file_mimetype = $anvil->data->{file_stat}{$target_file}{mimetype}; |
|
my $file_size = $anvil->data->{file_stat}{$target_file}{size}; |
|
my $file_mtime = $anvil->data->{file_stat}{$target_file}{modified_time}; |
|
my $executable = -x $target_file ? 1 : 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
file_mimetype => $file_mimetype, |
|
file_size => $file_size." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}).")", |
|
file_mtime => $file_mtime, |
|
executable => $executable, |
|
}}); |
|
|
|
# This is the file's type/purpose. The expected values are 'iso', 'rpm', 'script', 'disk-image', or |
|
# 'other'. If set to 'DELETED', the file will be removed from disk. |
|
my $file_type = "other"; |
|
if ($file_mimetype =~ /cd-image/) |
|
{ |
|
$file_type = "iso"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_type => $file_type }}); |
|
} |
|
# This will need to be expanded over time |
|
elsif (($executable) or ($file_mimetype =~ /perl/) or ($file_mimetype =~ /python/)) |
|
{ |
|
$file_type = "script"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_type => $file_type }}); |
|
|
|
# Change the mode to be executable |
|
$anvil->Storage->change_mode({ |
|
debug => 2, |
|
path => $target_file, |
|
mode => "0755", |
|
}); |
|
} |
|
elsif ($file_mimetype =~ /raw-disk-image/) |
|
{ |
|
$file_type = "image"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_type => $file_type }}); |
|
} |
|
|
|
my $file_uuid = $anvil->Database->insert_or_update_files({ |
|
debug => 2, |
|
file_name => $file_name, |
|
file_directory => $anvil->data->{path}{directories}{shared}{files}, |
|
file_size => $file_size, |
|
file_md5sum => $md5sum, |
|
file_type => $file_type, |
|
file_mtime => $file_mtime, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }}); |
|
|
|
# Now copy this to our peers. We're going to do this serially so that we don't overwhelm the system, |
|
# Any hosts not currently online will have a job registered. |
|
$anvil->Storage->push_file({ |
|
debug => 2, |
|
file => $target_file, |
|
file_uuid => $file_uuid, |
|
}); |
|
|
|
# Call track_files, it'll make sure the file_locations are setup. |
|
$anvil->Database->track_files({debug => 2}); |
|
|
|
# Done! |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "message_0197", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0197"}); |
|
|
|
return(0); |
|
} |
|
|
|
# This pulls files from dashboards onto the running host. |
|
sub process_pull_file |
|
{ |
|
my ($anvil) = @_; |
|
|
|
$anvil->Job->update_progress({ |
|
progress => $anvil->data->{sys}{progress}, |
|
message => "message_0198", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0198" }); |
|
|
|
# Collect some data |
|
$anvil->Database->get_anvils({debug => 3}); |
|
$anvil->Database->get_files({debug => 3}); |
|
$anvil->Database->get_file_locations({debug => 3}); |
|
|
|
my $file_uuid = ($anvil->data->{jobs}{job_data} =~ /file_uuid=(.*)$/)[0]; |
|
my $anvil_uuid = $anvil->Cluster->get_anvil_uuid({debug => 2}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
anvil_uuid => $anvil_uuid, |
|
file_uuid => $file_uuid, |
|
}}); |
|
|
|
if (not $file_uuid) |
|
{ |
|
# Can't do anything, file wasn't parsed. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0173,!!job_uuid!".$anvil->data->{switches}{'job-uuid'}."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0173", variables => { job_uuid => $anvil->data->{switches}{'job-uuid'} }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
elsif (not exists $anvil->data->{files}{file_uuid}{$file_uuid}) |
|
{ |
|
# File UUID doesn't appear to be valid. |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0174,!!file_uuid!".$file_uuid."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0174", variables => { file_uuid => $file_uuid }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
my $file_name = $anvil->data->{files}{file_uuid}{$file_uuid}{file_name}; |
|
my $file_directory = $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory}; |
|
my $file_path = $file_directory."/".$file_name; |
|
my $file_size = $anvil->data->{files}{file_uuid}{$file_uuid}{file_size}; |
|
my $file_md5sum = $anvil->data->{files}{file_uuid}{$file_uuid}{file_md5sum}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
's1:file_name' => $file_name, |
|
's2:file_directory' => $file_directory, |
|
's3:file_path' => $file_path, |
|
's4:file_size' => $file_size." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $file_size}).")", |
|
's5:file_md5sum' => $file_md5sum, |
|
}}); |
|
|
|
if (not $anvil_uuid) |
|
{ |
|
# Uhhh... |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "error_0175,!!file!".$file_path."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0175", variables => { file => $file_path }}); |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
# How many Strikers are up and have the file we're looking for? |
|
$anvil->data->{target_strikers} = []; |
|
foreach my $host_uuid (keys %{$anvil->data->{database}}) |
|
{ |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); |
|
|
|
my $host_name = $anvil->Get->host_name_from_uuid({debug => 2, host_uuid => $host_uuid}); |
|
my $target = $anvil->data->{database}{$host_uuid}{host}; |
|
my $password = $anvil->data->{database}{$host_uuid}{password}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
host_name => $host_name, |
|
target => $target, |
|
password => $anvil->Log->is_secure($password), |
|
}}); |
|
|
|
# If the file exists, the return code is '0'. If the file isn't found, '1' is returned. |
|
# When found, the size in bytes followed by the file name is returned. |
|
my $shell_call = $anvil->data->{path}{exe}{wc}." -c ".$file_path; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
|
my ($output, $error, $return_code) = $anvil->Remote->call({ |
|
debug => 3, |
|
shell_call => $shell_call, |
|
target => $target, |
|
password => $password, |
|
remote_user => "root", |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
output => $output, |
|
error => $error, |
|
output => $output, |
|
}}); |
|
if ($output =~ /^(\d+)\s+$file_path$/) |
|
{ |
|
my $size_on_peer = $1; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
size_on_peer => $size_on_peer." (".$anvil->Convert->bytes_to_human_readable({"bytes" => $size_on_peer}).")" |
|
}}); |
|
|
|
# For now, we only do a size check as md5sums can take a long time. |
|
if ($size_on_peer eq $file_size) |
|
{ |
|
# We can pull from this striker! |
|
push @{$anvil->data->{target_strikers}}, { |
|
host_name => $host_name, |
|
host_uuid => $host_uuid, |
|
target => $target, |
|
password => $password, |
|
}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
host_name => $host_name, |
|
host_uuid => $host_uuid, |
|
target => $target, |
|
password => $anvil->Log->is_secure($password), |
|
}}); |
|
} |
|
else |
|
{ |
|
# The file doesn't exist or we couldn't contact the Striker, so we'll skip |
|
# it. |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0576", variables => { |
|
file_path => $file_path, |
|
host_name => $host_name, |
|
}}); |
|
} |
|
} |
|
} |
|
|
|
my $anvil_node1_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; |
|
my $anvil_node2_host_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
anvil_node1_host_uuid => $anvil_node1_host_uuid, |
|
anvil_node2_host_uuid => $anvil_node2_host_uuid, |
|
}}); |
|
|
|
# Where we pull from will depend on which machine we are and how many strikers we have. If we have |
|
# one Anvil!, sub-node 1 and 2 download at the same time. If there are two strikers, Each node will |
|
# download from a different striker (if possible). |
|
my $i_am = "node1"; |
|
if ($anvil->Get->host_uuid eq $anvil_node2_host_uuid) |
|
{ |
|
$i_am = "node2"; |
|
} |
|
|
|
my $striker_count = @{$anvil->data->{target_strikers}}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
i_am => $i_am, |
|
striker_count => $striker_count, |
|
}}); |
|
if (not $striker_count) |
|
{ |
|
# No available Strikers. |
|
$anvil->Job->update_progress({ |
|
progress => 1, |
|
message => "warning_0072,!!file_path!".$file_path."!!", |
|
job_status => "failed", |
|
}); |
|
sleep 60; |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "warning_0072", variables => { file_path => $file_path }}); |
|
$anvil->nice_exit({exit_code => 2}); |
|
} |
|
|
|
my $use = 0; |
|
if ($striker_count >= 3) |
|
{ |
|
if ($i_am eq "node1") { $use = 0; } |
|
elsif ($i_am eq "node2") { $use = 1; } |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'use' => $use }}); |
|
} |
|
elsif ($striker_count == 2) |
|
{ |
|
# Two strikers, each node will use the other Striker |
|
if ($i_am eq "node1") { $use = 0; } |
|
elsif ($i_am eq "node2") { $use = 1; } |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'use' => $use }}); |
|
} |
|
elsif ($striker_count == 1) |
|
{ |
|
# Only 1 Striker |
|
if ($i_am eq "node1") { $use = 0; } |
|
elsif ($i_am eq "node2") { $use = 0; } |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'use' => $use }}); |
|
} |
|
|
|
# Now proceed with the download! |
|
my $target_host_name = $anvil->data->{target_strikers}->[$use]->{host_name}; |
|
my $target_host_uuid = $anvil->data->{target_strikers}->[$use]->{host_uuid}; |
|
my $target_host = $anvil->data->{target_strikers}->[$use]->{target}; |
|
my $target_password = $anvil->data->{target_strikers}->[$use]->{password}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
target_host_name => $target_host_name, |
|
target_host_uuid => $target_host_uuid, |
|
target_host => $target_host, |
|
target_password => $anvil->Log->is_secure($target_password), |
|
}}); |
|
|
|
# Rsync the file. |
|
my $say_source_file = "root\@".$target_host.":".$file_path; |
|
my $target_directory = $file_directory."/"; |
|
$anvil->Job->update_progress({ |
|
progress => 50, |
|
message => "message_0200,!!source_file!".$say_source_file."!!,!!target_directory!".$target_directory."!!", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0200", variables => { |
|
source_file => $say_source_file, |
|
target_directory => $target_directory, |
|
}}); |
|
|
|
$anvil->Storage->rsync({ |
|
debug => 2, |
|
source => $say_source_file, |
|
destination => $target_directory, |
|
try_again => 1, |
|
}); |
|
|
|
if (-e $file_path) |
|
{ |
|
# Calculate the md5sum. |
|
$anvil->Job->update_progress({ |
|
progress => 75, |
|
message => "message_0201", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0201"}); |
|
|
|
my $local_md5sum = $anvil->Get->md5sum({file => $file_path}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { local_md5sum => $local_md5sum }}); |
|
|
|
if ($file_md5sum eq $local_md5sum) |
|
{ |
|
$anvil->Job->update_progress({ |
|
progress => 100, |
|
message => "message_0202", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0202"}); |
|
$anvil->nice_exit({exit_code => 0}); |
|
} |
|
else |
|
{ |
|
# Unlink the file. The perioding sync call can try again later. |
|
unlink $file_path; |
|
$anvil->Job->update_progress({ |
|
progress => 1, |
|
message => "error_0176,!!local_md5sum!".$local_md5sum."!!,!!file_md5sum!".$file_md5sum."!!", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0176", variables => { |
|
local_md5sum => $local_md5sum, |
|
file_md5sum => $file_md5sum, |
|
}}); |
|
sleep 60; |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
} |
|
else |
|
{ |
|
# Failed... |
|
$anvil->Job->update_progress({ |
|
progress => 1, |
|
message => "error_0177", |
|
job_status => "failed", |
|
}); |
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => 'err', key => "error_0177" }); |
|
sleep 60; |
|
$anvil->nice_exit({exit_code => 1}); |
|
} |
|
|
|
return(0); |
|
} |
|
|
|
# This takes a host and job UUID and determines if we're still waiting on the target. |
|
sub wait_on_host |
|
{ |
|
my ($anvil, $host_uuid, $job_uuid) = @_; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
host_uuid => $host_uuid." (".$anvil->Get->host_name_from_uuid({host_uuid => $host_uuid}).")", |
|
job_uuid => $job_uuid, |
|
}}); |
|
|
|
my $waiting = 1; |
|
|
|
# Look up the job progress. |
|
my $query = "SELECT job_progress FROM jobs WHERE job_uuid = ".$anvil->Database->quote($job_uuid).";"; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); |
|
|
|
my $progress = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { progress => $progress }}); |
|
|
|
if ($progress == 100) |
|
{ |
|
$waiting = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { waiting => $waiting }}); |
|
} |
|
else |
|
{ |
|
# Can I ping the node? |
|
my $pinged = 0; |
|
foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{network}{$host_uuid}{interface}}) |
|
{ |
|
my $target_ip = $anvil->data->{network}{$host_uuid}{interface}{$interface}{ip}; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { |
|
interface => $interface, |
|
target_ip => $target_ip, |
|
}}); |
|
|
|
($pinged, my $average_time) = $anvil->Network->ping({ |
|
ping => $target_ip, |
|
count => 1, |
|
}); |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pinged => $pinged }}); |
|
|
|
last if $pinged; |
|
} |
|
|
|
if (not $pinged) |
|
{ |
|
# Stop waiting, it looks to be offline. |
|
$waiting = 0; |
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { waiting => $waiting }}); |
|
} |
|
} |
|
|
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { waiting => $waiting }}); |
|
return($waiting) |
|
}
|
|
|