Skip to content
Snippets Groups Projects
Commit d4dd1d67 authored by Sastre, Alfonso (asastre)'s avatar Sastre, Alfonso (asastre)
Browse files

add support to jupyter notebooks

parent 2a072496
Branches
No related tags found
No related merge requests found
......@@ -9,13 +9,21 @@ function main() {
var iarg = 2
var args = process.argv
var cmds = []
const usage = `node ${args[1]} [-h|--help] [webserver|watcher]`
var imageType = "beaker"
const usage = `node ${args[1]} [-h|--help] [--image-type [beaker|jupyter]] [webserver|watcher]`
while (iarg < args.length) {
var arg = args[iarg]
iarg += 1
if (arg == '-h' || arg == '--help') {
console.log(usage)
return;
} else if (arg == "--image-type") {
iarg += 1
if (iarg > args.length) {
console.log(`Expected image type after --image-type, ${usage}`)
return;
}
imageType = args[iarg]
} else if (arg == "webserver") {
cmds.push("webserver")
} else if (arg == "apiserver") {
......@@ -26,6 +34,7 @@ function main() {
throw new Error(`unknown command line argument '${arg}.\n${usage}'`)
}
}
config.k8component['imageType'] = imageType
if (cmds.includes("watcher")) {
const fileWatcher = require('./app/filesWatcher')(env, config, models);
}
......
......@@ -30,11 +30,11 @@ ProxyRouter.prototype.kubernetesServiceLookup = function(req, res, userID, isWeb
function createService(userID) {
console.log("trying to create service for the user: " + userID);
self.set_user_state(userID,self.stateEnum.STARTING);
k8.ns(config.k8component.namespace).service.get('beaker-svc-'+userID,function(err, result) {
k8.ns(config.k8component.namespace).service.get(config.k8component.imageType + '-svc-'+userID,function(err, result) {
if(err)
k8.ns(config.k8component.namespace).service.post({ body: k8component('service', userID)}, function(err, result){
if(err){
console.log("#ERROR# Can't start service for the user: " + userID);
console.log(`#ERROR# Can't start service ${config.k8component.imageType} for the user: ${userID}`);
console.log(stringify(err, null, 2));
}
else
......@@ -76,7 +76,7 @@ ProxyRouter.prototype.kubernetesServiceLookup = function(req, res, userID, isWeb
function createReplicationController(userID) {
console.log("trying to create replication controller for user: " + userID);
// createUserDir(userID); //Kubernetes can handle it, but the permissions can be problamatic
k8.ns(config.k8component.namespace).replicationcontrollers.get('beaker-rc-'+userID, function(err, result) {
k8.ns(config.k8component.namespace).replicationcontrollers.get(config.k8component.imageType + '-rc-' + userID, function(err, result) {
if(err)
k8.ns(config.k8component.namespace).replicationcontrollers.post({ body: k8component('replicationController', userID)}, function(err, result){
if(err){
......@@ -94,7 +94,7 @@ ProxyRouter.prototype.kubernetesServiceLookup = function(req, res, userID, isWeb
function getServicePort(userID) {
console.log("trying to get service part for user: " + userID);
self.set_user_state(userID,self.stateEnum.STARTED);
k8.ns(config.k8component.namespace).service.get('beaker-svc-'+userID,function(err, result) {
k8.ns(config.k8component.namespace).service.get(config.k8component.imageType + '-svc-' + userID,function(err, result) {
if(err){
console.log("#ERROR# Can't find service for the user: " + userID);
console.log(stringify(err, null, 2));
......@@ -150,52 +150,64 @@ ProxyRouter.prototype.lookup = function(req, res, userID, isWebsocket, path, nex
console.log(`Resolved using local cache to ${stringify(target)}`)
next(target);
}
else {
//Check if the path has been defined in the redis client otherwise get it from kubernetes
self.client.hget(userID, path, function(err, data) {
if (data) {
var target = JSON.parse(data);
console.log(`Resolved using redis cache to ${stringify(target)}`)
// Set cache and expiration
if (self.cache[userID] === undefined){
self.cache[userID] = { path: target }
}
else{
self.cache[userID][path] = target;
}
self.expire_route(userID, self.cache_ttl);
http.request({method:'HEAD',host:target.host,port:target.port,path: '/'}, (r) => {
if(r.statusCode >= 200 && r.statusCode < 400 ){
console.log("Forwarding to the target!");
self.set_user_state(userID,self.stateEnum.AVAILABLE);
next(target);
} else {
self.expire_route(userID, 0);
self.push_user_error(userID, err.message);
self.clear_user_state(userID);
self.client.hdel(userID, path, () =>{});
console.log("Sending message back to the browser!")
if (!isWebsocket) {
res.send(reloadMsg);
else {
if (config.specialUsers[userID]) {
target = config.specialUsers[userID]
// Set cache and expiration
if (self.cache[userID] === undefined){
self.cache[userID] = { path: target }
} else {
self.cache[userID][path] = target;
}
}
}).setTimeout(1000).on('error', (err) => {
self.expire_route(userID, 0);
self.push_user_error(userID, err.message);
self.clear_user_state(userID);
self.client.hdel(userID, path, () =>{});
console.log("From error! Sending message back to the browser!")
if (!isWebsocket) {
res.send(reloadMsg);
}
}).end();
console.log(`Forwarding special user ${userID} to ${stringify(target)}!`);
next(target);
} else {
//Check if the path has been defined in the redis client otherwise get it from kubernetes
self.client.hget(userID, path, function(err, data) {
if (data) {
var target = JSON.parse(data);
console.log(`Resolved using redis cache to ${stringify(target)}`)
// Set cache and expiration
if (self.cache[userID] === undefined){
self.cache[userID] = { path: target }
}
else{
self.cache[userID][path] = target;
}
self.expire_route(userID, self.cache_ttl);
http.request({method:'HEAD',host:target.host,port:target.port,path: '/'}, (r) => {
if(r.statusCode >= 200 && r.statusCode < 400 ){
console.log("Forwarding to the target!");
self.set_user_state(userID,self.stateEnum.AVAILABLE);
next(target);
} else {
self.expire_route(userID, 0);
self.push_user_error(userID, err.message);
self.clear_user_state(userID);
self.client.hdel(userID, path, () =>{});
console.log("Sending message back to the browser!")
if (!isWebsocket) {
res.send(reloadMsg);
}
}
}).setTimeout(1000).on('error', (err) => {
self.expire_route(userID, 0);
self.push_user_error(userID, err.message);
self.clear_user_state(userID);
self.client.hdel(userID, path, () =>{});
console.log("From error! Sending message back to the browser!")
if (!isWebsocket) {
res.send(reloadMsg);
}
}).end();
} else { //Else of path check in redis client
//Lookup target from Kubernetes
console.log(`Cant resolve using redis cache!!`)
self.kubernetesServiceLookup(req, res, userID, isWebsocket, path, next);
}
});
} else { //Else of path check in redis client
//Lookup target from Kubernetes
console.log(`Cant resolve using redis cache!!`)
self.kubernetesServiceLookup(req, res, userID, isWebsocket, path, next);
}
});
}
}
};
......
......@@ -13,27 +13,31 @@ var createNamespaceConfig = function(user) {
};
var createServiceConfig = function(user) {
var imageType = config.k8component.imageType
var imageInfo = config.k8component.images[imageType]
if (!imageInfo)
throw new Error(`could not fing image ${imageType} in ${JSON.stringify(imageInfo)}`)
const service= {
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "beaker-svc-"+user,
"name": imageType + "-svc-"+user,
"labels": {
"user": user,
"app": "beaker"
"app": imageType
}
},
"spec":{
"type": "NodePort",
"ports":[{
"port": 8801,
"name": "beaker-port",
"targetPort": 8801,
"name": imageType + "-port",
"targetPort": imageInfo.port,
"protocol": "TCP"
}],
"selector":{
"user": user,
"app": "beaker"
"app": imageType
}
}
};
......@@ -41,37 +45,41 @@ var createServiceConfig = function(user) {
};
var createRcControllerConfig = function(user) {
var imageType = config.k8component.imageType
var imageInfo = config.k8component.images[imageType]
if (!imageInfo)
throw new Error(`could not fing image ${imageType} in ${JSON.stringify(imageInfo)}`)
const rcController = {
"apiVersion": "v1",
"kind": "ReplicationController",
"metadata": {
"name": "beaker-rc-"+user,
"name": imageType + "-rc-" + user,
"labels": {
"user": user,
"app": "beaker"
"app": imageType
},
},
"spec": {
"replicas": 1,
"selector":{
"user": user,
"app": "beaker"
"app": imageType
},
"template": {
"metadata": {
"labels": {
"user":user,
"app": "beaker"
"app": imageType
}
},
"spec": {
"containers": [
{
"image": config.k8component.image,
"name": "beaker",
"image": imageInfo.image,
"name": imageType,
"ports": [
{
"containerPort": 8801,
"containerPort": imageInfo.port,
"name": "main-port",
"protocol": "TCP"
}
......@@ -94,7 +102,7 @@ var createRcControllerConfig = function(user) {
"readOnly": true
},
{
"mountPath": "/home/beaker/notebooks",
"mountPath": imageInfo.homePath+"/notebooks",
"name": "notebooks-data-volume",
"readOnly": true
},
......
......@@ -8,11 +8,16 @@ docker run --name filemanager-mongo -p 27017:27017 --restart=unless-stopped -d m
docker run -p 80:80 --name=node-manager --env PORT=80 --env NODE_ENV=production -v $PWD:/usr/src/app -w /usr/src/app -d node:6 bash -c "npm install && npm start watcher webserver apiserver"
#to use the jupyter image
docker run -p 80:80 --name=node-manager --env PORT=80 --env NODE_ENV=production -v $PWD:/usr/src/app -w /usr/src/app -d node:6 bash -c "npm install && npm start --image-type jupyter watcher webserver apiserver"
#On labdev-nomad ; To be run from the folder where nodejs code is present
docker run -p 8801:443 --restart=unless-stopped --name=beaker-manager-https --env PORT=443 --env NODE_ENV=labdev -v /u/ankar/certi:/certs:ro -v $PWD:/usr/src/app -w /usr/src/app -v /nomad/nomadlab/beaker-notebooks/user-data:/nomad/nomadlab/beaker-notebooks/user-data -d node:6 bash -c "npm install && npm start webserver"
docker run -p 880:443 --restart=unless-stopped --name=beaker-manager-api --env PORT=443 --env NODE_ENV=labdev -v /u/ankar/certi:/certs:ro -v $PWD:/usr/src/app -w /usr/src/app -v /nomad/nomadlab/beaker-notebooks/user-data:/nomad/nomadlab/beaker-notebooks/user-data -d node:6 bash -c "npm install && npm start apiserver"
docker run --restart=unless-stopped --name=beaker-manager-watcher --env PORT=443 --env NODE_ENV=labdev -v /u/ankar/certi:/certs:ro -v $PWD:/usr/src/app -w /usr/src/app -v /nomad/nomadlab/beaker-notebooks/user-data:/nomad/nomadlab/beaker-notebooks/user-data -d node:6 bash -c "npm install && npm start watcher"
# jupyter:
docker run -p 8807:443 --restart=unless-stopped --name=jupyter-manager-https --env PORT=443 --env NODE_ENV=labdev -v /u/ankar/certi:/certs:ro -v $PWD:/usr/src/app -w /usr/src/app -v /nomad/nomadlab/beaker-notebooks/user-data:/nomad/nomadlab/beaker-notebooks/user-data -d node:6 bash -c "npm install && npm start --image-type jupyter webserver"
#On analytics-toolkit or labtest-nomad; To be run from the folder where nodejs code is present
......
module.exports = {
development: {
specialUsers: {
sastre: { host: "172.17.0.21", port: 8801}
},
app: {
name: 'Container per user manager',
port: process.env.PORT || 80,
......@@ -40,7 +43,20 @@ module.exports = {
},
k8component: {
namespace: 'default',
image: 'labdev-nomad.esc.rzg.mpg.de:5000/nomadlab/notebook:v1.8.0-145-g491616a8-dirty'
images: {
beaker: {
image: 'labdev-nomad.esc.rzg.mpg.de:5000/nomadlab/notebook:v1.8.0-145-g491616a8-dirty',
port: 8801,
prefix: '/beaker',
homePath: '/home/beaker'
},
jupyter: {
image: 'labdev-nomad.esc.rzg.mpg.de:5000/jupyter-notebook',
port: 8888,
prefix: '/jupyter',
homePath: '/home/beaker'
}
}
},
userInfo: {
basePathToWatch: process.env.HOME + '/nomad/user-data',
......@@ -52,6 +68,9 @@ module.exports = {
}
},
labdev: {
specialUsers: {
sastre: { host: "172.17.0.21", port: 8801}
},
app: {
name: 'User container manager',
port: process.env.PORT || 443,
......@@ -92,7 +111,20 @@ module.exports = {
},
k8component: {
namespace: 'default',
image: 'labdev-nomad.esc.rzg.mpg.de:5000/nomadlab/notebook:v1.8.0-145-g491616a8-dirty'
images: {
beaker: {
image: 'labdev-nomad.esc.rzg.mpg.de:5000/nomadlab/notebook:v1.8.0-145-g491616a8-dirty',
port: 8801,
prefix: '/beaker',
homePath: '/home/beaker'
},
jupyter: {
image: 'labdev-nomad.esc.rzg.mpg.de:5000/jupyter-notebook',
port: 8888,
prefix: '/jupyter',
homePath: '/home/beaker'
}
}
},
userInfo: {
basePathToWatch: '/nomad/nomadlab/beaker-notebooks/user-data',
......@@ -104,6 +136,7 @@ module.exports = {
}
},
analyticsToolkit: {
specialUsers: {},
app: {
name: 'User container manager',
port: process.env.PORT || 443,
......@@ -147,7 +180,20 @@ module.exports = {
},
k8component: {
namespace: 'default',
image: 'labdev-nomad.esc.rzg.mpg.de:5000/nomadlab/notebook:v1.8.0-145-g491616a8-dirty'
images: {
beaker: {
image: 'labdev-nomad.esc.rzg.mpg.de:5000/nomadlab/notebook:v1.8.0-145-g491616a8-dirty',
port: 8801,
prefix: '/beaker',
homePath: '/home/beaker'
},
jupyter: {
image: 'labdev-nomad.esc.rzg.mpg.de:5000/jupyter-notebook',
port: 8888,
prefix: '/jupyter',
homePath: '/home/beaker'
}
}
},
userInfo: {
basePathToWatch: '/nomad/nomadlab/beaker-notebooks/user-data',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment