diff --git a/Anvil/Tools/Storage.pm b/Anvil/Tools/Storage.pm index 3915aa43..db81542b 100644 --- a/Anvil/Tools/Storage.pm +++ b/Anvil/Tools/Storage.pm @@ -22,6 +22,7 @@ my $THIS_FILE = "Storage.pm"; # check_md5sums # compress # copy_file +# copy_device # delete_file # find # get_file_stats @@ -1263,6 +1264,67 @@ fi"; } +=head3 copy_device + +This uses the C<< dd >> system call, possibly over ssh, to create a copy of the source on the destination. Being based on C<< dd >>, this works with raw block devices and to or from files. + +B<< Warning >>: This must be used carefully! Calling this backwards could destroy data! + +B<< Note >>: The caller is responsible for ensuring the data on the soure will not change during the copy. If the source is a server, make sure it's off. If the source is a file system, make sure it's unmounted. + +Parameters; + +=head3 block_size (optional, default '4M') + +This is the block size to be used for the copy. Specifically, this transtes into 'read bytes, copy, read bytes, copy'. This should match the size of the logical extents, block size or similar where needed. Most LVM logical extents are 4 MiB, so the default of C<< 4M >> should be fine in most cases. + +B<< Note >>: See C<< man dd >> for valid formatting of this option. + +=head3 calculate_sums (Optional, default '0') + +If set to C<< 1 >>, the C<< md5sum >> of the source and destination are calculated and returned. If this is not used, the returned sum fields will be an empty string. + +B<< Note >>: Calculating sums is highly advised, but can increase the time it takes for the copy to complete! + +=head3 destination (required) + +This is the full path to the destination (copy to) file or device. If the source is remote, used the format C<< @target:/path/to/file >>. + +B<< Note >>: Only the source OR the destination can be remote, not both! + +=head3 source (required) + +This is the full path to the source (copy from) file or device. If the source is remote, used the format C<< @target:/path/to/file >>. + +B<< Note >>: Only the source OR the destination can be remote, not both! + +=cut +sub copy_device +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Storage->delete_file()" }}); + + my $file = defined $parameter->{file} ? $parameter->{file} : ""; + my $password = defined $parameter->{password} ? $parameter->{password} : ""; + my $port = defined $parameter->{port} ? $parameter->{port} : 22; + my $remote_user = defined $parameter->{remote_user} ? $parameter->{remote_user} : "root"; + my $target = defined $parameter->{target} ? $parameter->{target} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + file => $file, + password => $anvil->Log->is_secure($password), + port => $port, + remote_user => $remote_user, + target => $target, + }}); + + + return(""); +} + + =head3 delete_file This deletes a file. Pretty much what it says on the tin. When run locally, it uses C<< unlink >>. When run on a remote machine, it uses C<< rm -f >>. As such, this will not delete directories, nor will it delete recursively. diff --git a/Anvil/Tools/System.pm b/Anvil/Tools/System.pm index 8d6709fa..e4483c6c 100644 --- a/Anvil/Tools/System.pm +++ b/Anvil/Tools/System.pm @@ -4902,7 +4902,6 @@ sub update_hosts # Read in the existing hosts file my $add_header = 1; - my $changes = 0; my $added_lo_ipv4 = 0; my $added_lo_ipv6 = 0; my $new_body = ""; @@ -4912,6 +4911,35 @@ sub update_hosts }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { old_body => $old_body }}); + # Look for duplicate empty lines and clear them. + my $last_line_blank = 0; + my $cleaned_body = ""; + foreach my $line (split/\n/, $old_body) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); + if ($line) + { + $last_line_blank = 0; + $cleaned_body .= $line."\n"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { last_line_blank => $last_line_blank }}); + } + elsif (not $last_line_blank) + { + $last_line_blank = 1; + $cleaned_body .= $line."\n"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { last_line_blank => $last_line_blank }}); + } + } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { last_line_blank => $last_line_blank }}); + + my $difference = diff \$old_body, \$cleaned_body, { STYLE => 'Unified' }; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { difference => $difference }}); + if ($difference) + { + $old_body = $cleaned_body; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { old_body => $old_body }}); + } + # This will track the IPs we've seen. We'll only write these out once, and skip any futher entries # that may be found. my $written_ips = {}; @@ -4955,9 +4983,6 @@ sub update_hosts { if ($line ne "127.0.0.1\tlocalhost localhost.localdomain localhost4 localhost4.localdomain4") { - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { changes => $changes }}); - if (not $added_lo_ipv4) { $new_body .= "127.0.0.1\tlocalhost localhost.localdomain localhost4 localhost4.localdomain4\n"; @@ -4977,9 +5002,6 @@ sub update_hosts { if ($line ne "::1\t\tlocalhost localhost.localdomain localhost6 localhost6.localdomain6") { - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { changes => $changes }}); - if (not $added_lo_ipv6) { $new_body .= "::1\t\tlocalhost localhost.localdomain localhost6 localhost6.localdomain6\n"; @@ -5019,8 +5041,6 @@ sub update_hosts if (exists $written_ips->{$ip_address}) { # Skipping at least one line, rewrite the file. - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { changes => $changes }}); next; } $written_ips->{$ip_address} = 1; @@ -5049,8 +5069,6 @@ sub update_hosts new_ip => $ip_address, host => $name, }}); - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { changes => $changes }}); next; } } @@ -5092,11 +5110,9 @@ sub update_hosts my $header = $anvil->Words->string({key => "message_0177"}); $header =~ s/^\n//; $new_body = $header.$new_body; - $changes = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - 's1:changes' => $changes, - 's2:header' => $header, - 's3:new_body' => $new_body, + 's1:header' => $header, + 's2:new_body' => $new_body, }}); } @@ -5132,9 +5148,6 @@ sub update_hosts $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { new_line_count => $new_line_count }}); if ($new_line_count) { - $changes = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { changes => $changes }}); - $new_body .= "\n"; #$new_body .= "\n# ".$anvil->Words->string({key => "message_0178", variables => { date => $anvil->Get->date_and_time({debug => $debug}) }})."\n"; foreach my $ip_address (@{$ip_order}) @@ -5144,11 +5157,10 @@ sub update_hosts } } - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - 's1:changes' => $changes, - 's2:new_body' => $new_body, - }}); - if ($changes) + $difference = ""; + $difference = diff \$old_body, \$new_body, { STYLE => 'Unified' }; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { difference => $difference }}); + if ($difference) { # Write the new file. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { new_body => $new_body }}); diff --git a/tools/anvil-provision-server b/tools/anvil-provision-server index 0ddee354..bb453791 100755 --- a/tools/anvil-provision-server +++ b/tools/anvil-provision-server @@ -44,6 +44,7 @@ $anvil->data->{switches}{uuid} = ""; $anvil->data->{switches}{ram} = ""; $anvil->data->{switches}{'storage-group'} = ""; $anvil->data->{switches}{'storage-size'} = ""; +$anvil->data->{switches}{'use-image'} = ""; $anvil->Get->switches; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {