diff --git a/meteor/client/lib/boot2docker.js b/meteor/client/lib/boot2docker.js deleted file mode 100644 index 9b4b34a512..0000000000 --- a/meteor/client/lib/boot2docker.js +++ /dev/null @@ -1,283 +0,0 @@ -var exec = require('exec'); -var path = require('path'); -var fs = require('fs'); -var path = require('path'); -var async = require('async'); -var packagejson = JSON.parse(fs.readFileSync(path.join(process.env.DIR, 'package.json'), 'utf8')); - - -Boot2Docker = {}; -Boot2Docker.VERSION = packagejson['boot2docker-version']; - -Boot2Docker.command = function () { - return path.join(Util.getBinDir(), 'boot2docker-' + Boot2Docker.VERSION); -}; - -Boot2Docker.exec = function (command, callback) { - var cmd = [Boot2Docker.command()]; - cmd.push.apply(cmd, command); - exec(cmd, function(stderr, stdout, code) { - callback(stderr, stdout, code); - }); -}; - -Boot2Docker.exists = function (callback) { - this.exec(['info'], function (stderr, stdout, code) { - if (code) { - callback(null, false); - } else { - callback(null, true); - } - }); -}; - -Boot2Docker.stop = function (callback) { - this.exec(['stop'], function (stderr, stdout, code) { - if (code) { - callback(stderr); - } else { - callback(); - } - }); -}; - -Boot2Docker.erase = function (callback) { - var VMFileLocation = path.join(Util.getHomePath(), 'VirtualBox\\ VMs/boot2docker-vm'); - exec(['rm', '-rf', VMFileLocation], function (stderr) { - callback(stderr); - }); -}; - -Boot2Docker.upgrade = function (callback) { - var self = this; - self.stop(function (stderr, stdout, code) { - if (code) {callback(stderr); return;} - self.exec(['upgrade'], function (stderr, stdout, code) { - if (code) { - callback(stderr); - } else { - callback(); - } - }); - }); -}; - -Boot2Docker.ip = function (callback) { - this.exec(['ip'], function (stderr, stdout, code) { - if (code) { - callback(stderr, null); - } else { - callback(null, stdout); - } - }); -}; - -Boot2Docker.init = function (callback) { - this.exec(['init'], function (stderr, stdout, code) { - if (code) { - callback(stderr); - } else { - callback(); - } - }); -}; - -Boot2Docker.start = function (callback) { - var self = this; - self.exists(function (err, exists) { - if (!exists) { - callback('Cannot start if the boot2docker VM doesn\'t exist'); - return; - } - self.exec(['start'], function (stderr, stdout, code) { - if (code) { - callback(stderr); - } else { - callback(); - } - }); - }); -}; - -Boot2Docker.state = function (callback) { - this.exec(['info'], function (stderr, stdout, code) { - if (code) { callback(stderr, null); return; } - try { - var info = JSON.parse(stdout); - callback(null, info.State); - } catch (e) { - callback(e, null); - } - }); -}; - -Boot2Docker.diskUsage = function (callback) { - this.exec(['ssh', 'df'], function (stderr, stdout, code) { - if (code) { - callback(stderr, null); - return; - } - try { - var lines = stdout.split('\n'); - var dataline = _.find(lines, function (line) { - return line.indexOf('/dev/sda1') !== -1; - }); - var tokens = dataline.split(' '); - tokens = tokens.filter(function (token) { - return token !== ''; - }); - var usedGb = parseInt(tokens[2], 10) / 1000000; - var totalGb = parseInt(tokens[3], 10) / 1000000; - var percent = parseInt(tokens[4].replace('%', ''), 10); - callback(null, { - used_gb: usedGb.toFixed(2), - total_gb: totalGb.toFixed(2), - percent: percent - }); - } catch (error) { - callback(error, null); - } - }); -}; - -Boot2Docker.memoryUsage = function (callback) { - this.exec(['ssh', 'free -m'], function (stderr, stdout, code) { - if (code) { - callback(stderr, null); - return; - } - try { - var lines = stdout.split('\n'); - var dataline = _.find(lines, function (line) { - return line.indexOf('-/+ buffers') !== -1; - }); - var tokens = dataline.split(' '); - tokens = tokens.filter(function(token) { - return token !== ''; - }); - var usedGb = parseInt(tokens[2], 10) / 1000; - var freeGb = parseInt(tokens[3], 10) / 1000; - var totalGb = usedGb + freeGb; - var percent = Math.round(usedGb / totalGb * 100); - callback(null, { - used_gb: usedGb.toFixed(2), - total_gb: totalGb.toFixed(2), - free_gb: freeGb.toFixed(2), - percent: percent - }); - } catch (error) { - callback(error, null); - } - }); -}; - -Boot2Docker.stats = function (callback) { - var self = this; - self.state(function (err, state) { - if (err) { callback(err, null); return; } - if (state === 'poweroff') { - callback(null, {state: state}); - return; - } - self.memoryUsage(function (err, mem) { - if (err) { - callback(null, {state: state}); - return; - } - self.diskUsage(function (err, disk) { - if (err) { - callback(null, {state: state, memory: mem}); - return; - } - callback(null, { - state: state, - memory: mem, - disk: disk - }); - }); - }); - }); -}; - -Boot2Docker.sshKeyExists = function () { - return fs.existsSync(path.join(Util.getHomePath(), '.ssh', 'id_boot2docker')); -}; - -Boot2Docker.version = function (callback) { - this.exec(['version'], function (stderr, stdout, code) { - if (code) { - callback(stderr); - return; - } - var match = stdout.match(/Client version: v(\d\.\d\.\d)/); - if (!match || match.length < 2) { - callback('Could not parse the boot2docker cli version.'); - } else { - callback(null, match[1]); - } - }); -}; - -Boot2Docker.check = function (callback) { - var self = this; - self.exists(function (err, exists) { - if (err) { - callback(err); - return; - } else { - self.state(function (err, state) { - if (state !== 'running') { - callback('boot2docker not running'); - } else { - callback(); - } - }); - } - }); -}; - -Boot2Docker.vmUpToDate = function (callback) { - fs.readFile(path.join(Util.getHomePath(), '.boot2docker', 'boot2docker.iso'), 'utf8', function (err, data) { - if (err) { - callback(err); return; - } - var match = data.match(/Boot2Docker-v(\d+\.\d+\.\d+)/); - if (!match) { - callback('Could not parse boot2docker iso version'); - return; - } - callback (null, Util.compareVersions(match[1], Boot2Docker.VERSION) >= 0); - }); -}; - -Boot2Docker.status = function (callback) { - this.exec(['status'], function (stderr, stdout, code) { - if (code) {callback(stderr); return;} - callback(null, stdout.trim()); - }); -}; - -Boot2Docker.portAvailable = function (port, protocol, callback) { - this.exec(['ssh', 'netstat -lntu | grep LISTEN | grep ' + protocol + ' | grep -c ":::' + port + '\\s"'], function (stdout, stderr, code) { - if (stderr.trim() === '0') { - callback(true); - } else { - callback(false); - } - }); -}; - -Boot2Docker.waitWhileStatus = function (status, callback) { - var current = status; - async.whilst(function () { - return current === status; - }, function (innerCallback) { - Boot2Docker.status(function (err, vmStatus) { - if (err) {innerCallback(err); return;} - current = vmStatus.trim(); - innerCallback(); - }); - }, function (err) { - callback(err); - }); -}; diff --git a/meteor/client/lib/imageutil.js b/meteor/client/lib/imageutil.js deleted file mode 100644 index 84d7a9e4ba..0000000000 --- a/meteor/client/lib/imageutil.js +++ /dev/null @@ -1,324 +0,0 @@ -var Convert = require('ansi-to-html'); -var convert = new Convert(); -var exec = require('exec'); -var path = require('path'); -var fs = require('fs'); -var async = require('async'); - -ImageUtil = {}; - -var getFromImage = function (dockerfile) { - var patternString = "(FROM)(.*)"; - var regex = new RegExp(patternString, "g"); - var fromInstruction = dockerfile.match(regex); - if (fromInstruction && fromInstruction.length > 0) { - return fromInstruction[0].replace('FROM', '').trim(); - } else { - return null; - } -}; - -var getImageJSON = function (directory) { - var jsonPath = path.join(directory, 'image.json'); - if (fs.existsSync(jsonPath)) { - var data = fs.readFileSync(jsonPath, 'utf8'); - return JSON.parse(data); - } else { - return null; - } -}; - -ImageUtil.getMetaData = function (directory) { - var ret = { - name: _.last(directory.split(path.sep)).replace(/\s+/g, '-').toLowerCase(), - version: 'latest' - }; - return ret; -}; - -ImageUtil.rebuildHelper = function (image, callback) { - var imageMetaData = ImageUtil.getMetaData(image.path); - if (imageMetaData.logo) { - Images.update(image._id, { - $set: { - logoPath: path.join(image.path, imageMetaData.logo) - } - }); - } else { - Images.update(image._id, { - $set: { - logoPath: null - } - }); - } - Images.update(image._id, { - $set: { - status: 'BUILDING', - meta: imageMetaData - } - }); - image = Images.findOne(image._id); - ImageUtil.pull(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), image._id, function (err) { - if (err) { callback(err, null); return; } - ImageUtil.build(image, function (err) { - if (err) { console.error(err); } - callback(null, null); - }); - }); -}; - -ImageUtil.rebuild = function (imageId) { - var image = Images.findOne(imageId); - if (!image) { - throw new Meteor.Error(403, "No image found with this ID."); - } - var apps = Apps.find({imageId: imageId}).fetch(); - if (apps.length > 0) { - _.each(apps, function (app) { - console.log('Updating app: ' + app.name); - if (app.docker) { - Docker.removeContainer(app.docker.Id, function (err) { - if (err) { console.error(err); } - }); - } - Apps.update(app._id, { - $set: { - 'docker.Id': null, - status: 'STARTING', - logs: [] - } - }); - }); - ImageUtil.rebuildHelper(image, function (err) { - if (err) { console.error(err); } - _.each(apps, function (app) { - app = Apps.findOne(app._id); - AppUtil.run(app, function (err) { - if (err) { console.error(err); } - }); - }); - }); - } else { - ImageUtil.rebuildHelper(image, function (err) { - if (err) { console.error(err); } - }); - } -}; - -ImageUtil.pull = function (dockerfile, imageId, callback) { - var fromImage = getFromImage(dockerfile); - console.log('From image: ' + fromImage); - var installedImage = null; - Docker.getImageData(imageId, function (err, data) { - installedImage = data; - if (fromImage && !installedImage) { - Images.update(imageId, { - $set: { - buildLogs: [] - } - }); - var logs = []; - Docker.client().pull(fromImage, function (err, response) { - if (err) { callback(err); return; } - response.setEncoding('utf8'); - response.on('data', function (data) { - try { - var logData = JSON.parse(data); - var logDisplay = ''; - if (logData.id) { - logDisplay += logData.id + ' | '; - } - logDisplay += logData.status; - if (logData.progressDetail && logData.progressDetail.current && logData.progressDetail.total) { - logDisplay += ' - ' + Math.round(logData.progressDetail.current / logData.progressDetail.total * 100) + '%'; - } - logs.push(logDisplay); - Images.update(imageId, { - $set: { - buildLogs: logs - } - }); - } catch (e) { - console.error(e); - } - }); - response.on('end', function () { - console.log('Finished pulling image: ' + fromImage); - callback(null); - }); - }); - } else { - callback(null); - } - }); -}; - -ImageUtil.build = function (image, callback) { - Util.createTarFile(image.path, path.join(Util.KITE_TAR_PATH, image._id + '.tar'), function (err, tarFilePath) { - if (err) { console.error(err); } - Images.update(image._id, { - $set: { - buildLogs: [] - } - }); - Docker.client().buildImage(tarFilePath, {forcerm: true, t: image.tags}, function (err, response) { - if (err) { callback(err); return; } - console.log('Building Docker image...'); - response.setEncoding('utf8'); - response.on('data', function (data) { - try { - var line = JSON.parse(data).stream; - Images.update(image._id, { - $push: { - buildLogs: convert.toHtml(line) - } - }); - } catch (e) { - // Ignore misc conversion errors - } - }); - response.on('end', function () { - console.log('Finished building Docker image.'); - try { - fs.unlinkSync(tarFilePath); - console.log('Cleaned up tar file.'); - } catch (e) { - console.error(e); - } - var imageData = null; - Docker.getImageData(image.tags, function (err, data) { - if (err) { - console.error(err); - Images.update(image._id, { - $set: { - status: 'ERROR' - } - }); - } else { - imageData = data; - Images.update(image._id, { - $set: { - docker: imageData, - status: 'READY' - } - }); - var oldImageId = null; - if (image.docker && image.docker.Id) { - oldImageId = image.docker.Id; - } - if (oldImageId && imageData && oldImageId !== imageData.Id) { - Docker.removeImage(oldImageId, function (err) { - if (err) { console.error(err); } - }); - } - } - callback(null); - }); - }); - }); - }); -}; - -ImageUtil.remove = function (imageId) { - var image = Images.findOne(imageId); - Images.remove({_id: image._id}); - if (image.docker) { - Docker.removeImage(image.docker.Id, function (err) { - if (err) { console.error(err); } - }); - } -}; - -ImageUtil.sync = function (callback) { - Docker.listImages({all: 0}, function (err, dockerImages) { - if (err) { - callback(err); - return; - } - var images = Images.find({}).fetch(); - - // Delete missing GUI images - var kitematicIds = _.map(images, function (image) { - if (image.docker && image.docker.Id) { - return image.docker.Id; - } - }); - var daemonIds = _.map(dockerImages, function (image) { - return image.Id; - }); - var diffImages = _.difference(kitematicIds, daemonIds); - _.each(diffImages, function (imageId) { - var image = Images.findOne({'docker.Id': imageId}); - if (image && image.status !== 'BUILDING') { - Images.remove(image._id); - } - }); - - // Add missing Daemon images - var diffDockerImages = _.reject(dockerImages, function (image) { - return _.contains(kitematicIds, image.Id); - }); - _.each(diffDockerImages, function (image) { - if (!image.RepoTags || !image.RepoTags || image.RepoTags[0] === ':' || !image.Config || _.isEmpty(image.Config.ExposedPorts)) { - return; - } - - var meta = {}; - var repoTag = _.first(image.RepoTags); - var repoTagTokens = repoTag.split(':'); - var name = repoTagTokens[0]; - var version = repoTagTokens[1]; - meta = { - name: name, - version: version - }; - var buildingImage = _.find(images, function (image) { - return image.status === 'BUILDING' && image.meta.name === name && image.meta.version === version; - }); - if (!buildingImage) { - var imageObj = { - status: 'READY', - docker: image, - buildLogs: [], - createdAt: new Date(), - tags: image.RepoTags.sort(), - meta: meta - }; - Images.insert(imageObj); - } - }); - - async.each(images, function (image, callback) { - var image = Images.findOne(image._id); - if (image && image.docker && image.docker.Id) { - var duplicateImages = Images.find({'docker.Id': image.docker.Id, _id: {$ne: image._id}}).fetch(); - _.each(duplicateImages, function (duplicateImage) { - Images.remove(duplicateImage._id); - }); - var imageData = _.find(dockerImages, function (dockerImage) { - return dockerImage.Id === image.docker.Id; - }); - if (imageData && imageData.RepoTags) { - Images.update(image._id, { - $set: { - tags: imageData.RepoTags.sort() - } - }); - } - Docker.getImageData(image.docker.Id, function (err, data) { - if (err) {callback(err); return;} - Images.update(image._id, { - $set: { - docker: data - } - }); - callback(); - }); - } else { - callback(); - } - }, function (err) { - callback(err); - }); - }); -}; diff --git a/meteor/client/views/dashboard/components/modal-create-image.js b/meteor/client/views/dashboard/components/modal-create-image.js deleted file mode 100755 index 6180063083..0000000000 --- a/meteor/client/views/dashboard/components/modal-create-image.js +++ /dev/null @@ -1,84 +0,0 @@ -var path = require('path'); -var fs = require('fs'); -var remote = require('remote'); -var dialog = remote.require('dialog'); - -Template.modalCreateImage.rendered = function () { - $('#modal-create-image').bind('hidden.bs.modal', function () { - Router.go('dashboard_images'); - }); -}; - -Template.modalCreateImage.events({ - 'click #btn-pick-directory': function () { - dialog.showOpenDialog({properties: ['openDirectory']}, function (filenames) { - if (!filenames) { - return; - } - var directory = filenames[0]; - if (directory) { - $('#picked-directory').html('' + directory + ''); - if (!Util.hasDockerfile(directory)) { - $('#picked-directory-error').html('Only directories with Dockerfiles are supported now.'); - $('#btn-create-image').attr('disabled', 'disabled'); - } else { - Session.set('createImagePickedDirectory', directory); - $('#btn-create-image').removeAttr('disabled'); - } - } else { - $('#picked-directory').html(''); - $('#btn-create-image').attr('disabled', 'disabled'); - } - }); - }, - 'click #btn-create-image': function () { - var directory = Session.get('createImagePickedDirectory'); - if (!directory) { - return; - } - $('#directory-picker').val(''); - $('#picked-directory-error').html(''); - $('#picked-directory').html(''); - $('#btn-create-image').attr('disabled', 'disabled'); - var imageObj = { - status: 'BUILDING', - path: directory, - buildLogs: [], - createdAt: new Date() - }; - var imageMetaData = ImageUtil.getMetaData(directory); - imageObj.meta = imageMetaData; - - var count = 2; - imageObj.tags = [imageMetaData.name + ':' + imageMetaData.version]; - while (Images.findOne({tags: imageObj.tags})) { - imageObj.meta = { - name: imageMetaData.name + '-' + count, - version: imageMetaData.version - }; - imageObj.tags = [imageMetaData.name + '-' + count + ':' + imageMetaData.version]; - count++; - } - var imageId = Images.insert(imageObj); - - $('#modal-create-image').modal('hide'); - $('#modal-create-image').on('hidden.bs.modal', function () { - Router.go('dashboard_images_logs', {id: imageId}); - }); - - if (imageObj.meta.logo) { - Images.update(imageId, { - $set: { - logoPath: path.join(directory, imageObj.meta.logo) - } - }); - } - var image = Images.findOne(imageId); - ImageUtil.pull(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), imageId, function (err) { - if (err) { throw err; } - ImageUtil.build(image, function (err) { - if (err) { console.error(err); } - }); - }); - } -});