goqemulibvirtvirsh

Golang libvirt guest-agent not available


I've tried to communicate with the guest agent on a qemu instance through the libvirt golang API. However, it always reject my connections with

2022-12-02T00:10:43.799+0100    DPANIC  test/main.go:335    Failed to connect to guest  {"error": "virError(Code=86, Domain=10, Message='Guest agent is not responding: QEMU guest agent is not connected')"}

Even if the qemu instance is fully booted and the guest agent is available through the commandline

sudo virsh qemu-agent-command test-vm '{"execute":"guest-info"}'

Is this a bug in the implementation or do I have to register the agent somewhere in the go code? I wasn't able to find references in the documentation.

    <channel type='unix'>
      <source mode='bind' path='/var/lib/libvirt/qemu/channel/target/domain-6-test-vm/org.qemu.guest_agent.0'/>
      <target type='virtio' name='org.qemu.guest_agent.0' state='connected'/>
      <alias name='channel0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>

Thanks!


Solution

  • Not sure what was the cause in the end. I had a loop and was accessing, or to be more specific try to access, the agent. I changed it to use a timeout of 500ms and not it works.

    type qemuStatusResponse struct {
        Return struct {
            Exitcode int    `json:"exitcode,omitempty"`
            OutData  string `json:"out-data,omitempty"`
            Exited   bool   `json:"exited,omitempty"`
            ErrData  string `json:"err-data,omitempty"`
        } `json:"return,omitempty"`
    }
    
    func (l *LibvirtInstance) waitForCompletion(ctx context.Context, pid int, domain *libvirt.Domain) (response *qemuStatusResponse, err error) {
        response = &qemuStatusResponse{}
    
        ticker := time.NewTicker(500 * time.Millisecond)
        defer ticker.Stop()
        for {
            select {
            case <-ticker.C:
                result, err := domain.QemuAgentCommand(
                    fmt.Sprintf(`
                    {
                        "execute": "guest-exec-status",
                        "arguments": {
                            "pid": %d
                        }
                        }`, pid),
                    libvirt.DOMAIN_QEMU_AGENT_COMMAND_BLOCK, 0)
                if err != nil {
                    return nil, err
                }
                if err := json.Unmarshal([]byte(result), response); err != nil {
                    return nil, err
                }
                if response.Return.Exited {
                    return response, nil
                }
            case <-ctx.Done():
                return nil, ctx.Err()
            }
        }
    }
    

    Furhtermore I had some stability issues (i.e., when executing multiple concurrent requests to the connection it was sometimes broken). I found some article in the web suggesting adding the user to the kvm group. This worked for me.