Initial version of sshfs storage backend

This commit is contained in:
Johannes Zellner
2020-06-05 11:39:51 +02:00
parent 0b2eb8fb9e
commit 6f60495d4d
3 changed files with 123 additions and 0 deletions

119
src/storage/sshfs.js Normal file
View File

@@ -0,0 +1,119 @@
'use strict';
exports = module.exports = {
upload: upload,
download: download,
copy: copy,
listDir: listDir,
remove: remove,
removeDir: removeDir,
testConfig: testConfig,
removePrivateFields: removePrivateFields,
injectPrivateFields: injectPrivateFields
};
var assert = require('assert'),
BoxError = require('../boxerror.js'),
debug = require('debug')('box:storage/sshfs'),
filesystem = require('./filesystem.js'),
mkdirp = require('mkdirp'),
path = require('path'),
safe = require('safetydance'),
shell = require('../shell.js');
// we mostly reuse the filesystem.js implementation but the config params are different
function translateConfig(apiConfig) {
assert.strictEqual(typeof apiConfig, 'object');
// skip chown
apiConfig._doNotChown = true;
// do not preserver file attributes
apiConfig._doNotPreserveAttributes = true;
// resolve the actual path
apiConfig.backupFolder = path.join(apiConfig.mountPoint, apiConfig.prefix);
return apiConfig;
}
// storage api
function upload(apiConfig, backupFilePath, sourceStream, callback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof backupFilePath, 'string');
assert.strictEqual(typeof sourceStream, 'object');
assert.strictEqual(typeof callback, 'function');
filesystem.upload(translateConfig(apiConfig), backupFilePath, sourceStream, callback);
}
function download(apiConfig, sourceFilePath, callback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof sourceFilePath, 'string');
assert.strictEqual(typeof callback, 'function');
filesystem.download(translateConfig(apiConfig), sourceFilePath, callback);
}
function listDir(apiConfig, dir, batchSize, iteratorCallback, callback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof dir, 'string');
assert.strictEqual(typeof batchSize, 'number');
assert.strictEqual(typeof iteratorCallback, 'function');
assert.strictEqual(typeof callback, 'function');
filesystem.listDir(translateConfig(apiConfig), dir, batchSize, iteratorCallback, callback);
}
function copy(apiConfig, oldFilePath, newFilePath) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof oldFilePath, 'string');
assert.strictEqual(typeof newFilePath, 'string');
return filesystem.copy(translateConfig(apiConfig), oldFilePath, newFilePath);
}
function remove(apiConfig, filename, callback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof filename, 'string');
assert.strictEqual(typeof callback, 'function');
filename.remove(translateConfig(apiConfig), filename, callback);
}
function removeDir(apiConfig, pathPrefix) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof pathPrefix, 'string');
return filesystem.removeDir(translateConfig(apiConfig), pathPrefix);
}
function testConfig(apiConfig, callback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof callback, 'function');
if (!apiConfig.mountPoint || typeof apiConfig.mountPoint !== 'string') return callback(new BoxError(BoxError.BAD_FIELD, 'mountPoint must be non-empty string', { field: 'mountPoint' }));
if ('noHardlinks' in apiConfig && typeof apiConfig.noHardlinks !== 'boolean') return callback(new BoxError(BoxError.BAD_FIELD, 'noHardlinks must be boolean', { field: 'noHardLinks' }));
if (typeof apiConfig.prefix !== 'string') return callback(new BoxError(BoxError.BAD_FIELD, 'prefix must be a string', { field: 'prefix' }));
// TODO check fstab entry
// TODO check mountpoint
// TODO check we can stat backup dir
// TODO check backup dir is dir
// TODO check we can create 'snapshot' folder
// TODO check we can write to backup dir (create and remove test file)
callback(null);
}
function removePrivateFields(apiConfig) {
return apiConfig;
}
function injectPrivateFields(/* newConfig, currentConfig */) {
}