Skip to content

Implement direct backup exports#2899

Merged
stgraber merged 14 commits intolxc:mainfrom
bensmrs:direct-export
Feb 8, 2026
Merged

Implement direct backup exports#2899
stgraber merged 14 commits intolxc:mainfrom
bensmrs:direct-export

Conversation

@bensmrs
Copy link
Copy Markdown
Contributor

@bensmrs bensmrs commented Feb 5, 2026

Closes: #2807

@bensmrs bensmrs requested a review from stgraber as a code owner February 5, 2026 19:37
@github-actions github-actions bot added Documentation Documentation needs updating API Changes to the REST API labels Feb 5, 2026
@bensmrs
Copy link
Copy Markdown
Contributor Author

bensmrs commented Feb 5, 2026

@stgraber, quick notes and questions.

  1. You mentioned that we should forbid using the name parameter when performing direct backups; there are several places in the code where that could happen, should I put the check in the REST API functions in cmd/incusd?
  2. I noticed that image backup lifecycle events are done in cmd/incusd/backup.go, but that is not the case for the others (storage volumes and buckets); any particular reason or just legacy?
  3. I didn’t care about making the operations cancellable; do you insist on that?

@stgraber
Copy link
Copy Markdown
Member

stgraber commented Feb 5, 2026

You mentioned that we should forbid using the name parameter when performing direct backups; there are several places in the code where that could happen, should I put the check in the REST API functions in cmd/incusd?

Yeah, request validation should happen as early as possible, so directly in the Post handler would be good.

@stgraber
Copy link
Copy Markdown
Member

stgraber commented Feb 5, 2026

I noticed that image backup lifecycle events are done in cmd/incusd/backup.go, but that is not the case for the others (storage volumes and buckets); any particular reason or just legacy?

I don't think there's any particular reason for that. The package setup for backups is a bit unusual so that may have had something to do with it. In practice, so long as it's done in a spot that's reliable, we're fine :)

@stgraber
Copy link
Copy Markdown
Member

stgraber commented Feb 5, 2026

I didn’t care about making the operations cancellable; do you insist on that?

Nah, very few operations are cancellable, it's basically limited to operations that download stuff from the Internet and which can therefore be easily cancelled.

In the case of streaming backups out, the background operation wouldn't even really be needed as the API call is synchronous in this case and a cancellation would come in the way of a closed connection from the user having closed their side of the connection. That will make all write operations fail which will in turn cancel everything.

@bensmrs
Copy link
Copy Markdown
Contributor Author

bensmrs commented Feb 6, 2026

I don't think there's any particular reason for that. The package setup for backups is a bit unusual so that may have had something to do with it. In practice, so long as it's done in a spot that's reliable, we're fine :)

Alright, I’m wondering if streamed backups should trigger a lifecycle event. I don’t know if these events implicitly convey some kind of object creation on the server, in which case they should be disabled.

Nah, very few operations are cancellable, it's basically limited to operations that download stuff from the Internet and which can therefore be easily cancelled.

Well, closing a pipe is also pretty easy, it’s just that I felt lazy.

In the case of streaming backups out, the background operation wouldn't even really be needed as the API call is synchronous in this case and a cancellation would come in the way of a closed connection from the user having closed their side of the connection. That will make all write operations fail which will in turn cancel everything.

Agreed, but I think it’s pretty nice to have a reporting that this action is currently running. In a way, console access isn’t completely asynchronous either, from a high level (there’s bidirectional data that can only flow if the consumer stays there).
Now, imagine that I’m the cluster admin and I want to free up some space, really quickly. A user is backing up a 1TiB instance and I need that TiB now, so I’m deleting the instance. My understanding is that the data will only be cleared when the user has finished their backup, which can impact my usage of the cluster.

@bensmrs
Copy link
Copy Markdown
Contributor Author

bensmrs commented Feb 6, 2026

Maybe I’m whatifing too much :)

@stgraber
Copy link
Copy Markdown
Member

stgraber commented Feb 6, 2026

Alright, I’m wondering if streamed backups should trigger a lifecycle event. I don’t know if these events implicitly convey some kind of object creation on the server, in which case they should be disabled.

The event should be emitted. Lifecycle events are meant for auditing activity on an Incus server.

@bensmrs
Copy link
Copy Markdown
Contributor Author

bensmrs commented Feb 6, 2026

Eh, there are quite a few more edge cases to fix. Pipes are fun. I also need to prevent creating DB entries.

@bensmrs bensmrs force-pushed the direct-export branch 3 times, most recently from 8e04e1f to 4fac193 Compare February 6, 2026 13:27
@bensmrs
Copy link
Copy Markdown
Contributor Author

bensmrs commented Feb 6, 2026

Alright, that should be good now.

return nil
}

type pipeResponse struct {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily opposed to introducing this simpler response type, but what was the issue with using FileResponse instead?

I thought we had support for streaming data out like that by using a single file with the following set:

  • Identifier
  • Filename
  • File
  • FileSize
  • FileModified

Copy link
Copy Markdown
Contributor Author

@bensmrs bensmrs Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is this: https://cs.opensource.google/go/go/+/refs/tags/go1.25.7:src/net/http/fs.go;l=247

We really don’t want to seek to the end of our stream :)
And there are plenty of other hidden features of ServeContent that are not well-suited for streamed data.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough :)

@stgraber
Copy link
Copy Markdown
Member

stgraber commented Feb 7, 2026

This actually ended up looking a lot cleaner than I expected ;)

@bensmrs
Copy link
Copy Markdown
Contributor Author

bensmrs commented Feb 7, 2026

Ok I’ll do those quick patches later today.

@bensmrs
Copy link
Copy Markdown
Contributor Author

bensmrs commented Feb 8, 2026

I got caught up in other matters, I’m looking into this now.
(Rebasing in a separate force-push to simplify auditing the diffs)

@bensmrs bensmrs force-pushed the direct-export branch 2 times, most recently from e1bb401 to e226cbf Compare February 8, 2026 19:41
@stgraber stgraber merged commit fd654ff into lxc:main Feb 8, 2026
104 of 108 checks passed
@bensmrs bensmrs deleted the direct-export branch February 11, 2026 14:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API Changes to the REST API Documentation Documentation needs updating

Development

Successfully merging this pull request may close these issues.

Allow sending backups with no intermediary file

2 participants