diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm
index f05dc654..7466ee25 100644
--- a/Anvil/Tools/Database.pm
+++ b/Anvil/Tools/Database.pm
@@ -2401,7 +2401,7 @@ This is the sum as calculated when the file is first uploaded. Once recorded, it
=head3 file_type (required)
-This is the file's type/purpose. The expected values are 'iso' (disc image a new server can be installed from or mounted in a virtual optical drive), 'repo_rpm' (a package to install on a guest that provides access to Anvil! RPM software), 'script' (pre or post migration scripts), 'image' (images to use for newly created servers, instead of installing from an ISO or PXE), or 'other'.
+This is the file's type/purpose. The expected values are 'iso' (disc image a new server can be installed from or mounted in a virtual optical drive), 'rpm' (a package to install on a guest that provides access to Anvil! RPM software), 'script' (pre or post migration scripts), 'image' (images to use for newly created servers, instead of installing from an ISO or PXE), or 'other'.
=cut
sub insert_or_update_files
diff --git a/Anvil/Tools/Job.pm b/Anvil/Tools/Job.pm
index 7a4d1eed..7d13f971 100644
--- a/Anvil/Tools/Job.pm
+++ b/Anvil/Tools/Job.pm
@@ -519,11 +519,12 @@ sub update_progress
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { job_uuid => $job_uuid }});
}
- # Return if we still don't have a job_uuid
+ # Return if we still don't have a job_uuid. This isn't unexpected as some programs can run with or
+ # without a job_uuid.
if (not $job_uuid)
{
# Nothing we can do.
- $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, priority => "alert", key => "log_0207"});
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0207"});
return(1);
}
diff --git a/Anvil/Tools/Storage.pm b/Anvil/Tools/Storage.pm
index 2056fc19..259de959 100644
--- a/Anvil/Tools/Storage.pm
+++ b/Anvil/Tools/Storage.pm
@@ -357,7 +357,7 @@ sub change_mode
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->change_mode()", parameter => "mode" }});
$error = 1;
}
- elsif (($mode !~ /^\d\d\d$/) && ($mode !~ /^\d\d\d\d$/))
+ elsif (($mode !~ /^\d\d\d$/) && ($mode !~ /^\d\d\d\d$/) && ($mode !~ /^\w\+\w$/) && ($mode !~ /^\w\-\w$/))
{
# Invalid mode
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0038", variables => { mode => $mode }});
@@ -1738,7 +1738,7 @@ sub rsync
=head2 scan_directory
-
+TODO: Wtite this...
=cut
### TODO: Make this work on remote systems
diff --git a/share/anvil.sql b/share/anvil.sql
index 406d56f4..a9a724e1 100644
--- a/share/anvil.sql
+++ b/share/anvil.sql
@@ -1104,7 +1104,7 @@ CREATE TABLE files (
file_name text not null, -- This is the file's name. It can change without re-uploading the file.
file_size numeric not null, -- This is the file's size in bytes. If it recorded as a quick way to determine if a file has changed on disk.
file_md5sum text not null, -- This is the sum as calculated when the file is first uploaded. Once recorded, it can't change.
- file_type text not null, -- This is; 'iso', 'repo_rpm', 'script', or 'backup'.
+ file_type text not null, -- This is the file's type/purpose. The expected values are 'iso', 'rpm', 'script', 'disk-image', or 'other'.
modified_date timestamp with time zone not null
);
ALTER TABLE files OWNER TO admin;
diff --git a/share/words.xml b/share/words.xml
index 437ece41..2558aea7 100644
--- a/share/words.xml
+++ b/share/words.xml
@@ -816,6 +816,8 @@ The update appears to have not completed successfully. The output was:
A request to rename the file: [#!variable!file!#] to: [#!variable!to!#], but there is an existing file or directory with that name.
A request to delete a file was made, but no file name was given.
A request to delete the file: [#!variable!file!#] was received, but it is not under '/mnt/shared/'. This program can only work on or under that directory.
+ Failed!
+ A request to toggle the script flag was received, but no file name was given.
Yes
diff --git a/tools/anvil-manage-files b/tools/anvil-manage-files
index ddb40242..6aa3a32c 100755
--- a/tools/anvil-manage-files
+++ b/tools/anvil-manage-files
@@ -119,6 +119,11 @@ elsif ($anvil->data->{switches}{'delete'}))
{
handle_delete($anvil);
}
+elsif ($anvil->data->{switches}{'is-script'}))
+{
+ handle_script($anvil);
+}
+
# We're done
$anvil->nice_exit({exit_code => 0});
@@ -128,6 +133,178 @@ $anvil->nice_exit({exit_code => 0});
# Private functions. #
#############################################################################################################
+# This gets the file_uuid for a given file name and/or md5sum. If the file isn't found, an empty string is
+# returned.
+sub get_file_uuid
+{
+ my ($anvil, $file_md5sum, $file_name) = @_;
+ $file_md5sum = "" if not defined $file_md5sum;
+ $file_name = "" if not defined $file_name;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ file_md5sum => $file_md5sum,
+ file_name => $file_name,
+ }});
+
+ ### TODO: At some point, we'll need to deal with the possibility that the same file name with
+ ### different md5sums might exist in the database.
+ # If I have the md5sum, search using that. If I have the filename only, then we'll fall back to that.
+ my $query = "
+SELECT
+ file_uuid
+FROM
+ files
+WHERE
+";
+ if ($file_md5sum)
+ {
+ $query .= " file_md5sum = ".$anvil->data->{sys}{database}{use_handle}->quote($file_md5sum)."\n";
+ }
+ elsif ($file_name)
+ {
+ $query .= " file_name = ".$anvil->data->{sys}{database}{use_handle}->quote($file_name)."\n";
+ }
+ my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
+ my $count = @{$results};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ results => $results,
+ count => $count,
+ }});
+ if (not $count)
+ {
+ # File wasn't found in the database
+ return("");
+ }
+ my $file_uuid = $results->[0]->[0];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ file_uuid => $file_uuid,
+ }});
+
+ return($file_uuid);
+}
+
+# This handles toggling a file to marked or unmarked as a script.
+sub handle_script
+{
+ my ($anvil) = @_;
+
+ if (not $anvil->data->{switches}{file})
+ {
+ # Um...
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0055"});
+ if ($anvil->data->{jobs}{'job-uuid'})
+ $anvil->Job->update_progress({
+ progress => 0,
+ message => "error_0055",
+ job_uuid => $anvil->data->{jobs}{'job-uuid'},
+ });
+ $anvil->nice_exit({exit_code => 3});
+ }
+
+ # Find the file_uuid.
+ my ($file_uuid) = get_file_uuid($anvil, "", $anvil->data->{switches}{file});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_uuid => $file_uuid }});
+
+ # Toggle the executable bits.
+ if ($anvil->data->{switches}{'is-script'})
+ {
+ # Is it already executable?
+ if (-x $anvil->data->{switches}{file})
+ {
+ # Switch it on
+ $anvil->Storage->change_mode({target => $anvil->data->{switches}{file}, mode => "a+x"});
+ }
+ else
+ {
+ # Already a script.
+ }
+ }
+ else
+ {
+ # Is it executable?
+ if (-x $anvil->data->{switches}{file})
+ {
+ # Switch it off.
+ $anvil->Storage->change_mode({target => $anvil->data->{switches}{file}, mode => "a-x"});
+ }
+ else
+ {
+ # Already not a script.
+ }
+ }
+
+ # If we have a file UUID, update the 'file_type
+ if ($file_uuid)
+ {
+ # Load the details.
+ my $query = "
+SELECT
+ file_name,
+ file_size,
+ file_md5sum,
+ file_type
+FROM
+ files
+WHERE
+ file_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($file_uuid)."
+;";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
+
+ my $results = $anvil->Database->query({query => $query, source => $file ? $file." -> ".$THIS_FILE : $THIS_FILE, line => $line ? $line." -> ".__LINE__ : __LINE__});
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results }});
+ my $file_name = $results->[0]->[0];
+ my $file_size = $results->[0]->[1];
+ my $file_md5sum = $results->[0]->[2];
+ my $file_type = $results->[0]->[3];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
+ file_name => $file_name,
+ file_size => $file_size,
+ file_md5sum => $file_md5sum,
+ file_type => $file_type,
+ }});
+ if (($file_type eq "script") && (not $anvil->data->{switches}{'is-script'}))
+ {
+ # Figure out what the file type is and update.
+ my $mimetype = mimetype($full_path);
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { mimetype => $mimetype }});
+
+ my $say_mimetype = "other";
+ if ($mimetype =~ /cd-image/)
+ {
+ $say_mimetype = "iso";
+ }
+ elsif ($mimetype =~ /rpm$/)
+ {
+ $say_mimetype = "rpm";
+ }
+ elsif ($mimetype =~ /disk-image/)
+ {
+ $say_mimetype = "disk-image";
+ }
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_mimetype => $say_mimetype }});
+ $anvil->Database->insert_or_update_files({
+ file_uuid => $file_uuid,
+ file_name => $anvil->data->{switches}{file},
+ file_size => $file_size,
+ file_md5sum => $file_md5sum,
+ file_type => $say_mimetype,
+ });
+ }
+ elsif ($file_type ne "script") && ($anvil->data->{switches}{'is-script'}))
+ {
+ # Change the file tpye to "script"
+ $anvil->Database->insert_or_update_files({
+ file_uuid => $file_uuid,
+ file_name => $anvil->data->{switches}{file},
+ file_size => $file_size,
+ file_md5sum => $file_md5sum,
+ file_type => "script",
+ });
+ }
+ }
+
+ return(0);
+}
+
# This handles deleting a file. If the requested deletion target doesn't exist, we'll just clear the
# database. If that doesn't exist either, we still don't error. This is to handle broad requests to delete a
# file everywhere. If we're asked to delete it everywhere, then we'll register a job against all hosts.
@@ -139,12 +316,23 @@ sub handle_delete
{
# Um...
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0052"});
+ if ($anvil->data->{jobs}{'job-uuid'})
+ $anvil->Job->update_progress({
+ progress => 0,
+ message => "error_0052",
+ job_uuid => $anvil->data->{jobs}{'job-uuid'},
+ });
$anvil->nice_exit({exit_code => 3});
}
elsif ($anvil->data->{switches}{file} !~ /^\/mnt\/shared\//)
{
# We don't do that here...
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0053", variables => { file => $anvil->data->{switches}{file} }});
+ $anvil->Job->update_progress({
+ progress => 0,
+ message => "error_0053,!!file!".$anvil->data->{switches}{file}."!!",
+ job_uuid => $anvil->data->{jobs}{'job-uuid'},
+ });
$anvil->nice_exit({exit_code => 6});
}
@@ -183,24 +371,44 @@ sub handle_rename
{
# Um...
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0049"});
+ $anvil->Job->update_progress({
+ progress => 0,
+ message => "error_0049",
+ job_uuid => $anvil->data->{jobs}{'job-uuid'},
+ });
$anvil->nice_exit({exit_code => 3});
}
elsif (not $anvil->data->{switches}{to})
{
# We need a target
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0050", variables => { file => $anvil->data->{switches}{file} }});
+ $anvil->Job->update_progress({
+ progress => 0,
+ message => "error_0050,!!file!".$anvil->data->{switches}{file}."!!",
+ job_uuid => $anvil->data->{jobs}{'job-uuid'},
+ });
$anvil->nice_exit({exit_code => 4});
}
elsif (not -f $anvil->data->{switches}{file})
{
# The file to rename doesn't exist.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0051", variables => { file => $anvil->data->{switches}{file} }});
+ $anvil->Job->update_progress({
+ progress => 0,
+ message => "error_0051,!!file!".$anvil->data->{switches}{file}."!!",
+ job_uuid => $anvil->data->{jobs}{'job-uuid'},
+ });
$anvil->nice_exit({exit_code => 5});
}
elsif (-e $anvil->data->{switches}{to})
{
# There's already a file (or directory or something) with that name.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "error_0052", variables => { file => $anvil->data->{switches}{file}, to => $anvil->data->{switches}{to} }});
+ $anvil->Job->update_progress({
+ progress => 0,
+ message => "error_0052,!!file!".$anvil->data->{switches}{file}."!!,!!to!".$anvil->data->{switches}{to}."!!",
+ job_uuid => $anvil->data->{jobs}{'job-uuid'},
+ });
$anvil->nice_exit({exit_code => 6});
}