-
Notifications
You must be signed in to change notification settings - Fork 19
SwanProjects extension for jupyter lab 3 #179
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
Changes from 1 commit
5e26c37
21c1cc2
80a44db
6704f9c
edd7fd6
59f3bb6
ee09134
c46c6c5
fcb1bf8
7c23c4f
5a47769
2a34628
c8e523d
b98417e
0475672
fd65b54
6bc92ce
4b43c4d
d9fc48f
ddd5886
9034e6a
624ce69
0861e56
7ed1f84
3abc7cc
f449a19
9683f5a
6fc7185
aaa40e4
a3fad1b
1cb3933
c5e7a6b
fb6a88b
8086bc9
cf79b5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[bumpversion] | ||
current_version = 0.1.0 | ||
commit = True | ||
tag = True | ||
tag_name = SwanProjects/v{new_version} | ||
message = SwanProjects v{new_version} | ||
|
||
[bumpversion:file:swanprojects/_version.py] | ||
|
||
[bumpversion:file:package.json] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
include LICENSE | ||
include README.md | ||
include SECURITY.md | ||
include pyproject.toml | ||
recursive-include jupyter-config *.json | ||
|
||
include swanprojects/kernelmanager/resources/* | ||
include swanprojects/stacks.json | ||
include swanprojects/static/index.html | ||
include package.json | ||
include install.json | ||
include ts*.json | ||
include yarn.lock | ||
|
||
graft swanprojects/labextension | ||
|
||
# Javascript files | ||
graft src | ||
graft style | ||
prune **/node_modules | ||
prune lib | ||
prune binder | ||
|
||
# Patterns to exclude from any directory | ||
global-exclude *~ | ||
global-exclude *.pyc | ||
global-exclude *.pyo | ||
global-exclude .git | ||
global-exclude .ipynb_checkpoints |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# SwanProjects | ||
|
||
Server and Lab extension that provides: | ||
* In the backend, the endpoints to: | ||
* Create and edit projects | ||
* Get project information | ||
* Get software stack information | ||
* Customized Kernel Spec Manager to handle kernel metadata. | ||
* In the Lab extension: | ||
* React dialogs with a set of components that allows to create and edit projects | ||
* LabIcons required for the dialogs | ||
|
||
## Requirements | ||
|
||
JupyterLab~=3.0 and SwanContents | ||
|
||
## Install | ||
|
||
Install the package and the lab extension: | ||
|
||
```bash | ||
pip install swanprojects | ||
``` | ||
|
||
To replace the default Jupyter Contents Manager and Kernel Spec Manager in the JupyterLab Notebook configuration (i.e in `jupyter_notebook_config.py`), set the following: | ||
|
||
```python | ||
c.NotebookApp.default_url = 'lab' | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
c.NotebookApp.contents_manager_class = 'swancontents.filemanager.swanfilemanager.SwanFileManager' | ||
c.NotebookApp.kernel_spec_manager_class = 'swanprojects.kernelmanager.kernelspecmanager.SwanKernelSpecManager' | ||
c.KernelSpecManager.ensure_native_kernel = False | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this? If it's something mandatory, just set it in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, It is mandatory, otherwise, Jupyterlab is able to put a default python kernel. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment explaining |
||
|
||
c.SwanProjects.stacks_path=path_to_stacks.json | ||
c.SwanKSMConfig.kernel_resources=path_to_native_kernel_resources | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Security Policy | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
## Supported Versions | ||
|
||
Use this section to tell people about which versions of your project are | ||
currently being supported with security updates. | ||
|
||
| Version | Supported | | ||
| ------- | ------------------ | | ||
| 0.1.0 | :white_check_mark: | | ||
|
||
## Reporting a Vulnerability | ||
|
||
Use this section to tell people how to report a vulnerability. | ||
|
||
Tell them where to go, how often they can expect to get an update on a | ||
reported vulnerability, what to expect if the vulnerability is accepted or | ||
declined, etc. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#!/bin/bash -i | ||
omazapa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#Author Omar.Zapata@cern.ch 2021 | ||
|
||
omazapa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
clear | ||
if ! [ -x "$(command -v jq)" ]; then | ||
echo 'Error: jq is not installed.' >&2 | ||
sleep 60 | ||
exit 1 | ||
fi | ||
if [[ $# -gt 0 ]] ; then | ||
PROJECT=$1 | ||
PROJECT_PATH="$HOME/SWAN_projects/$PROJECT" | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
PROJECT_FILE="$PROJECT_PATH/.swanproject" | ||
|
||
if [ -d "$PROJECT_PATH" ] | ||
then | ||
STACK=`jq '.stack' $PROJECT_FILE` | ||
RELEASE=`jq '.release' $PROJECT_FILE` | ||
PLATFORM=`jq '.platform' $PROJECT_FILE` | ||
USER_SCRIPT="$PROJECT_PATH/.userscript" | ||
env -i HOME=$HOME OAUTH2_FILE=$OAUTH2_FILE \ | ||
OAUTH2_TOKEN=$OAUTH2_TOKEN \ | ||
OAUTH_INSPECTION_ENDPOINT=$OAUTH_INSPECTION_ENDPOINT \ | ||
PROJECT=$PROJECT \ | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
PROJECT_PATH=$PROJECT_PATH PS1="$PS1" \ | ||
PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:$HOME/.local/bin/" \ | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
bash -c "swan_env $PROJECT $PROJECT_PATH bash --rcfile <(echo 'PS1=\"($PROJECT) $PS1 \"') " | ||
else | ||
echo "Error: project $PROJECT_PATH doesn't exists" >&2 | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
sleep 60 | ||
omazapa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
exit 1 | ||
fi | ||
fi |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#!/bin/bash | ||
omazapa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#DEFINITIONS: | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
# STACK: LCG/CMSSW | ||
# RELEASE: version of the stack ex (LCG_99) | ||
# PLATFORM: usually os and compiler version | ||
# USER_SCRIPT: customized bash script provided by the user | ||
# CWD: working directory path | ||
PARAMETERS=($@) #WARNING: empty options disappear | ||
|
||
#Checking if jq is installed | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
if ! [ -x "$(command -v jq)" ]; then | ||
echo 'Error: jq is not installed.' >&2 | ||
sleep 60 | ||
omazapa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
exit 1 | ||
fi | ||
|
||
#Checking if we have more that 2 parameters | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
if [[ $# -lt 2 ]] ; then | ||
echo 'Error: project name and commands required.' >&2 | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
echo 'Example: swan_env myproject python --version' >&2 | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
sleep 60 | ||
exit 1 | ||
fi | ||
|
||
PROJECT=$1 | ||
PROJECT_PATH="$HOME/SWAN_projects/$PROJECT" | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
PROJECT_FILE="$PROJECT_PATH/.swanproject" | ||
STACK=`jq -r '.stack' $PROJECT_FILE` | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
RELEASE=`jq -r '.release' $PROJECT_FILE` | ||
PLATFORM=`jq -r '.platform' $PROJECT_FILE` | ||
USER_SCRIPT="$PROJECT_PATH/.userscript" | ||
|
||
CWD="$2" | ||
|
||
i=0 | ||
if [ "$CWD" != "" ]; then | ||
i=$((i+1)) | ||
fi | ||
|
||
for j in $(seq 0 1 $((i)));do | ||
unset PARAMETERS[$j] | ||
done | ||
|
||
COMMAND=${PARAMETERS[@]} | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
if [[ $STACK == "LCG" ]]; then | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
#example: swan_env SFT LCG_96 x86_64-centos7-gcc8-opt "" $PWD which python | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
CVMFS_PATH="/cvmfs/sft.cern.ch/lcg/views/$RELEASE/$PLATFORM/setup.sh" | ||
if [ "$SWAN_ENV_SILENCE" != "1" ]; then | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
echo "Loading $RELEASE with plafortm $PLATFORM " | ||
fi | ||
source $CVMFS_PATH | ||
fi | ||
|
||
if [[ $STACK == "CMSSW" ]]; then | ||
#example: swan_env CMS CMSSW_10_6_19 slc7_amd64_gcc820 ipython kernelspec list | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
source /cvmfs/cms.cern.ch/cmsset_default.sh | ||
if [ "$SWAN_ENV_SILENCE" != "1" ]; then | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
echo "Loading $RELEASE with plafortm $PLATFORM " | ||
fi | ||
CMS_BASEDIR=/cvmfs/cms.cern.ch | ||
CMSSW=$RELEASE | ||
SCRAM=$PLATFORM | ||
|
||
export PATH=${CMS_BASEDIR}/common:$PATH | ||
#by default I will load the environment in the cvmfs path in read only | ||
cd /cvmfs/cms.cern.ch/$SCRAM/cms/cmssw/$CMSSW | ||
eval `scramv1 runtime -sh` | ||
#requires to prepend the lib and bin paths | ||
export LD_LIBRARY_PATH=/cvmfs/cms.cern.ch/$SCRAM/cms/cmssw/$CMSSW/external/$SCRAM/lib/:$LD_LIBRARY_PATH | ||
export PATH=/cvmfs/cms.cern.ch/$SCRAM/cms/cmssw/$CMSSW/external/$SCRAM/bin/:$PATH | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
fi | ||
export SWAN_STACK="$RELEASE($PLATFORM)" | ||
export SWAN_PROJECT_NAME=$PROJECT | ||
export SWAN_PROJECT_PATH=$PROJECT_PATH | ||
diocas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
omazapa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if [ "$USER_SCRIPT" != "" ] && [ -f "$USER_SCRIPT" ]; then | ||
omazapa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
. ${USER_SCRIPT} | ||
fi | ||
cd $CWD | ||
$COMMAND | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
#!/usr/bin/env python | ||
import argparse | ||
import json | ||
import os | ||
import pprint | ||
import subprocess | ||
import sys | ||
from distutils.spawn import find_executable | ||
from shutil import rmtree | ||
|
||
def _checkipykernel(project_path,python_interpreter,python_version): | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
python_code='import ipykernel' | ||
command = [python_interpreter,"-c",python_code] | ||
proc = subprocess.Popen(command, stdout = subprocess.PIPE) | ||
proc.wait() | ||
data = proc.stdout.read().decode("utf-8") | ||
print(data) | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
proc.communicate() | ||
if proc.returncode !=0 : | ||
print("Error ipykernel not found for {} in project {}".format(python_version,project_path)) | ||
return proc.returncode | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
def check_native_kernel(project_path): | ||
project_file = project_path+os.path.sep+".swanproject" | ||
f = open(project_file,"r+") | ||
project_data = f.read() | ||
if project_data.strip() == "": | ||
project_data = {} | ||
else: | ||
project_data = json.loads(project_data) | ||
print(project_data) | ||
f.seek(0) | ||
python2 = find_executable("python2") | ||
omazapa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if python2 is not None: | ||
print("python2 found = "+python2) | ||
project_data["python2"]={"found":True,"path":python2} | ||
rcode = _checkipykernel(project_path,python2,"python2") | ||
if rcode == 0: | ||
project_data["python2"]["ipykernel"] = True | ||
else: | ||
project_data["python2"]["ipykernel"] = False | ||
else: | ||
project_data["python2"]["found"] = False | ||
|
||
python3 = find_executable("python3") | ||
if python3 is not None: | ||
print("python3 found = "+python3) | ||
project_data["python3"]={"found":True,"path":python3} | ||
rcode = _checkipykernel(project_path,python3,"python3") | ||
if rcode == 0: | ||
project_data["python3"]["ipykernel"] = True | ||
else: | ||
project_data["python3"]["ipykernel"] = False | ||
else: | ||
project_data["python3"]["found"] = False | ||
|
||
f.seek(0) | ||
f.truncate() | ||
json.dump(project_data,f,indent=4) | ||
f.close() | ||
|
||
def save_kernel_paths(project_path): | ||
from jupyter_core.paths import jupyter_path | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
kernels_blacklist_paths = [os.environ["HOME"]+os.sep+'.local/share/jupyter/kernels','/usr/local/share/jupyter/kernels','/usr/share/jupyter/kernels'] | ||
tmp_paths = jupyter_path('kernels') | ||
paths = [] | ||
for path in tmp_paths: | ||
diocas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
found=False | ||
for bl_path in kernels_blacklist_paths: | ||
if bl_path in path: | ||
found=True | ||
if not found: | ||
paths.append(path) | ||
project_file = project_path+os.path.sep+".swanproject" | ||
|
||
with open(project_file,"r+") as f: | ||
project_data = f.read() | ||
if project_data == "": | ||
project_data = {} | ||
else: | ||
project_data = json.loads(project_data) | ||
f.seek(0) | ||
f.truncate() | ||
if "kernel_dirs" in list(project_data.keys()): | ||
project_data["kernel_dirs"] = project_data["kernel_dirs"] + paths | ||
else: | ||
project_data["kernel_dirs"] = paths | ||
json.dump(project_data,f,indent=4) | ||
|
||
def generate_ksminfo(project_path): | ||
check_native_kernel(project_path) | ||
save_kernel_paths(project_path) | ||
|
||
def swan_kmspecs(project_name): | ||
command = ["env","-i","HOME=%s"%os.environ["HOME"]] | ||
#checking if we are on EOS to add the env variables | ||
#we required this to read/write in a isolate environment with EOS | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
if "OAUTH2_FILE" in os.environ: | ||
command.append("OAUTH2_FILE=%s"%os.environ["OAUTH2_FILE"]) | ||
if "OAUTH2_TOKEN" in os.environ: | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
command.append("OAUTH2_TOKEN=%s"%os.environ["OAUTH2_TOKEN"]) | ||
if "OAUTH_INSPECTION_ENDPOINT" in os.environ: | ||
command.append("OAUTH_INSPECTION_ENDPOINT=%s"%os.environ["OAUTH_INSPECTION_ENDPOINT"]) | ||
|
||
#special case when the package was not installed like root, useful for development | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
command.append("PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:{}/.local/bin/".format(os.environ["HOME"])) | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
command += ["/bin/bash","swan_env",project_name, ".","python",__file__,"--generate_ksminfo","--project_name",project_name] | ||
print(" ".join(command)) | ||
proc = subprocess.Popen(command, stdout = subprocess.PIPE) | ||
proc.wait() | ||
data = proc.stdout.read().decode("utf-8") | ||
proc.communicate() | ||
if proc.returncode !=0 : | ||
print("Error creating navite kernel for project {}".format(project_name)) | ||
|
||
return proc.returncode | ||
|
||
if __name__ == '__main__': | ||
parser = argparse.ArgumentParser(description='Swan Enviroment Kernel Manager CMD options.') | ||
parser.add_argument('--project_name', type=str,required=True, help='Project name') | ||
parser.add_argument('--generate_ksminfo', action='store_true',default=None, help='Generates Kernel Spec Manager info') | ||
args = parser.parse_args() | ||
project_name = args.project_name | ||
|
||
project_path = os.environ["HOME"]+"/SWAN_projects/"+project_name | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
if args.generate_ksminfo: | ||
omazapa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
generate_ksminfo(project_path) | ||
else: | ||
rcode = swan_kmspecs(project_name) | ||
sys.exit(rcode) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"packageManager": "python", | ||
"packageName": "swanprojects", | ||
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package swanprojects" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"NotebookApp": { | ||
"nbserver_extensions": { | ||
"swanprojects": true | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"ServerApp": { | ||
"jpserver_extensions": { | ||
"swanprojects": true | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.