Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distribute the worker environment with job files. Closes #1528 #1532

Merged
merged 4 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions bin/deepforge
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/usr/bin/env node
const childProcess = require('child_process');
const Conda = require('../utils/conda-utils');
const {promisify} = require('util');
const fs = require('fs');
const writeFile = promisify(fs.writeFile);
const os = require('os'),
IS_WINDOWS = os.type() === 'WINDOWS_NT',
SHELL = IS_WINDOWS ? true : '/bin/bash',
Expand All @@ -14,7 +17,6 @@ var Command = require('commander').Command,
Q = require('q'),
execSync = childProcess.execSync,
path = require('path'),
fs = require('fs'),
pkgJson = require('../package.json'),
version = pkgJson.version,
exists = require('exists-file'),
Expand Down Expand Up @@ -413,7 +415,8 @@ program
const extensionData = extender.getExtensionsConfig();
const libraries = Object.values(extensionData.Library);
const dirs = libraries.map(lib => lib.project.root);
const name = typeof cmd.name === 'string' ? cmd.name : 'deepforge';
const isUpdatingDefault = typeof cmd.name !== 'string';
const name = isUpdatingDefault ? 'deepforge' : cmd.name;

try {
if (cmd.server) {
Expand All @@ -422,6 +425,9 @@ program
}
if (cmd.worker) {
await createEnvFromDirs(name, dirs, 'worker', cmd.force);
if (isUpdatingDefault) {
await exportWorkerEnvForJobs(name);
}
}
} catch (errOrExitCode) {
const msg = '\n\nUnable to create environment.';
Expand Down Expand Up @@ -454,6 +460,13 @@ function getCondaEnvFiles(dirs, type) {
return envFiles;
}

async function exportWorkerEnvForJobs(name) {
const contents = await Conda.export(name);
const filename = path.join(__dirname, '..', 'src', 'plugins', 'GenerateJob',
'templates', 'environment.worker.yml');
await writeFile(filename, contents);
}

// user-management
program.command('users', 'Manage deepforge users.');

Expand Down
1 change: 1 addition & 0 deletions src/plugins/GenerateJob/GenerateJob.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ define([
if (condaEnv) {
files.addFile('environment.yml', condaEnv);
}
files.addFile('environment.worker.yml', Templates.WORKER_ENV);

const filename = GenerateJob.toSnakeCase(content.name);
files.addFile(`operations/${filename}.py`, content.code);
Expand Down
Empty file.
3 changes: 3 additions & 0 deletions src/plugins/GenerateJob/templates/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ define([
'text!./serialize.ejs',
'text!./deserialize.ejs',
'text!./utils.build.js',
'text!./environment.worker.yml',
], function(
START,
RUN_DEBUG,
Expand All @@ -19,6 +20,7 @@ define([
SERIALIZE,
DESERIALIZE,
UTILS,
WORKER_ENV,
) {

return {
Expand All @@ -31,5 +33,6 @@ define([
DEEPFORGE_INIT,
DESERIALIZE,
UTILS,
WORKER_ENV,
};
});
36 changes: 31 additions & 5 deletions src/plugins/GenerateJob/templates/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ requirejs([
cleanup();
});

const envFile = path.join(__dirname, 'environment.yml');
const envName = await updateCondaEnvironment(envFile);
const envName = await prepareCondaEnvironment(__dirname);
const workerCacheDir = await prepareCache(process.env.DEEPFORGE_WORKER_CACHE);
await prepareInputsOutputs();
try {
Expand Down Expand Up @@ -106,6 +105,34 @@ requirejs([
});
}

async function prepareCondaEnvironment(jobDir) {
if (!await hasConda()) {
return null;
}
const envs = await getCondaEnvironments();
if (!envs.includes('deepforge')) {
await createBaseEnvironment(jobDir);
}
const jobEnvFile = path.join(jobDir, 'environment.yml');
await updateCondaEnvironment(jobEnvFile);
const envName = await updateCondaEnvironment(jobEnvFile);
return envName;
}

async function hasConda() {
try {
await conda('-V');
return true;
} catch (err) {
return false;
}
}

async function createBaseEnvironment(jobDir) {
const envFile = path.join(jobDir, 'environment.worker.yml');
await conda(`create -n ${name} -f ${envFile}`);
}

function getJobStartCommand(envName) {
if (envName) {
return [
Expand Down Expand Up @@ -187,7 +214,7 @@ requirejs([
if (exists) {
let name;
try {
name = await getCondaEnvironmentName();
name = await getCondaEnvironmentName('deepforge');
await conda(`create -n ${name} --clone deepforge`);
await conda(`env update -n ${name} --file ${filepath}`);
return name;
Expand All @@ -198,8 +225,7 @@ requirejs([
}
}

async function getCondaEnvironmentName() {
const basename = 'deepforge';
async function getCondaEnvironmentName(basename) {
const envs = await getCondaEnvironments();
let newEnvName = basename;
let counter = Math.floor(1000*Math.random());
Expand Down