Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(backup): make remote immutable #6928

Merged
merged 1 commit into from
Jan 31, 2024
Merged

feat(backup): make remote immutable #6928

merged 1 commit into from
Jan 31, 2024

Conversation

fbeauchamp
Copy link
Collaborator

@fbeauchamp fbeauchamp commented Jun 30, 2023

Description

in the doc folder of the new package

one watcher per vm should not overload the remote, even with a few thousands VMs saved ( default inotify allow 8192 watcher )

review by commit

Checklist

  • Commit
    • Title follows commit conventions
    • Reference the relevant issue (Fixes #007, See xoa-support#42, See https://...)
    • If bug fix, add Introduced by
  • Changelog
    • If visible by XOA users, add changelog entry
    • Update "Packages to release" in CHANGELOG.unreleased.md
  • PR
    • If UI changes, add screenshots
    • If not finished or not tested, open as Draft

@fbeauchamp fbeauchamp changed the title feat: make local remote immutable feat: make remote immutable Jun 30, 2023
@fbeauchamp fbeauchamp changed the title feat: make remote immutable feat(backup): make remote immutable Jun 30, 2023
@fbeauchamp fbeauchamp force-pushed the feat_immutable branch 2 times, most recently from 23b19ab to 9776785 Compare December 5, 2023 15:58
@fbeauchamp fbeauchamp force-pushed the feat_immutable branch 7 times, most recently from 87019e1 to 6d83b84 Compare December 15, 2023 14:24
@julien-f julien-f self-requested a review December 15, 2023 16:00

## Making a file immutable

when marking a file or a folder immutable, it create an alias file in `.immutable/<hash of full path>.<file|dir>.<extension>` containing the path to the folder/file and make this file also immutable.
Copy link
Member

Choose a reason for hiding this comment

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

IMHO we should add a directory level to prevent issues when lots of entries: hash[0]/hash[1].

It's pretty easy and can help if there are a lot of entries.


## Making a file immutable

when marking a file or a folder immutable, it create an alias file in `.immutable/<hash of full path>.<file|dir>.<extension>` containing the path to the folder/file and make this file also immutable.
Copy link
Member

Choose a reason for hiding this comment

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

The path format used for hashing must be properly documented: / vs \, relative vs absolute, leading or trailing slash, etc.


## Making a file immutable

when marking a file or a folder immutable, it create an alias file in `.immutable/<hash of full path>.<file|dir>.<extension>` containing the path to the folder/file and make this file also immutable.
Copy link
Member

Choose a reason for hiding this comment

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

I'm ill-at-ease with the fact that the content of these files will not be encrypted even if the rest of remote is.

What bothers me is the inconsistency.

Possible solutions:

  • use symlinks instead
  • put these files in a specific directory which will only contain unencrypted files.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

  • symlinks can't be made immutable chattr: Operation not supported while reading flags on source
  • I think we don't really need to have xo use the hidden index folder


## Configuring

this package uses app-conf to store its config. The application name id `immutable-backup`
Copy link
Member

Choose a reason for hiding this comment

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

IMHO, the application name should contain xo, example: xo-immutable-manager

@fbeauchamp
Copy link
Collaborator Author

the merge process on vhd file rename files, it is correctly detected as a change event by chokidar, thus, not making he merged vhd immutable anew

}
await fs.writeFile(settingPath,
JSON.stringify({
since: +new Date(),
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
since: +new Date(),
since: Date.now(),

@fbeauchamp fbeauchamp force-pushed the feat_immutable branch 3 times, most recently from 13f4af5 to 48dafaa Compare January 12, 2024 16:21
@fbeauchamp fbeauchamp marked this pull request as ready for review January 12, 2024 16:22
async function handleExistingFile(root, immutabilityIndexPath, path) {
try {
// a vhd block directory is completly immutable
if (path.split('/').length === 8) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

should watch against dirname = .vhd

// with awaitWriteFinish we have complete files here
// we can make them immutable

if (path.split('/').length === 8) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

should watch against dirname = .vhd

if (path.split('/').length === 8) {
// watching a vhd block
// wait for header/footer and BAT before making this immutable recursively
const splitted = path.split('/')
Copy link
Member

Choose a reason for hiding this comment

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

path.split(nodePath.separator)

const vmUuid = splitted[1]
const vdiUuid = splitted[4]
const uniqPath = `${vmUuid}/${vdiUuid}`
const { existing } = pendingVhds.get(uniqPath)
Copy link
Collaborator Author

@fbeauchamp fbeauchamp Jan 26, 2024

Choose a reason for hiding this comment

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

const { existing } = pendingVhds.get(uniqPath) ?? {}

} else {
// already two of the key files,and we got the last one
if (existing === 2) {
Directory.makeImmutable(join(root, dirname(path)))
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

delete pendingvhds entry after

await File.makeImmutable(testPath, immutabilityCachePath)
try {
await fs.writeFile(testPath, `test immut change 2 ${new Date()}`)
await fs.unlink(testPath)
Copy link
Member

Choose a reason for hiding this comment

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

unlink is not tested due to rejection from writeFile.

Comment on lines 37 to 41
} catch (error) {
if (error.code !== 'EPERM') {
throw error
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Use assert.rejects.

for await (const { index, target } of listOlderTargets(immutabilityCachePath, immutabilityDuration)) {
await Directory.liftImmutability(target, immutabilityCachePath)
await fs.unlink(index)
if (target.match(/xo-vm-backups\/[^/]+\/[^/]+\.json$/)) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

extract this method

Comment on lines 27 to 30
const { remotes } = await loadConfig(APP_NAME, {
appDir: APP_DIR,
ignoreUnknownFormats: true,
})
Copy link
Member

Choose a reason for hiding this comment

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

Extract in _config.mjs.

})

for (const [remoteId, {indexPath,immutabilityDuration}] of Object.entries(remotes)) {
const basePath = indexPath ?? process.env.XDG_DATA_HOME ?? join('~', '.local', 'share')
Copy link
Member

Choose a reason for hiding this comment

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

Extract in _indexPath.mjs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I put the logic in the _loadConfig.mjs , my intention is that the config is either rejected or ready to use

await fs.unlink(index)
if (target.match(/xo-vm-backups\/[^/]+\/[^/]+\.json$/)) {
// snipe vm metadata cache to force XO to update it
await fs.unlink(join(dirname(target), 'cache.json.gz'))
Copy link
Member

Choose a reason for hiding this comment

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

Extract in _deleteCache.mjs.

Comment on lines 89 to 92
get immutability(){
return this.#immutability
}

Copy link
Member

Choose a reason for hiding this comment

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

IMHO, this should not be in fs, move into async RemoteAdapter.getImmutability() and it can have a cache.

return await this.#addSyncStackTrace(retry, () => fs.readFile(filePath, options), this.#retriesOnEagain)
const isPath = typeof file === 'string'
return await this.#addSyncStackTrace(retry, () => {
if(isPath){
Copy link
Member

Choose a reason for hiding this comment

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

Prettier did not passed on this file.

let fd
try {
// this will trigger e EPERM error if the file is immutable
fd = (await handler.openFile(path, 'r+')).fd
Copy link
Member

Choose a reason for hiding this comment

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

You don't need to do that, you can pass flags to readFile.

@fbeauchamp fbeauchamp requested a review from julien-f January 29, 2024 09:49
@fbeauchamp fbeauchamp force-pushed the feat_immutable branch 4 times, most recently from 734136e to 8d16242 Compare January 29, 2024 10:05
@julien-f julien-f force-pushed the feat_immutable branch 3 times, most recently from 0d9339b to 9494f64 Compare January 31, 2024 15:23
@julien-f julien-f force-pushed the feat_immutable branch 2 times, most recently from 4147fc2 to d0c7a8e Compare January 31, 2024 15:55
@julien-f julien-f merged commit ed7046c into master Jan 31, 2024
1 check failed
@julien-f julien-f deleted the feat_immutable branch January 31, 2024 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants