Progress for default images and vbox

This commit is contained in:
Jeff Morgan 2014-09-09 16:23:48 -07:00
parent 8ebc911f85
commit cab775f9c2
10 changed files with 196 additions and 51 deletions

View File

@ -6,6 +6,9 @@ var path = require('path');
Docker = {};
Docker.DOCKER_HOST = '192.168.60.103';
Docker.DEFAULT_IMAGES_FILENAME = 'base-images-0.0.2.tar.gz';
Docker.DEFAULT_IMAGES_CHECKSUM = '67e7c7562991a4208c90007461ec14bc184a52ad6048e6bed3e8a8c2b306cee7'; // Sha256 Checksum
Docker.client = function () {
return new Dockerode({host: Docker.DOCKER_HOST, port: '2375'});
};
@ -283,7 +286,7 @@ Docker.reloadDefaultContainers = function (callback) {
return;
}
console.log('Loading new Kitematic default images.');
docker.loadImage(path.join(Util.getBinDir(), 'base-images.tar.gz'), {}, function (err) {
docker.loadImage(path.join(Util.getResourceDir(), Docker.DEFAULT_IMAGES_FILENAME), {}, function (err) {
if (err) {
callback(err);
return;

View File

@ -22,27 +22,43 @@ Installer.isUpToDate = function () {
*/
Installer.steps = [
{
run: function (callback) {
run: function (callback, progressCallback) {
var installed = VirtualBox.installed();
if (!installed) {
Util.downloadFile(Installer.baseURL + VirtualBox.INSTALLER_FILENAME, path.join(Util.getResourceDir(), VirtualBox.INSTALLER_FILENAME), VirtualBox.INSTALLER_CHECKSUM, function (err) {
if (err) {callback(err); return;}
VirtualBox.install(function (err) {
if (!VirtualBox.installed()) {
callback('VirtualBox could not be installed. The installation either failed or was cancelled. Please try closing all VirtualBox instances and try again.');
} else {
callback(err);
}
});
}, function (progress) {
progressCallback(progress);
});
} else {
// Version 4.3.12 is required.
VirtualBox.version(function (err, installedVersion) {
if (err) {
callback(err);
return;
}
if (err) {callback(err); return;}
if (Util.compareVersions(installedVersion, VirtualBox.REQUIRED_VERSION) < 0) {
// Download a newer version of Virtualbox
Util.downloadFile(Installer.baseURL + VirtualBox.INSTALLER_FILENAME, path.join(Util.getResourceDir(), VirtualBox.INSTALLER_FILENAME), VirtualBox.INSTALLER_CHECKSUM, function (err) {
if (err) {callback(err); return;}
VirtualBox.install(function (err) {
if (err) {callback(err); return;}
VirtualBox.version(function (err, installedVersion) {
if (err) {callback(err); return;}
if (Util.compareVersions(installedVersion, VirtualBox.REQUIRED_VERSION) < 0) {
callback('VirtualBox could not be installed. The installation either failed or was cancelled. Please try closing all VirtualBox instances and try again.');
} else {
callback(err);
}
});
}, function (progress) {
progressCallback(progress);
});
});
} else {
callback();
}
@ -50,8 +66,8 @@ Installer.steps = [
}
},
pastMessage: 'VirtualBox installed',
message: 'Installing VirtualBox',
futureMessage: 'Install VirtualBox if necessary'
message: 'Downloading & Installing VirtualBox',
futureMessage: 'Download & Install VirtualBox if necessary'
},
// Initialize Boot2Docker if necessary.
@ -78,9 +94,9 @@ Installer.steps = [
}
});
},
pastMessage: 'Setup the Boot2Docker VM (if required)',
message: 'Setting up the Boot2Docker VM',
futureMessage: 'Set up the Boot2Docker VM(if required)'
pastMessage: 'Setup the Kitematic VM (if required)',
message: 'Setting up the Kitematic VM',
futureMessage: 'Set up the Kitematic VM(if required)'
},
{
@ -89,9 +105,9 @@ Installer.steps = [
callback(err);
});
},
pastMessage: 'Added custom host adapter to the Boot2Docker VM',
message: 'Adding custom host adapter to the Boot2Docker VM',
futureMessage: 'Add custom host adapter to the Boot2Docker VM'
pastMessage: 'Added custom host adapter to the Kitematic VM',
message: 'Adding custom host adapter to the Kitematic VM',
futureMessage: 'Add custom host adapter to the Kitematic VM'
},
// Start the Kitematic VM
@ -111,8 +127,8 @@ Installer.steps = [
}
});
},
pastMessage: 'Started the Boot2Docker VM',
message: 'Starting the Boot2Docker VM',
pastMessage: 'Started the Kitematic VM',
message: 'Starting the Kitematic VM',
futureMessage: 'Start the Kitematic VM'
},
@ -129,12 +145,16 @@ Installer.steps = [
// Set up the default Kitematic images
{
run: function (callback) {
run: function (callback, progressCallback) {
Util.downloadFile(Installer.baseURL + Docker.DEFAULT_IMAGES_FILENAME, path.join(Util.getResourceDir(), Docker.DEFAULT_IMAGES_FILENAME), Docker.DEFAULT_IMAGES_CHECKSUM, function (err) {
Docker.reloadDefaultContainers(function (err) {
callback(err);
});
}, function (progress) {
progressCallback(progress);
});
},
pastMessage: 'Started the Boot2Docker VM',
pastMessage: 'Set up the default Kitematic images.',
message: 'Setting up the default Kitematic images...',
subMessage: '(This may take a few minutes)',
futureMessage: 'Set up the default Kitematic images'
@ -147,6 +167,7 @@ Installer.run = function (callback) {
Session.set('numberOfInstallSteps', this.steps.length);
async.eachSeries(this.steps, function (step, callback) {
console.log('Performing step ' + currentStep);
Session.set('currentInstallStepProgress', 0);
step.run(function (err) {
if (err) {
callback(err);
@ -155,6 +176,8 @@ Installer.run = function (callback) {
Session.set('currentInstallStep', currentStep);
callback();
}
}, function (progress) {
Session.set('currentInstallStepProgress', progress);
});
}, function (err) {
if (err) {

View File

@ -1,6 +1,6 @@
var path = require('path');
var fs = require('fs');
var https = require('https');
var wget = require('wget');
var nodeCrypto = require('crypto');
Util = {};
@ -95,25 +95,24 @@ Util.openTerminal = function (command) {
});
};
Util.downloadFile = function (url, filename, checksum, progressCallback, callback) {
Util.downloadFile = function (url, filename, checksum, callback, progressCallback) {
var doDownload = function () {
var file = fs.createWriteStream(filename);
https.get(url, function(res) {
var len = 0;
res.on('data', function(chunk) {
file.write(chunk);
len += chunk.length;
// percentage downloaded is as follows
var percent = (len / res.headers['content-length']) * 100;
var percent = 0;
var interval = setInterval(function () {
progressCallback(percent);
}, 250);
var download = wget.download(url, filename);
download.on('error', function (err) {
console.log(err);
clearInterval(interval);
});
res.on('end', function() {
file.close();
});
file.on('close', function() {
download.on('end', function (output) {
console.log(output);
callback();
clearInterval(interval);
});
download.on('progress', function (progress) {
percent = Math.round(progress * 100.0);
});
};
@ -122,10 +121,13 @@ Util.downloadFile = function (url, filename, checksum, progressCallback, callbac
var existingChecksum = nodeCrypto.createHash('sha256').update(fs.readFileSync(filename), 'utf8').digest('hex');
console.log(existingChecksum);
if (existingChecksum !== checksum) {
fs.unlinkSync(filename);
doDownload();
} else {
callback();
}
} else {
doDownload();
}
};

View File

@ -8,7 +8,7 @@ VirtualBox = {};
VirtualBox.REQUIRED_VERSION = '4.3.14';
VirtualBox.INCLUDED_VERSION = '4.3.14';
VirtualBox.INSTALLER_FILENAME = 'virtualbox-4.3.14.pkg';
VirtualBox.INSTALLER_CHECKSUM = '486348a5336539728ca20dcd9674cf3d37e5c7f32255d90f1edc7391b54bd5dd';
VirtualBox.INSTALLER_CHECKSUM = '486348a5336539728ca20dcd9674cf3d37e5c7f32255d90f1edc7391b54bd5dd'; // Sha256 Checksum
// Info for the hostonly interface we add to the VM.
VirtualBox.HOSTONLY_HOSTIP = '192.168.60.3';
@ -26,7 +26,7 @@ VirtualBox.exec = function (command, callback) {
VirtualBox.install = function (callback) {
// -W waits for the process to close before finishing.
exec('open -W ' + path.join(Util.getResourceDir(), this.INSTALLER_FILENAME), function (error, stdout, stderr) {
exec('open -W ' + path.join(Util.getResourceDir(), this.INSTALLER_FILENAME).replace(' ', '\\ '), function (error, stdout, stderr) {
console.log(stdout);
console.log(stderr);
if (error) {

View File

@ -9,3 +9,4 @@
@import "stylesheets/dashboard.import.less";
@import "stylesheets/setup.import.less";
@import "stylesheets/spinner.import.less";
@import "stylesheets/radial-progress.import.less";

View File

@ -0,0 +1,91 @@
.radial-progress {
@circle-size: 34px;
@circle-background: #d6dadc;
@circle-color: #3FD899;
@inset-size: 28px;
@inset-color: #fbfbfb;
@transition-length: 1s;
@shadow: 0px 1px 3px rgba(0,0,0,0.2);
@percentage-color: #3FD899;
@percentage-font-size: 11px;
@percentage-text-width: 57px;
width: @circle-size;
height: @circle-size;
background-color: @circle-background;
border-radius: 50%;
.circle {
.mask, .fill, .shadow {
width: @circle-size;
height: @circle-size;
position: absolute;
border-radius: 50%;
}
.shadow {
box-shadow: @shadow inset;
}
.mask, .fill {
-webkit-backface-visibility: hidden;
transition: -webkit-transform @transition-length;
transition: -ms-transform @transition-length;
transition: transform @transition-length;
border-radius: 50%;
}
.mask {
clip: rect(0px, @circle-size, @circle-size, @circle-size/2);
.fill {
clip: rect(0px, @circle-size/2, @circle-size, 0px);
background-color: @circle-color;
}
}
}
.inset {
width: @inset-size;
height: @inset-size;
position: absolute;
margin-left: (@circle-size - @inset-size)/2;
margin-top: (@circle-size - @inset-size)/2;
background-color: @inset-color;
border-radius: 50%;
box-shadow: @shadow;
.percentage {
width: @percentage-text-width;
position: absolute;
top: (@inset-size - @percentage-font-size) / 2;
left: (@inset-size - @percentage-text-width) / 2;
line-height: 1;
text-align: center;
color: @percentage-color;
font-weight: 800;
font-size: @percentage-font-size;
}
}
@i: 0;
@increment: 180deg / 100;
.loop (@i) when (@i <= 100) {
&[data-progress="@{i}"] {
.circle {
.mask.full, .fill {
-webkit-transform: rotate(@increment * @i);
-ms-transform: rotate(@increment * @i);
transform: rotate(@increment * @i);
}
.fill.fix {
-webkit-transform: rotate(@increment * @i * 2);
-ms-transform: rotate(@increment * @i * 2);
transform: rotate(@increment * @i * 2);
}
}
.inset .percentage:before {
content: "@{i}%"
}
}
.loop(@i + 1);
}
.loop(@i);
}

View File

@ -23,9 +23,13 @@
<span class="pull-left">
{{#if $eq this.index failedStep}}
<img src="/step_failed.png">
{{else}}
{{#if currentInstallStepProgress}}
{{> radial_progress progress=currentInstallStepProgress}}
{{else}}
{{> spinner}}
{{/if}}
{{/if}}
</span>
<div class="media-body">
{{this.message}}

View File

@ -25,6 +25,9 @@ Template.setup_install.helpers({
currentInstallStep: function () {
return Session.get('currentInstallStep');
},
currentInstallStepProgress: function () {
return Session.get('currentInstallStepProgress');
},
installComplete: function () {
return Session.get('currentInstallStep') === Installer.steps.length;
},

View File

@ -0,0 +1,17 @@
<template name="radial_progress">
<div class="radial-progress" data-progress="{{progress}}">
<div class="circle">
<div class="mask full">
<div class="fill"></div>
</div>
<div class="mask half">
<div class="fill"></div>
<div class="fill fix"></div>
</div>
<div class="shadow"></div>
</div>
<div class="inset">
<div class="percentage"></div>
</div>
</div>
</template>

View File

@ -10,6 +10,7 @@
"open": "0.0.5",
"dockerode": "2.0.3",
"tar": "0.1.20",
"ansi-to-html": "0.2.0"
"ansi-to-html": "0.2.0",
"wget": "0.0.1"
}
}