LXD GO API Command Execution "Timed out waiting for websockets to connect

Im trying to get into the GO API for LXD but I can’t get the example code execution to run.
Im on a VM with Ubuntu 20.04 and LXD version 4.22 installed with snap. Im testing with a ubuntu focal container Alias 20.04 from the image source Ubuntu Cloud Images

I’m able to do other API Commands so i know connection to the unix socket works.

// Connect to LXD over the Unix socket
c, err := lxd.ConnectLXDUnix("/var/snap/lxd/common/lxd/unix.socket", nil)
if err != nil {
  return err
}

// Setup the exec request
req := api.ContainerExecPost{
  Command: []string{"bash"},
  WaitForWS: true,
  Interactive: true,
  Width: 80,
  Height: 15,
}

// Setup the exec arguments (fds)
args := lxd.ContainerExecArgs{
  Stdin: os.Stdin,
  Stdout: os.Stdout,
  Stderr: os.Stderr,
}

// Setup the terminal (set to raw mode)
if req.Interactive {
  cfd := int(syscall.Stdin)
  oldttystate, err := termios.MakeRaw(cfd)
  if err != nil {
    return err
  }

  defer termios.Restore(cfd, oldttystate)
}

// Get the current state
op, err := c.ExecContainer("c1", req, &args)
if err != nil {
  return err
}

// Wait for it to complete
err = op.Wait()
if err != nil {
  return err
}

The function runs to the point op, err := c.ExecContainer("c1", req, &args)
When it enters err = op.Wait() it takes a few seconds and i get the output “Timed out waiting for websockets to connect”

Can somebody tell me what could be the issue?

Take a look at the lxc client ExecInstance function for a working example.

You need to connect to the websockets offered by LXD and you have 10s to do that before the session is terminated.

See

Thanks for the quick reply. I will try to understand the Connection to the websocket first before trying out the ExecContainer Command.

You should use ExecInstance for compatiblity with VMs too, ExecContainer is deprecated.

Good to know. I would suggest updating the example in the LXD GO documentation lxd package - github.com/lxc/lxd/client - pkg.go.dev it is misleading. So generally i should use the Instance Commands instead of the container commands?

Please can you log an issue for that here https://github.com/lxc/lxd/issues

But yes the Instance functions are considered “current”.

1 Like

Could you help me out once more?
I don’t know what connection to use in the InstanceExecArgs. In the github code you sent me the GetOperationWebsocket returns a connection that is used. But the Instance server that i get returned after using c, err := lxd.ConnectLXDUnix("/var/snap/lxd/common/lxd/unix.socket", nil) doesnt have the GetOperationWebsocket function. What Do i have to do to get the connection required by the InstanceExecArgs ?

Its this one lxd package - github.com/lxc/lxd/client - pkg.go.dev which is part of InstanceServer (see lxd package - github.com/lxc/lxd/client - pkg.go.dev)

Just wanted to let you know. It got it working. I keep getting the error “Timed out waiting for websockets to connect” on my Ubuntu 20.04 Desktop VM trying to run the ExecInstance code example. So i tried out a Ubuntu Server 20.04 VM. There the ExecInstance code example ran fine. If anybody should have the same weird issue as me: Try Ubuntu Server.
One more detail: on the Ubuntu Server VM where it worked lxd version got 4.0.7
On the Ubuntu 20.04 Desktop VM where it gets the error lxd version got 4.22
I will test out the older lxd version on my ubuntu Desktop VM aswell and give you an Update if it will run when using the older LXD Version.

Update: When using the snap install from sudo snap install lxd --channel=4.0/stable
it does work. So i suspect that there is an error in the lxd release newer than 4.0 stable.
I will open an issue in the github on this.

The more recent LXD versions introduced a timeout for waiting for the client to connect.
We expect the control socket, plus at least 1 websocket for interactive, and 3 (stdin, stdout and stderr) for non-interactive.

Could you provide me with a working code example for more recent LXD versions? (Sorry i just started using go for the lxd api. So i’m at loss how to alter the code example from the Go documentation to work with lxc 4.22.)

There’s what we use for lxc exec command:

Thank you i will try it straight away.