The previous implementation always decoded the base64-encoded content received from the qemu-guest-agent file-read call. Since JSON strings must be comliant unicode text, binary data got escaped using unicode escape sequences, using the pattern: \u00XX - with XX being the hex value of the byte to encode. For certain binary files, this lead to a massively inflated payload size of the API response.
Comparison on my test system: For a 4MiB test-file generated using dd if=/dev/urandom bs=4M count=1 - Reading it with decode=1 transfers 8.61MiB and takes 5700ms on avg. - Reading it with decode=0 transfers 5.59MiB and takes 3300ms on avg. To be backwards compatible, the decode parameter defaults to 1. Signed-off-by: Markus Ebner <[email protected]> --- src/PVE/API2/Qemu/Agent.pm | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/PVE/API2/Qemu/Agent.pm b/src/PVE/API2/Qemu/Agent.pm index f32e1dc2..1f5962e9 100644 --- a/src/PVE/API2/Qemu/Agent.pm +++ b/src/PVE/API2/Qemu/Agent.pm @@ -472,6 +472,15 @@ __PACKAGE__->register_method({ default => $MAX_READ_SIZE, description => "Number of bytes to read.", }, + decode => { + type => 'boolean', + optional => 1, + default => 1, + description => "Data received from the QEMU Guest-Agent is base64 encoded." + . " If this is set to true, the data is decoded." + . " Otherwise the content is forwarded with base64 encoding." + . " Defaults to true.", + }, file => { type => 'string', description => 'The path to the file', @@ -496,6 +505,7 @@ __PACKAGE__->register_method({ code => sub { my ($param) = @_; my $count = int($param->{count} // $MAX_READ_SIZE); + my $decode = $param->{decode} // 1; my $vmid = $param->{vmid}; my $conf = PVE::QemuConfig->load_config($vmid); @@ -515,7 +525,10 @@ __PACKAGE__->register_method({ mon_cmd($vmid, "guest-file-read", handle => $qgafh, count => int($chunk_size)); check_agent_error($read, "can't read from file"); - $content .= decode_base64($read->{'buf-b64'}); + my $chunk = $read->{'buf-b64'}; + $chunk = decode_base64($chunk) if $decode; + $content .= $chunk; + $bytes_read += $read->{count}; $eof = $read->{eof} // 0; } -- 2.53.0
