[TUTORIAL] qm guest exec error

Olive Kingdom Qiu

New Member
Jan 25, 2024
5
0
1
vm is centos:
execute qemu-ga -v
and node execute : pvesh get /nodes/pve1/qemu/104/agent/file-read -file /usr/local/test/中.txt

qemu-ga stdout below:

1714466760.560233: debug: received EOF
1714466760.660361: debug: received EOF
1714466760.760514: debug: received EOF
1714466760.860675: debug: received EOF
1714466760.960840: debug: read data, count: 103, data: {"execute":"guest-sync-delimited","arguments":{"id":13874501}}
{"execute":"guest-ping","arguments":{}}

1714466760.960901: debug: process_event: called
1714466760.961049: debug: processing command
1714466760.961178: debug: sending data, count: 22
1714466760.961291: debug: process_event: called
1714466760.961471: debug: processing command
1714466760.961783: debug: sending data, count: 15
1714466760.964899: debug: read data, count: 138, data: {"execute":"guest-sync-delimited","arguments":{"id":13874502}}
{"execute":"guest-file-open","arguments":{"path":"/usr/local/test/中.txt"}
1714466760.964918: debug: process_event: called
1714466760.965032: debug: processing command
1714466760.965173: debug: sending data, count: 22
1714466765.968145: debug: received EOF
1714466766.68277: debug: received EOF
1714466766.168394: debug: received EOF
1714466766.268498: debug: received EOF
1714466766.368603: debug: received EOF
1714466766.468706: debug: received EOF
1714466766.568812: debug: received EOF
1714466766.668929: debug: received EOF
1714466766.769043: debug: received EOF
1714466766.869156: debug: received EOF
1714466766.969258: debug: received EOF
1714466767.69368: debug: received EOF
1714466767.169464: debug: received EOF
1714466767.269557: debug: received EOF
1714466767.369652: debug: received EOF

and node stdout below :
VM 104 qmp command 'guest-file-open' failed - got timeout

otherwise: vm system is windows 10 , qm guest exec vmid command , when command contains simple Chinise , qemu-guest-agent down and nerver restart . and the node stdout is the same .

how can i handle it when command contains simple Chinise ?

appreciate to give some advice
 
use api
/api2/json/nodes/pve/qemu/104/agent/exec

{
"command": "powershell",
"input-data": "Get-Content -path C:\\Users\\ct\\中.txt \r\n"
}

the result :
Wide character in subroutine entry at /usr/share/perl5/PVE/QemuServer/Agent.pm line 81

when i check source code about:
use MIME::Base64 qw(decode_base64 encode_base64);

https://docs.mojolicious.org/MIME/Base64 , it means (encode_base64( $bytes )encode_base64( $bytes, $eol );):The function will croak with "Wide character in subroutine entry" if $bytes contains characters with code above 255. The base64 encoding is only defined for single-byte characters. Use the Encode module to select the byte encoding you want.

choose use Encode Module ,it goes error: got time out .
is it a bug ?@Folke
 
never mind , i change the Agent.pm
Perl:
package PVE::QemuServer::Agent;


use strict;
use warnings;


use PVE::QemuServer;
use PVE::QemuServer::Monitor;
use MIME::Base64 qw(decode_base64 encode_base64);
use JSON;
use Encode qw(encode);
use base 'Exporter';


our @EXPORT_OK = qw(
check_agent_error
agent_available
agent_cmd
);


sub check_agent_error {
    my ($result, $errmsg, $noerr) = @_;


    $errmsg //= '';
    my $error = '';
    if (ref($result) eq 'HASH' && $result->{error} && $result->{error}->{desc}) {
        $error = "Agent error: $result->{error}->{desc}\n";
    } elsif (!defined($result)) {
        $error = "Agent error: $errmsg\n";
    }


    if ($error) {
        die $error if !$noerr;


        warn $error;
        return;
    }


    return 1;
}


sub agent_available {
    my ($vmid, $conf, $noerr) = @_;


    eval {
        die "No QEMU guest agent configured\n" if !defined($conf->{agent});
        die "VM $vmid is not running\n" if !PVE::QemuServer::check_running($vmid);
        die "QEMU guest agent is not running\n" if !PVE::QemuServer::qga_check_running($vmid, 1);
    };


    if (my $err = $@) {
        die $err if !$noerr;
        return;
    }


    return 1;
}


# loads config, checks if available, executes command, checks for errors
sub agent_cmd {
    my ($vmid, $cmd, $params, $errormsg, $noerr) = @_;


    my $conf = PVE::QemuConfig->load_config($vmid); # also checks if VM exists
    agent_available($vmid, $conf, $noerr);


    my $res = PVE::QemuServer::Monitor::mon_cmd($vmid, "guest-$cmd", %$params);
    check_agent_error($res, $errormsg, $noerr);


    return $res;
}


sub qemu_exec {
    my ($vmid, $input_data, $cmd) = @_;


    my $args = {
        'capture-output' => JSON::true,
    };


    if ($cmd) {
        $args->{path} = shift @$cmd;
        $args->{arg} = $cmd;
    }


    $args->{'input-data'} = encode_base64(encode('UTF-8',$input_data)) if defined($input_data);
    #$args->{'input-data'} = encode_base64($input_data, '') if defined($input_data);


    die "command or input-data (or both) required\n"
        if !defined($args->{'input-data'}) && !defined($args->{path});


    my $errmsg = "can't execute command";
    if ($cmd) {
        $errmsg .= " ($args->{path} $args->{arg})";
    }
    if (defined($input_data)) {
        $errmsg .= " (input-data given)";
    }


    my $res = agent_cmd($vmid, "exec", $args, $errmsg);


    return $res;
}


sub qemu_exec_status {
    my ($vmid, $pid) = @_;


    my $res = agent_cmd($vmid, "exec-status", { pid => $pid }, "can't get exec status for '$pid'");


    if ($res->{'out-data'}) {
        my $decoded = eval { decode_base64($res->{'out-data'}) };
        warn $@ if $@;
        if (defined($decoded)) {
            $res->{'out-data'} = $decoded;
        }
    }


    if ($res->{'err-data'}) {
        my $decoded = eval { decode_base64($res->{'err-data'}) };
        warn $@ if $@;
        if (defined($decoded)) {
            $res->{'err-data'} = $decoded;
        }
    }


    # convert JSON::Boolean to 1/0
    foreach my $d (keys %$res) {
        if (JSON::is_bool($res->{$d})) {
            $res->{$d} = ($res->{$d})? 1 : 0;
        }
    }


    return $res;
}


1;

finally, it works well . pve version 7.4.1