Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • rc/bc_uab_jupyter
  • louistw/bc_uab_jupyter
2 results
Show changes
Commits on Source (39)
......@@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## Unreleased
## [Unreleased]
### Changed
- Increased verbosity of output to make debugging easier.
- Does not launch template script as login shell anymore to speed up load time.
### Fixed
- Fix job not ending if forked processes still running.
### Removed
- Removed support for Anaconda Notebook extensions.
## [1.0.1] - 2018-01-03
### Changed
- Updated date in `LICENSE.txt`.
### Fixed
- Remove ERB from YAML comments to avoid possible crash.
[#4](https://github.com/OSC/bc_example_jupyter/issues/4)
## 1.0.0 - 2017-11-15
### Added
- Initial release!
[Unreleased]: https://github.com/OSC/bc_example_jupyter/compare/v1.0.1...HEAD
[1.0.1]: https://github.com/OSC/bc_example_jupyter/compare/v1.0.0...v1.0.1
Copyright (c) 2016-2017 Ohio Supercomputer Center
Copyright (c) 2016-2018 Ohio Supercomputer Center
MIT License
......
......@@ -19,12 +19,8 @@ OnDemand node):
**Optional** software:
- [Anaconda](https://www.continuum.io/anaconda-overview) 4.3.13+ and its
[Jupyter Notebook extensions](https://docs.continuum.io/anaconda/user-guide/tasks/use-jupyter-notebook-extensions)
that allow users to define custom environment-based kernels from within the
Jupyter notebook dashboard.
- [Lmod](https://www.tacc.utexas.edu/research-development/tacc-projects/lmod)
6.0.1+ or any other `module restore` and `module load <modules>` based CLI
6.0.1+ or any other `module purge` and `module load <modules>` based CLI
used to load appropriate environments within the batch job before launching
the Jupyter Notebook server.
......
const table = {
"interactive": { "max_cpu": 48, "max_hour": 2, "max_gpu": 0 },
"express": { "max_cpu": 48, "max_hour": 2, "max_gpu": 0 },
"short": { "max_cpu": 48, "max_hour": 12, "max_gpu": 0 },
"pascalnodes": { "max_cpu": 28, "max_hour": 12, "max_gpu": 4 },
"pascalnodes-medium": { "max_cpu": 28, "max_hour": 48, "max_gpu": 4 },
"medium": { "max_cpu": 48, "max_hour": 50, "max_gpu": 0 },
"long": { "max_cpu": 48, "max_hour": 150, "max_gpu": 0 },
"intel-dcb": { "max_cpu": 24, "max_hour": 150, "max_gpu": 0 },
"amd-hdr100": { "max_cpu": 128, "max_hour": 150, "max_gpu": 0 },
"largemem": { "max_cpu": 24, "max_hour": 50, "max_gpu": 0 },
"largemem-long": { "max_cpu": 24, "max_hour": 150, "max_gpu": 0 },
"amperenodes": { "max_cpu": 128, "max_hour": 12, "max_gpu": 2 },
"amperenodes-medium": { "max_cpu": 128, "max_hour": 48, "max_gpu": 2 },
}
const gpu_part_regex = /pascal|ampere/;
function set_max_value(form_id, value) {
const form_element = $(form_id);
form_element.attr({'max': value});
if (form_element.val() > value)
form_element.val(value)
}
function set_partition_change_handler() {
let partition_select = $("#batch_connect_session_context_bc_partition");
partition_select.change( function(e) {
toggle_gpu_visibility(e);
});
}
function toggle_gpu_visibility(event) {
const partition = event.target.value;
const cpu_selector = '#batch_connect_session_context_bc_num_slots';
const gpu_selector = '#batch_connect_session_context_bc_num_gpus';
const hour_selector = '#batch_connect_session_context_bc_num_hours';
toggle_visibilty_of_form_group(gpu_selector, gpu_part_regex.test(partition));
set_max_value(cpu_selector, table[partition]["max_cpu"]);
set_max_value(gpu_selector, table[partition]["max_gpu"]);
set_max_value(hour_selector, table[partition]["max_hour"]);
}
function toggle_visibilty_of_form_group(form_id, show) {
let form_element = $(form_id);
let parent = form_element;
while (
(! parent[0].classList.contains('form-group')) &&
(! parent.is('html')) // ensure that we don't loop infinitely
) {
parent = parent.parent();
}
// If parent is HTML then something has gone wrong and visibility should not be changed
if ( parent.is('html') ) {
return;
}
if(show) {
parent.show();
} else {
parent.hide();
}
}
toggle_gpu_visibility(
// Fake the event
{ target: document.querySelector('#batch_connect_session_context_bc_partition') }
);
set_partition_change_handler();
<%-
partitions = OodAppkit.clusters[:SLURM_CLUSTER].custom_config[:partitions]
-%>
# Batch Connect app configuration file
#
# @note Used to define the submitted cluster, title, description, and
......@@ -8,7 +11,15 @@
# under /etc/ood/config/clusters.d/*.yml
# @example Use the Owens cluster at Ohio Supercomputer Center
# cluster: "owens"
cluster: ""
cluster: "SLURM_CLUSTER"
# Title of the app displayed in the Dashboard
title: "Jupyter Notebook"
# Description of the app displayed in the Dashboard (can use multi-line string
# and Markdown syntax)
description: |
This app will launch a Jupyter Notebook server on one or more cores.
# Define attribute values that aren't meant to be modified by the user within
# the Dashboard form
......@@ -25,7 +36,16 @@ attributes:
# modules: "python/3.5"
# @example Using combination of modules
# modules: "python/3.5 cuda/8.0.44"
modules: "python"
custom_environment:
widget: text_area
label: Environment Setup
value: |
# The latest version of Anaconda3 with jupyter is loaded by default.
# If you would like to load other modules
# or use specific version of Anaconda please list below
#
# format:
# module load example_module/VERSION example_module2
# Whether Conda extensions will be available within the Jupyter notebook
# server
......@@ -41,8 +61,44 @@ attributes:
# Any extra command line arguments to feed to the `jupyter notebook ...`
# command that launches the Jupyter notebook within the batch job
extra_jupyter_args: ""
extra_jupyter_args:
widget: text_field
label: Extra jupyter arguments
bc_num_hours:
value: 1
bc_num_slots:
widget: "number_field"
label: Number of CPU
value: 1
min: 1
max: 24
step: 1
bc_num_mems:
widget: "number_field"
label: Memory per CPU (GB)
value: 4
min: 1
max: 128
step: 1
bc_num_gpus:
widget: "number_field"
label: Number of GPUs
value: 1
min: 0
max: 4
step: 1
bc_partition:
widget: select
label: Partition
options:
<%- partitions.each do |p| -%>
- [ "<%= p %>", "<%= p %>" ]
<%- end -%>
# All of the attributes that make up the Dashboard form (in respective order),
# and made available to the submit configuration file and the template ERB
# files
......@@ -53,11 +109,12 @@ attributes:
# option, then it will not appear in the form page that the user sees in the
# Dashboard
form:
- modules
- custom_environment
- conda_extensions
- extra_jupyter_args
- bc_num_hours
- bc_partition
- bc_num_gpus
- bc_num_slots
- bc_account
- bc_queue
- bc_num_mems
- bc_email_on_started
# Job submission configuration file
#
<%-
email = ENV['USER']
if !email.include? '@'
email = email + '@uab.edu'
end
-%>
---
# This config comes from below URL
# https://github.com/OSC/bc_example_jupyter/blob/custom_environment/submit.yml.erb
# The -C option in the config provided for slurm has been removed because it does
# not apply to implementation at UAB. We do not use constraint list to be used with -C.
#
# Configure the content of the job script for the batch job here
# @see http://www.rubydoc.info/gems/ood_core/OodCore/BatchConnect/Template
#
batch_connect:
# We use the basic web server template for generating the job script
#
# @note Do not change this unless you know what you are doing!
template: "basic"
# You can override the command used to query the hostname of the compute node
# here
#
# @note It is **highly** recommended this be set in the global cluster
# configuration file so that all apps can take advantage of it by default
#
#set_host: "host=$(hostname -A | awk '{print $2}')"
#
# Configure the job script submission parameters for the batch job here
# @see http://www.rubydoc.info/gems/ood_core/OodCore/Job/Script
#
# Example for Slurm
#
# @example Specify nodes with specific features for all jobs
#script:
# native: [ "-N", "<%= bc_num_slots.blank? ? 1 : bc_num_slots.to_i %>", "-C", "c12" ]
# Examples for PBS/Torque
#
# @example Specify the PPN for all jobs
#script:
# native:
# resources:
# nodes: "<%= bc_num_slots.blank? ? 1 : bc_num_slots.to_i %>:ppn=28"
script:
job_environment:
USER: "<%= ENV['USER'] %>"
native:
- "-N 1"
- "-n <%= bc_num_slots.blank? ? 1 : bc_num_slots.to_i %>"
- "--mem-per-cpu=<%= bc_num_mems.blank? ? 4 : bc_num_mems.to_i %>G"
- "--partition=<%= bc_partition %>"
- "--time=<%= bc_num_hours.blank? ? 1 : bc_num_hours.to_i %>:00:00"
- "--job-name=ood-jupyter"
<%- if bc_partition.include? "pascalnodes" or bc_partition.include? "amperenodes" -%>
- "--gres=gpu:<%= bc_num_gpus.blank? ? 1 : bc_num_gpus.to_i %>"
<%- end -%>
<%- if bc_email_on_started == "1" -%>
- "--mail-type=BEGIN"
- "--mail-user=<%= email %>"
<%- end -%>
# Wait for the Jupyter Notebook server to start
echo "Waiting for Jupyter Notebook server to open port ${port}..."
echo "TIMING - Starting wait at: $(date)"
if wait_until_port_used "${host}:${port}" 600; then
echo "Discovered Jupyter Notebook server listening on port ${port}!"
echo "TIMING - Wait ended at: $(date)"
else
echo "Timed out waiting for Jupyter Notebook server to open port ${port}!"
echo "TIMING - Wait ended at: $(date)"
pkill -P ${SCRIPT_PID}
clean_up 1
fi
sleep 2
......@@ -26,6 +26,9 @@
# - $password
# The plain text password used to authenticate to the web server with
# Export the module function if it exists
[[ $(type -t module) == "function" ]] && export -f module
# Find available port to run server on
port=$(find_port)
......@@ -51,13 +54,5 @@ c.NotebookApp.open_browser = False
c.NotebookApp.allow_origin = '*'
c.NotebookApp.notebook_dir = '${HOME}'
c.NotebookApp.disable_check_xsrf = True
<%- if context.conda_extensions == "1" -%>
c.NotebookApp.kernel_spec_manager_class = "nb_conda_kernels.CondaKernelSpecManager"
c.NotebookApp.nbserver_extensions = {
"nb_conda": True,
"nb_anacondacloud": True,
"nbpresent": True
}
<%- end -%>
EOL
)
......@@ -2,18 +2,12 @@
# Set working directory to home directory
cd "${HOME}"
module reset
#
# Start Jupyter Notebook Server
#
<%- unless context.modules.blank? -%>
# Restore the module environment to avoid conflicts
module restore
# Load the require modules
module load <%= context.modules %>
<%- end -%>
module load Anaconda3
<%= context.custom_environment.gsub(/\r\n?/, "\n") %>
unset XDG_RUNTIME_DIR
# Launch the Jupyter Notebook Server
jupyter notebook --config="${CONFIG_FILE}" <%= context.extra_jupyter_args %>
<p>
If you see <code>Failed to connect to ...</code>, then wait a few seconds
before trying the <strong>Connect to Jupyter</strong> button again. This
warning appeared because the Jupyter Notebook is still starting up.
</p>
<form action="/node/<%= host %>/<%= port %>/login" method="post" target="_blank">
<input type="hidden" name="password" value="<%= password %>">
<button class="btn btn-primary" type="submit">
<i class="fa fa-eye"></i> Connect to Jupyter
<i class="fas fa-eye"></i> Connect to Jupyter
</button>
</form>