mirror of https://github.com/digint/btrbk
btrbk: replace "info" command with "usage", with tabular output; add support for right-aligned columns
parent
fd985d0245
commit
05bfeaff1b
|
@ -13,6 +13,7 @@ btrbk-current
|
|||
(experimental).
|
||||
* Added configuration option "timestamp_format short|long".
|
||||
* Added transaction log (configuration option "transaction_log").
|
||||
* Replaced "info" command with "usage", with tabular output.
|
||||
* Bugfix: correctly handle "incremental no" option.
|
||||
* Bugfix: return exit status 10 instead of 0 if one or more backup
|
||||
tasks aborted.
|
||||
|
|
165
btrbk
165
btrbk
|
@ -142,11 +142,17 @@ my %table_formats = (
|
|||
raw => [ qw( type source_host source_path snapshot_path snapshot_name status target_host target_path source_rsh ) ],
|
||||
},
|
||||
|
||||
schedule => { table => [ qw( action target_host target_subvol scheme reason ) ],
|
||||
long => [ qw( action host root_path name scheme reason ) ],
|
||||
schedule => { table => [ qw( action host subvol scheme reason ) ],
|
||||
long => [ qw( action host root_path subvol_path scheme reason ) ],
|
||||
raw => [ qw( topic action url host path dow d m w) ],
|
||||
},
|
||||
|
||||
usage => { table => [ qw( host path size used free ) ],
|
||||
long => [ qw( type host path size device_allocated device_unallocated device_missing used free free_min data_ratio metadata_ratio used global_reserve global_reserve_used ) ],
|
||||
raw => [ qw( type host path size device_allocated device_unallocated device_missing used free free_min data_ratio metadata_ratio used global_reserve global_reserve_used ) ],
|
||||
RALIGN => { size=>1, device_allocated=>1, device_unallocated=>1, device_missing=>1, used=>1, free=>1, free_min=>1, data_ratio=>1, metadata_ratio=>1, used=>1, global_reserve=>1, global_reserve_used=>1 },
|
||||
},
|
||||
|
||||
action_log => { table => [ qw( type status target_host target_subvol source_host source_subvol parent_subvol ) ],
|
||||
long => [ qw( localtime type status duration target_host target_subvol source_host source_subvol parent_subvol message ) ],
|
||||
raw => [ qw( time localtime type status duration target_url source_url parent_url message ) ],
|
||||
|
@ -207,7 +213,7 @@ sub HELP_MESSAGE
|
|||
print STDERR " resolve snapshots [filter...] shows snapshots and corresponding targets\n";
|
||||
print STDERR " resolve targets [filter...] shows targets and corresponding snapshots\n";
|
||||
print STDERR " resolve latest [filter...] shows latest snapshots/targets\n";
|
||||
print STDERR " info [filter...] print useful filesystem information\n";
|
||||
print STDERR " usage [filter...] print filesystem usage\n";
|
||||
print STDERR " origin <subvol> print origin information for subvolume\n";
|
||||
print STDERR " diff <from> <to> shows new files since subvolume <from> for subvolume <to>\n";
|
||||
print STDERR "\n";
|
||||
|
@ -468,16 +474,19 @@ sub vinfo_set_detail($$)
|
|||
# returns hash: ( $prefix_{url,path,host,name,subvol_path,rsh} => value, ... )
|
||||
sub vinfo_prefixed_keys($$)
|
||||
{
|
||||
my $prefix = shift || die;
|
||||
my $prefix = shift // die;
|
||||
my $vinfo = shift;
|
||||
return () unless($vinfo);
|
||||
my %ret;
|
||||
foreach (qw( URL PATH HOST NAME SUBVOL_PATH )) {
|
||||
$ret{$prefix . '_' . lc($_)} = $vinfo->{$_};
|
||||
if($prefix) {
|
||||
$ret{$prefix} = $vinfo->{PRINT};
|
||||
$prefix .= '_';
|
||||
}
|
||||
$ret{$prefix . "_subvol"} = $vinfo->{PATH};
|
||||
$ret{$prefix} = $vinfo->{PRINT};
|
||||
$ret{$prefix . "_rsh"} = ($vinfo->{RSH} ? join(" ", @{$vinfo->{RSH}}) : undef),
|
||||
foreach (qw( URL PATH HOST NAME SUBVOL_PATH )) {
|
||||
$ret{$prefix . lc($_)} = $vinfo->{$_};
|
||||
}
|
||||
$ret{$prefix . "subvol"} = $vinfo->{PATH};
|
||||
$ret{$prefix . "rsh"} = ($vinfo->{RSH} ? join(" ", @{$vinfo->{RSH}}) : undef),
|
||||
return %ret;
|
||||
}
|
||||
|
||||
|
@ -818,10 +827,53 @@ sub btrfs_filesystem_usage($)
|
|||
{
|
||||
my $vol = shift || die;
|
||||
my $path = $vol->{PATH} // die;
|
||||
return run_cmd( cmd => [ qw(btrfs filesystem usage), $path ],
|
||||
rsh => $vol->{RSH},
|
||||
non_destructive => 1
|
||||
);
|
||||
my $ret = run_cmd( cmd => [ qw(btrfs filesystem usage), $path ],
|
||||
rsh => $vol->{RSH},
|
||||
non_destructive => 1
|
||||
);
|
||||
return undef unless(defined($ret));
|
||||
|
||||
my %detail;
|
||||
foreach (split("\n", $ret)) {
|
||||
if(/^\s+Device size:\s+(\S+)/) {
|
||||
$detail{size} = $1;
|
||||
}
|
||||
elsif(/^\s+Device allocated:\s+(\S+)/) {
|
||||
$detail{device_allocated} = $1;
|
||||
}
|
||||
elsif(/^\s+Device unallocated:\s+(\S+)/) {
|
||||
$detail{device_unallocated} = $1;
|
||||
}
|
||||
elsif(/^\s+Device missing:\s+(\S+)/) {
|
||||
$detail{device_missing} = $1;
|
||||
}
|
||||
elsif(/^\s+Used:\s+(\S+)/) {
|
||||
$detail{used} = $1;
|
||||
}
|
||||
elsif(/^\s+Free \(estimated\):\s+(\S+)\s+\(min: (\S+)\)/) {
|
||||
$detail{free} = $1;
|
||||
$detail{free_min} = $2;
|
||||
}
|
||||
elsif(/^\s+Data ratio:\s+(\S+)/) {
|
||||
$detail{data_ratio} = $1;
|
||||
}
|
||||
elsif(/^\s+Metadata ratio:\s+(\S+)/) {
|
||||
$detail{metadata_ratio} = $1;
|
||||
}
|
||||
elsif(/^\s+Used:\s+(\S+)/) {
|
||||
$detail{used} = $1;
|
||||
}
|
||||
elsif(/^\s+Global reserve:\s+(\S+)\s+\(used: (\S+)\)/) {
|
||||
$detail{global_reserve} = $1;
|
||||
$detail{global_reserve_used} = $2;
|
||||
}
|
||||
else {
|
||||
TRACE "Failed to parse filesystem usage line \"$_\" for: $vol->{PRINT}";
|
||||
}
|
||||
DEBUG "Parsed " . scalar(keys %detail) . " filesystem usage detail items: $vol->{PRINT}";
|
||||
TRACE(Data::Dumper->Dump([$vol], ["btrfs_subvolume_detail($vol->{URL})"]));
|
||||
}
|
||||
return \%detail;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1854,6 +1906,8 @@ sub print_formatted(@)
|
|||
my $title = $args{title};
|
||||
my $format = $args{output_format} || $output_format || $default_format;
|
||||
my $keys = $table_formats{$format_key}->{$format};
|
||||
my $ralign = $table_formats{$format_key}->{RALIGN} // {};
|
||||
my $table_spacing = 2;
|
||||
|
||||
unless($keys) {
|
||||
WARN "Unsupported output format \"$format\", defaulting to \"$default_format\" format.";
|
||||
|
@ -1905,21 +1959,33 @@ sub print_formatted(@)
|
|||
}
|
||||
|
||||
# print keys (headings)
|
||||
my $fill = '';
|
||||
my $fill = 0;
|
||||
foreach (@$keys) {
|
||||
print $fill . $_;
|
||||
$fill = ' ' x (2 + $maxlen{$_} - length($_));
|
||||
print ' ' x $fill;
|
||||
$fill = $maxlen{$_} - length($_);
|
||||
if($ralign->{$_}) {
|
||||
print ' ' x $fill;
|
||||
$fill = 0;
|
||||
}
|
||||
print $_;
|
||||
$fill += $table_spacing;
|
||||
}
|
||||
print "\n";
|
||||
print join(" ", map { '-' x ($maxlen{$_}) } @$keys) . "\n";
|
||||
print join(' ' x $table_spacing, map { '-' x ($maxlen{$_}) } @$keys) . "\n";
|
||||
|
||||
# print values
|
||||
foreach my $row (@$data) {
|
||||
my $fill = '';
|
||||
my $fill = 0;
|
||||
foreach (@$keys) {
|
||||
my $val = $row->{$_};
|
||||
print $fill . $val;
|
||||
$fill = ' ' x (2 + $maxlen{$_} - length($val));
|
||||
print ' ' x $fill;
|
||||
$fill = $maxlen{$_} - length($val);
|
||||
if($ralign->{$_}) {
|
||||
print ' ' x $fill;
|
||||
$fill = 0;
|
||||
}
|
||||
print $val;
|
||||
$fill += $table_spacing;
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
@ -1997,7 +2063,7 @@ MAIN:
|
|||
WARN 'found option "--progress", but "pv" is not present: (please install "pv")';
|
||||
$show_progress = 0;
|
||||
}
|
||||
my ($action_run, $action_info, $action_resolve, $action_diff, $action_origin, $action_config_print, $action_list);
|
||||
my ($action_run, $action_usage, $action_resolve, $action_diff, $action_origin, $action_config_print, $action_list);
|
||||
my @filter_args;
|
||||
my $args_allow_group = 0;
|
||||
my ($args_expected_min, $args_expected_max) = (0, 0);
|
||||
|
@ -2009,8 +2075,8 @@ MAIN:
|
|||
$args_allow_group = 1;
|
||||
@filter_args = @ARGV;
|
||||
}
|
||||
elsif ($command eq "info") {
|
||||
$action_info = 1;
|
||||
elsif ($command eq "usage") {
|
||||
$action_usage = 1;
|
||||
$args_expected_min = 0;
|
||||
$args_expected_max = 9999;
|
||||
$args_allow_group = 1;
|
||||
|
@ -2250,7 +2316,7 @@ MAIN:
|
|||
#
|
||||
# filter subvolumes matching command line arguments
|
||||
#
|
||||
if(($action_run || $action_resolve || $action_info || $action_list || $action_config_print) && scalar(@filter_args))
|
||||
if(($action_run || $action_resolve || $action_usage || $action_list || $action_config_print) && scalar(@filter_args))
|
||||
{
|
||||
my %match;
|
||||
foreach my $config_vol (@{$config->{VOLUME}}) {
|
||||
|
@ -2324,29 +2390,22 @@ MAIN:
|
|||
}
|
||||
|
||||
|
||||
if($action_info)
|
||||
if($action_usage)
|
||||
{
|
||||
#
|
||||
# print filesystem information
|
||||
#
|
||||
print "================================================================================\n";
|
||||
print "Filesystem information ($version_info)\n\n";
|
||||
print " Date: " . localtime($start_time) . "\n";
|
||||
print " Config: $config->{SRC_FILE}\n";
|
||||
print "================================================================================\n";
|
||||
|
||||
my @data;
|
||||
my %processed;
|
||||
foreach my $config_vol (@{$config->{VOLUME}})
|
||||
{
|
||||
foreach my $config_vol (@{$config->{VOLUME}}) {
|
||||
next if($config_vol->{ABORTED});
|
||||
my $sroot = vinfo($config_vol->{url}, $config_vol);
|
||||
unless($processed{$sroot->{URL}})
|
||||
{
|
||||
print "\n--------------------------------------------------------------------------------\n";
|
||||
print "Source volume: $sroot->{PRINT}\n";
|
||||
print "--------------------------------------------------------------------------------\n";
|
||||
print (btrfs_filesystem_usage($sroot) // "");
|
||||
print "\n";
|
||||
unless($processed{$sroot->{URL}}) {
|
||||
my $usage = btrfs_filesystem_usage($sroot) // {};
|
||||
push @data, { %$usage,
|
||||
type => "source",
|
||||
vinfo_prefixed_keys("", $sroot),
|
||||
};
|
||||
$processed{$sroot->{URL}} = 1;
|
||||
}
|
||||
}
|
||||
|
@ -2356,22 +2415,20 @@ MAIN:
|
|||
my $sroot = vinfo($config_vol->{url}, $config_vol);
|
||||
foreach my $config_subvol (@{$config_vol->{SUBVOLUME}}) {
|
||||
next if($config_subvol->{ABORTED});
|
||||
foreach my $config_target (@{$config_subvol->{TARGET}})
|
||||
{
|
||||
foreach my $config_target (@{$config_subvol->{TARGET}}) {
|
||||
my $droot = vinfo($config_target->{url}, $config_target);
|
||||
unless($processed{$droot->{URL}})
|
||||
{
|
||||
print "\n--------------------------------------------------------------------------------\n";
|
||||
print "Target volume: $droot->{PRINT}\n";
|
||||
print " ^--- $sroot->{PRINT}\n";
|
||||
print "--------------------------------------------------------------------------------\n";
|
||||
print (btrfs_filesystem_usage($droot) // "");
|
||||
print "\n";
|
||||
unless($processed{$droot->{URL}}) {
|
||||
my $usage = btrfs_filesystem_usage($droot) // {};
|
||||
push @data, { %$usage,
|
||||
type => "target",
|
||||
vinfo_prefixed_keys("", $droot),
|
||||
};
|
||||
$processed{$droot->{URL}} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print_formatted("usage", \@data);
|
||||
exit exit_status($config);
|
||||
}
|
||||
|
||||
|
@ -3238,13 +3295,7 @@ MAIN:
|
|||
# print scheduling results
|
||||
#
|
||||
if($loglevel >= 2) {
|
||||
my @data = map { $_->{url} = $_->{value}->{URL};
|
||||
$_->{host} = $_->{value}->{HOST};
|
||||
$_->{path} = $_->{value}->{PATH};
|
||||
$_->{name} = $_->{value}->{SUBVOL_PATH};
|
||||
$_->{target} = $_->{value}->{PRINT};
|
||||
$_;
|
||||
} @$schedule_results;
|
||||
my @data = map { { %$_, vinfo_prefixed_keys("", $_->{value}) }; } @$schedule_results;
|
||||
my @data_backup = map { $_->{topic} eq "backup" ? $_ : () } @data;
|
||||
my @data_snapshot = map { $_->{topic} eq "snapshot" ? $_ : () } @data;
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ STATEMENTS\fR below). Use the \fI\-\-format\fR command line option to
|
|||
switch between different output formats.
|
||||
.RE
|
||||
.PP
|
||||
.B info
|
||||
.B usage
|
||||
[filter...]
|
||||
.RS 4
|
||||
Print filesystem usage information for all source/target
|
||||
|
|
Loading…
Reference in New Issue