diff --git a/internal/rest/resources/control.go b/internal/rest/resources/control.go index 57082a99..699fcc49 100644 --- a/internal/rest/resources/control.go +++ b/internal/rest/resources/control.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "slices" + "time" "github.com/canonical/lxd/shared" "github.com/canonical/lxd/shared/api" @@ -91,8 +92,14 @@ func controlPost(state types.State, r *http.Request) types.Response { return } + // Use an independent context for cleanup so that it is not tied + // to the request context, which may already be expired (e.g. the + // join timed out). + cleanupCtx, cleanupCancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cleanupCancel() + // Run the pre-remove hook like we do for cluster node removals. - err := intState.Hooks.PreRemove(r.Context(), state, true) + err := intState.Hooks.PreRemove(cleanupCtx, state, true) if err != nil { logger.Error("Failed to run pre-remove hook on initialization error", slog.String("error", err.Error())) } @@ -101,7 +108,7 @@ func controlPost(state types.State, r *http.Request) types.Response { // As part of this request the cluster member gets re-executed. // If we don't send the request, re-exec the member manually. if joinInfo == nil || req.JoinToken == "" { - reExec, err := resetClusterMember(r.Context(), state, true) + reExec, err := resetClusterMember(cleanupCtx, state, true) if err != nil { logger.Error("Failed to reset cluster member on bootstrap error", slog.String("error", err.Error())) return @@ -114,13 +121,15 @@ func controlPost(state types.State, r *http.Request) types.Response { } url := api.NewURL().Scheme("https").Host(joinInfo.TrustedMember.Address.String()) - cert, err := shared.GetRemoteCertificate(r.Context(), url.String(), "") + cert, err := shared.GetRemoteCertificate(cleanupCtx, url.String(), "") if err != nil { + logger.Error("Failed to get certificate of cluster member for cleanup", slog.String("address", url.String()), slog.String("error", err.Error())) return } client, err := state.Connect().Member(&url.URL, false, cert) if err != nil { + logger.Error("Failed to create client for cluster member cleanup", slog.String("address", url.String()), slog.String("error", err.Error())) return }