Skip to content

Commit

Permalink
lxd-agent: Adds an operation wait endpoint.
Browse files Browse the repository at this point in the history
After recent changes to the client in canonical#12349, when calling ExecInstance
we wait for the operation to complete by directly calling the operation
wait endpoint instead of listening for the event.

When calling exec on a VM, the client is used to connect with the LXD
agent via vsock. This was failing with a 404 because the
endpoint didn't exist.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
  • Loading branch information
markylaing authored and tomponline committed Nov 30, 2023
1 parent 69bea35 commit 778a07c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
1 change: 1 addition & 0 deletions lxd-agent/api_1.0.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var api10 = []APIEndpoint{
operationsCmd,
operationCmd,
operationWebsocket,
operationWait,
sftpCmd,
stateCmd,
}
Expand Down
46 changes: 46 additions & 0 deletions lxd-agent/operations.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package main

import (
"context"
"fmt"
"log"
"net/http"
"net/url"
"strings"
"time"

"github.com/gorilla/mux"

Expand Down Expand Up @@ -35,6 +37,11 @@ var operationWebsocket = APIEndpoint{
Get: APIEndpointAction{Handler: operationWebsocketGet},
}

var operationWait = APIEndpoint{
Path: "operations/{id}/wait",
Get: APIEndpointAction{Handler: operationWaitGet},
}

func operationDelete(d *Daemon, r *http.Request) response.Response {
id, err := url.PathUnescape(mux.Vars(r)["id"])
if err != nil {
Expand Down Expand Up @@ -158,3 +165,42 @@ func operationWebsocketGet(d *Daemon, r *http.Request) response.Response {

return operations.OperationWebSocket(r, op)
}

func operationWaitGet(d *Daemon, r *http.Request) response.Response {
id, err := url.PathUnescape(mux.Vars(r)["id"])
if err != nil {
return response.InternalError(fmt.Errorf("Failed to extract operation ID from URL: %w", err))
}

timeoutSecs, err := shared.AtoiEmptyDefault(r.FormValue("timeout"), -1)
if err != nil {
return response.InternalError(fmt.Errorf("Failed to extract operation wait timeout from URL: %w", err))
}

var ctx context.Context
var cancel context.CancelFunc
if timeoutSecs > -1 {
ctx, cancel = context.WithDeadline(r.Context(), time.Now().Add(time.Second*time.Duration(timeoutSecs)))
} else {
ctx, cancel = context.WithCancel(r.Context())
}

defer cancel()

op, err := operations.OperationGetInternal(id)
if err != nil {
return response.NotFound(err)
}

err = op.Wait(ctx)
if err != nil {
return response.SmartError(err)
}

_, opAPI, err := op.Render()
if err != nil {
return response.SmartError(err)
}

return response.SyncResponse(true, opAPI)
}

0 comments on commit 778a07c

Please sign in to comment.