You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cvm/src/image-store.js

61 lines
1.8 KiB
JavaScript

'use strict';
const Promise = require("bluebird");
const bhttp = require("bhttp");
const uuid = require("uuid");
const fs = Promise.promisifyAll(require("fs-extra"));
const path = require("path");
const endOfStreamAsync = Promise.promisify(require("end-of-stream"));
const progressIndicator = require("./tasks/progress-indicator");
module.exports = function createImageStore(storagePath) {
function getPath(id) {
return path.join(storagePath, `${id}.iso`);
}
return {
addFromUrl: function addFromUrl(url) {
return Promise.try(() => {
return bhttp.get(url, {stream: true});
}).then((response) => {
if (response.statusCode !== 200) {
throw new Error(`Encountered a non-200 status code while attempting to download image (status code was ${response.statusCode})`);
}
let imageId = uuid.v4();
let targetStream = fs.createWriteStream(getPath(imageId));
let totalSize = null;
if (response.headers["content-length"] != null) {
totalSize = parseInt(response.headers["content-length"]);
}
let downloadTracker = progressIndicator(totalSize, imageId);
response.on("progress", (completedBytes, totalBytes) => {
downloadTracker.report(completedBytes);
});
response.pipe(targetStream);
// FIXME: Potential race condition? Are writes handled asynchronously? If so, then we may run into issues here, if the downloadTracker completion is based on the last source read, rather than the last destination write.
return downloadTracker;
});
},
addFromPath: function addFromPath(path) {
return Promise.try(() => {
let imageId = uuid.v4();
return Promise.try(() => {
return fs.copyAsync(path, getPath(imageId), {
overwrite: false
});
}).then(() => {
return imageId;
});
})
}
}
}