[pve-devel] [pve-common 2/4] CLIFormatter: define some commonly useful rendering functions

Thomas Lamprecht t.lamprecht at proxmox.com
Mon Jul 2 14:10:41 CEST 2018


On 7/2/18 1:34 PM, Dietmar Maurer wrote:
> Signed-off-by: Dietmar Maurer <dietmar at proxmox.com>
> ---
>  src/PVE/CLIFormatter.pm | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 54 insertions(+)
> 
> diff --git a/src/PVE/CLIFormatter.pm b/src/PVE/CLIFormatter.pm
> index b50464d..14ca9d4 100644
> --- a/src/PVE/CLIFormatter.pm
> +++ b/src/PVE/CLIFormatter.pm
> @@ -10,6 +10,60 @@ use JSON;
>  use utf8;
>  use Encode;
>  
> +sub render_duration {
> +    my ($duration_in_seconds) = @_;
> +
> +    my $text = '';
> +    my $rest = $duration_in_seconds;
> +    if ((my $days = int($rest/(24*3600))) > 0) {
> +	$text .= " " if length($text);
                     ^^^^^^^^^^^^^^^^^ 

could be omitted, never true here. An alternative general version:
(not because yours is bad in anyway, rather because text renderers
are somewhat fun ^^):

my $text = '';
my $rest = shift // die "$0 SECONDS\n";

my $step = sub {
   my ($unit, $unitlength) = @_;

   if ((my $v = int($rest/$unitlength)) > 0) {
	$text .= " " if length($text);
	$text .= "${v}${unit}";
	$rest -= $v * $unitlength;
   }
};

$step->('w', 7*24*3600);
$step->('d', 24*3600);
$step->('h', 3600);
$step->('m', 60);
$step->('s', 1);


> +	$text .= "${days}d";
> +	$rest -= $days*24*3600;
> +    }
> +    if ((my $hours = int($rest/3600)) > 0) {
> +	$text .= " " if length($text);
> +	$text .= "${hours}h";
> +	$rest -= $hours*3600;
> +    }
> +    if ((my $minutes = int($rest/60)) > 0) {
> +	$text .= " " if length($text);
> +	$text .= "${minutes}m";
> +	$rest -= $minutes*60;
> +    }
> +    if ($rest > 0) {
> +	$text .= " " if length($text);
> +	$text .= "${rest}s";
> +    }
> +    return $text;
> +}
> +
> +PVE::JSONSchema::register_renderer('duration', \&render_duration);
> +
> +sub render_fraction_as_percentage {
> +    my ($fraction) = @_;
> +
> +    return sprintf("%.2f%%", $fraction*100);
> +}
> +
> +PVE::JSONSchema::register_renderer(
> +    'fraction_as_percentage', \&render_fraction_as_percentage);
> +
> +sub render_bytes {
> +    my ($bytes) = @_;
> +
> +    if ((my $gib = $bytes/(1024*1024*1024)) >= 1) {
> +	return sprintf("%.2fGiB", $gib);
> +    } elsif ((my $mib = $bytes/1024*1024) >= 1) {
> +	return sprintf("%.2fMiB", $mib);
> +    } elsif ((my $kib = $bytes/1024) >= 1) {
> +	return sprintf("%.2fKiB", $kib);
> +    } else {
> +	return "${bytes}";
> +    }

I recently sent a patch[0] which included such a method in a bit more generic way,
slightly adapted to match your output it'd be:

sub render_bytes {
    my ($value) = @_;

    my @units = qw(B KiB MiB GiB TiB PiB);

    my $max_unit = 0;
    if ($value > 1023) {
	$max_unit = int(log($value)/log(1024));
	$value /= 1024**($max_unit);
    }

    return sprintf "%.2f $units[$max_unit]", $value;
}

Simply gets the log_1024 of the value to determine to which decimal
point we can scale and prints it.
Especially for storages TiB may not be uncommon, and I like the general/scalable
way of this method.

[0]: https://pve.proxmox.com/pipermail/pve-devel/2018-June/032805.html

> +}
> +
> +PVE::JSONSchema::register_renderer('bytes', \&render_bytes);
> +
>  sub query_terminal_options {
>      my ($options) = @_;
>  
> 





More information about the pve-devel mailing list