add volume support

part of #668, #569
This commit is contained in:
Girish Ramakrishnan
2020-04-22 19:18:04 -07:00
parent b46d3e74d6
commit b8bb69f730
20 changed files with 864 additions and 38 deletions

View File

@@ -47,7 +47,7 @@ var addons = require('./addons.js'),
shell = require('./shell.js'),
safe = require('safetydance'),
util = require('util'),
_ = require('underscore');
volumes = require('./volumes.js');
const CLEARVOLUME_CMD = path.join(__dirname, 'scripts/clearvolume.sh'),
MKDIRVOLUME_CMD = path.join(__dirname, 'scripts/mkdirvolume.sh');
@@ -188,11 +188,34 @@ function downloadImage(manifest, callback) {
}, callback);
}
function createSubcontainer(app, name, cmd, options, callback) {
function getEnvAndMounts(app, callback) {
addons.getEnvironment(app, function (error, addonEnv) {
if (error) return callback(error);
let mounts = addons.getMountsSync(app, app.manifest.addons);
volumes.getAppMounts(app.id, function (error, volumes) {
if (error) return callback(error);
volumes.forEach(function (volume) {
mounts.push({
Target: `/media/${volume.name}`, // mnt is for temporary mounts. media is for removable mounts
Source: volume.id,
Type: 'volume',
ReadOnly: volume.readOnly
});
});
callback(null, addonEnv, mounts);
});
});
}
function createSubcontainer(app, name, cmd, callback) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof name, 'string');
assert(!cmd || util.isArray(cmd));
assert.strictEqual(typeof options, 'object');
assert.strictEqual(typeof callback, 'function');
let isAppContainer = !cmd; // non app-containers are like scheduler and exec (terminal) containers
@@ -249,7 +272,7 @@ function createSubcontainer(app, name, cmd, options, callback) {
// if required, we can make this a manifest and runtime argument later
if (!isAppContainer) memoryLimit *= 2;
addons.getEnvironment(app, function (error, addonEnv) {
getEnvAndMounts(app, function (error, addonEnv, mounts) {
if (error) return callback(error);
// do no set hostname of containers to location as it might conflict with addons names. for example, an app installed in mail
@@ -276,7 +299,7 @@ function createSubcontainer(app, name, cmd, options, callback) {
'isCloudronManaged': String(true)
},
HostConfig: {
Mounts: addons.getMountsSync(app, app.manifest.addons),
Mounts: mounts,
LogConfig: {
Type: 'syslog',
Config: {
@@ -317,8 +340,6 @@ function createSubcontainer(app, name, cmd, options, callback) {
];
}
containerOptions = _.extend(containerOptions, options);
debugApp(app, 'Creating container for %s', app.manifest.dockerImage);
gConnection.createContainer(containerOptions, function (error, container) {
@@ -330,7 +351,7 @@ function createSubcontainer(app, name, cmd, options, callback) {
}
function createContainer(app, callback) {
createSubcontainer(app, app.id /* name */, null /* cmd */, { } /* options */, callback);
createSubcontainer(app, app.id /* name */, null /* cmd */, callback);
}
function startContainer(containerId, callback) {
@@ -573,10 +594,10 @@ function memoryUsage(containerId, callback) {
});
}
function createVolume(app, name, volumeDataDir, callback) {
assert.strictEqual(typeof app, 'object');
function createVolume(name, volumeDataDir, labels, callback) {
assert.strictEqual(typeof name, 'string');
assert.strictEqual(typeof volumeDataDir, 'string');
assert.strictEqual(typeof labels, 'object');
assert.strictEqual(typeof callback, 'function');
const volumeOptions = {
@@ -587,10 +608,7 @@ function createVolume(app, name, volumeDataDir, callback) {
device: volumeDataDir,
o: 'bind'
},
Labels: {
'fqdn': app.fqdn,
'appId': app.id
},
Labels: labels
};
// requires sudo because the path can be outside appsdata
@@ -600,13 +618,12 @@ function createVolume(app, name, volumeDataDir, callback) {
gConnection.createVolume(volumeOptions, function (error) {
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
callback();
callback(null);
});
});
}
function clearVolume(app, name, options, callback) {
assert.strictEqual(typeof app, 'object');
function clearVolume(name, options, callback) {
assert.strictEqual(typeof name, 'string');
assert.strictEqual(typeof options, 'object');
assert.strictEqual(typeof callback, 'function');
@@ -626,14 +643,13 @@ function clearVolume(app, name, options, callback) {
}
// this only removes the volume and not the data
function removeVolume(app, name, callback) {
assert.strictEqual(typeof app, 'object');
function removeVolume(name, callback) {
assert.strictEqual(typeof name, 'string');
assert.strictEqual(typeof callback, 'function');
let volume = gConnection.getVolume(name);
volume.remove(function (error) {
if (error && error.statusCode !== 404) return callback(new BoxError(BoxError.DOCKER_ERROR, `removeVolume: Error removing volume of ${app.id} ${error.message}`));
if (error && error.statusCode !== 404) return callback(new BoxError(BoxError.DOCKER_ERROR, `Error removing volume: ${error.message}`));
callback();
});