### Install tbump Source: https://github.com/jupyterhub/batchspawner/blob/main/RELEASE.md Install the tbump tool, which is used for version bumping and tagging. ```shell pip install tbump ``` -------------------------------- ### Check Resource Limits and Partitions Source: https://context7.com/jupyterhub/batchspawner/llms.txt If a job is queued but not starting, inspect partition information for SLURM or use checkjob for Moab to identify potential resource constraints. ```bash sinfo -p standard --long # SLURM partition info ``` ```bash checkjob # Moab ``` -------------------------------- ### Install Batchspawner and Basic JupyterHub Configuration Source: https://context7.com/jupyterhub/batchspawner/llms.txt Install the package via pip and register a spawner class in `jupyterhub_config.py`. The `import batchspawner` statement is required to register API routes and spawner classes. Increase timeouts as batch jobs can take time to be scheduled. ```python # Install # pip install batchspawner # jupyterhub_config.py — minimal setup import batchspawner # required to register spawner API c.JupyterHub.spawner_class = 'batchspawner.SlurmSpawner' # Increase timeout: batch jobs can take time to be scheduled c.Spawner.http_timeout = 120 c.BatchSpawnerBase.start_timeout = 300 # seconds ``` -------------------------------- ### Configure ProfilesSpawner with BatchSpawner Options Source: https://github.com/jupyterhub/batchspawner/blob/main/README.md Example of using ProfilesSpawner to offer multiple configurations for BatchSpawner. Includes local server and various TorqueSpawner job profiles with different resource allocations and queues. ```python import batchspawner c.JupyterHub.spawner_class = 'wrapspawner.ProfilesSpawner' c.Spawner.http_timeout = 120 #------------------------------------------------------------------------------ # BatchSpawnerBase configuration # Providing default values that we may omit in the profiles #------------------------------------------------------------------------------ c.BatchSpawnerBase.req_host = 'mesabi.xyz.edu' c.BatchSpawnerBase.req_runtime = '12:00:00' c.TorqueSpawner.state_exechost_exp = r'in-\1.mesabi.xyz.edu' #------------------------------------------------------------------------------ # ProfilesSpawner configuration #------------------------------------------------------------------------------ # List of profiles to offer for selection. Signature is: # List(Tuple( Unicode, Unicode, Type(Spawner), Dict )) # corresponding to profile display name, unique key, Spawner class, # dictionary of spawner config options. # # The first three values will be exposed in the input_template as {display}, # {key}, and {type} # c.ProfilesSpawner.profiles = [ ( "Local server", 'local', 'jupyterhub.spawner.LocalProcessSpawner', {'ip':'0.0.0.0'} ), ('Mesabi - 2 cores, 4 GB, 8 hours', 'mesabi2c4g12h', 'batchspawner.TorqueSpawner', dict(req_nprocs='2', req_queue='mesabi', req_runtime='8:00:00', req_memory='4gb')), ('Mesabi - 12 cores, 128 GB, 4 hours', 'mesabi128gb', 'batchspawner.TorqueSpawner', dict(req_nprocs='12', req_queue='ram256g', req_runtime='4:00:00', req_memory='125gb')), ('Mesabi - 2 cores, 4 GB, 24 hours', 'mesabi2c4gb24h', 'batchspawner.TorqueSpawner', dict(req_nprocs='2', req_queue='mesabi', req_runtime='24:00:00', req_memory='4gb')), ('Interactive Cluster - 2 cores, 4 GB, 8 hours', 'lab', 'batchspawner.TorqueSpawner', dict(req_nprocs='2', req_host='labhost.xyz.edu', req_queue='lab', req_runtime='8:00:00', req_memory='4gb', state_exechost_exp='')) ] c.ProfilesSpawner.ip = '0.0.0.0' ``` -------------------------------- ### Configure Torque Spawner with BatchSpawnerBase Source: https://github.com/jupyterhub/batchspawner/blob/main/README.md Example configuration for TorqueSpawner, setting common batch job parameters like number of processes, queue, host, runtime, and memory. These parameters are used in the job script template. ```python # Select the Torque backend and increase the timeout since batch jobs may take time to start import batchspawner c.JupyterHub.spawner_class = 'batchspawner.TorqueSpawner' c.Spawner.http_timeout = 120 #------------------------------------------------------------------------------ # BatchSpawnerBase configuration # These are simply setting parameters used in the job script template below #------------------------------------------------------------------------------ c.BatchSpawnerBase.req_nprocs = '2' c.BatchSpawnerBase.req_queue = 'mesabi' c.BatchSpawnerBase.req_host = 'mesabi.xyz.edu' c.BatchSpawnerBase.req_runtime = '12:00:00' c.BatchSpawnerBase.req_memory = '4gb' #------------------------------------------------------------------------------ # TorqueSpawner configuration # The script below is nearly identical to the default template, but we needed # to add a line for our local environment. For most sites the default templates ``` -------------------------------- ### Verify Batchspawner Import Source: https://context7.com/jupyterhub/batchspawner/llms.txt Confirm that the batchspawner package is correctly installed and importable in your JupyterHub configuration. ```python python -c "import batchspawner; print(batchspawner.__version__)" ``` -------------------------------- ### Configure PBSSpawner for OpenPBS/PBS Pro Source: https://context7.com/jupyterhub/batchspawner/llms.txt Configure PBSSpawner for OpenPBS/PBS Pro. Uses 'select' syntax for resources and 'qstat -fx' for state parsing. Customizes resource requests and runtime. ```python # jupyterhub_config.py import batchspawner c.JupyterHub.spawner_class = 'batchspawner.PBSSpawner' c.PBSSpawner.req_queue = 'workq' c.PBSSpawner.req_host = 'pbspro.hpc.example.org' c.PBSSpawner.req_nprocs = '4' c.PBSSpawner.req_memory = '10256mb' c.PBSSpawner.req_runtime = '08:00:00' c.PBSSpawner.req_options = '-l place=scatter' # Default batch_script uses Jinja2 with select= syntax: # #PBS -l select=1:ncpus={{nprocs}}:mem={{memory}} # Output: {{homedir}}/.jupyterhub.pbs.out ``` -------------------------------- ### Configure GridengineSpawner for SGE/Univa Source: https://context7.com/jupyterhub/batchspawner/llms.txt Configure GridengineSpawner for SGE/Univa/Son of Grid Engine clusters. Uses qsub/qstat -xml/qdel and forwards SGE environment variables. ```python # jupyterhub_config.py import batchspawner c.JupyterHub.spawner_class = 'batchspawner.GridengineSpawner' c.GridengineSpawner.req_qname = 'compute' c.GridengineSpawner.req_pe = 'make' c.GridengineSpawner.req_slots = '1' c.GridengineSpawner.req_shell = '/bin/bash' c.GridengineSpawner.req_use_qname = True # Custom batch script (Jinja2) c.GridengineSpawner.batch_script = '''#!/bin/bash #$ -S {shell} #$ -cwd #$ -V #$ -q {qname} #$ -pe {pe} {slots} #$ -N jupyterhub-singleuser set -euo pipefail {{prologue}} {{cmd}} {{epilogue}} ''' ``` -------------------------------- ### Configuring Multiple Spawn Profiles with wrapspawner Source: https://context7.com/jupyterhub/batchspawner/llms.txt Configure JupyterHub to use `wrapspawner.ProfilesSpawner` to present users with a dropdown menu for selecting different spawner configurations. Each profile defines a name, a spawner class, and a dictionary of configuration overrides. ```python # jupyterhub_config.py import batchspawner # registers batchspawner classes c.JupyterHub.spawner_class = 'wrapspawner.ProfilesSpawner' c.Spawner.http_timeout = 120 # Shared defaults c.BatchSpawnerBase.req_host = 'slurm.cluster.example.edu' c.BatchSpawnerBase.req_runtime = '08:00:00' c.ProfilesSpawner.profiles = [ ( "Local server (no cluster)", 'local', 'jupyterhub.spawner.LocalProcessSpawner', {'ip': '127.0.0.1'}, ), ( "SLURM — 2 cores, 4 GB RAM, 8 h", 'slurm_small', 'batchspawner.SlurmSpawner', dict(req_nprocs='2', req_partition='standard', req_memory='4G', req_runtime='08:00:00'), ), ( "SLURM — 16 cores, 64 GB RAM, 4 h", 'slurm_large', 'batchspawner.SlurmSpawner', dict(req_nprocs='16', req_partition='highmem', req_memory='64G', req_runtime='04:00:00'), ), ( "SLURM — 4 cores, 1 GPU (V100), 2 h", 'slurm_gpu', 'batchspawner.SlurmSpawner', dict(req_nprocs='4', req_partition='gpu', req_gres='gpu:v100:1', req_memory='16G', req_runtime='02:00:00'), ), ( "Torque — 8 cores, 32 GB RAM, 12 h", 'torque_large', 'batchspawner.TorqueSpawner', dict(req_nprocs='8', req_queue='batch', req_memory='32gb', req_runtime='12:00:00'), ), ] c.ProfilesSpawner.ip = '0.0.0.0' ``` -------------------------------- ### Configure GridengineSpawner Source: https://context7.com/jupyterhub/batchspawner/llms.txt Set the spawner class to GridengineSpawner and define requested options and prologue script for Gridengine jobs. ```python import batchspawner c.JupyterHub.spawner_class = 'batchspawner.GridengineSpawner' c.GridengineSpawner.req_options = '-pe mpi 4 -l h_rt=08:00:00 -l mem_free=2G' c.GridengineSpawner.req_prologue = 'source /opt/sge/default/common/settings.sh' ``` -------------------------------- ### Configure LsfSpawner Source: https://context7.com/jupyterhub/batchspawner/llms.txt Set the spawner class to LsfSpawner and define the requested queue, options, and prologue script for LSF jobs. ```python import batchspawner c.JupyterHub.spawner_class = 'batchspawner.LsfSpawner' c.LsfSpawner.req_queue = 'interactive' c.LsfSpawner.req_options = '-R "rusage[mem=4096]" -n 4' c.LsfSpawner.req_prologue = 'module load jupyter/2023' ``` -------------------------------- ### Configure TorqueSpawner for Torque/PBS Source: https://context7.com/jupyterhub/batchspawner/llms.txt Configure TorqueSpawner for Torque (OpenPBS). Set resource requests and specify a custom batch script using string formatting. ```python # jupyterhub_config.py import batchspawner c.JupyterHub.spawner_class = 'batchspawner.TorqueSpawner' c.TorqueSpawner.req_queue = 'batch' c.TorqueSpawner.req_host = 'torque.cluster.example.edu' c.TorqueSpawner.req_nprocs = '2' c.TorqueSpawner.req_memory = '4gb' c.TorqueSpawner.req_runtime = '12:00:00' # Rewrite internal node names to routable hostnames (re.match.expand syntax) c.TorqueSpawner.state_exechost_exp = r'int-\1.cluster.example.edu' # Custom batch script (str.format style) c.TorqueSpawner.batch_script = '''#!/bin/sh #PBS -q {queue}@{host} #PBS -l walltime={runtime} #PBS -l nodes=1:ppn={nprocs} #PBS -l mem={memory} #PBS -N jupyterhub-singleuser #PBS -v {keepvars} #PBS {options} set -eu module load python3/3.11 {prologue} {cmd} {epilogue} ''' ``` -------------------------------- ### Configure SlurmSpawner for SLURM Source: https://context7.com/jupyterhub/batchspawner/llms.txt Configure SlurmSpawner to use SLURM. Set resource requests like partition, memory, and GPUs. Customize the sbatch script using Jinja2 templating. ```python # jupyterhub_config.py import batchspawner c.JupyterHub.spawner_class = 'batchspawner.SlurmSpawner' c.Spawner.http_timeout = 120 c.SlurmSpawner.req_partition = 'standard' c.SlurmSpawner.req_nprocs = '2' c.SlurmSpawner.req_memory = '4G' c.SlurmSpawner.req_runtime = '08:00:00' c.SlurmSpawner.req_gres = 'gpu:1' # generic resources c.SlurmSpawner.req_reservation = 'jupyter_res' # optional reservation c.SlurmSpawner.req_qos = 'interactive' # optional QoS c.SlurmSpawner.req_cluster = 'mycluster' # multi-cluster support c.SlurmSpawner.req_account = 'pi_group' # Disable srun wrapping if needed (affects env handling — see SPAWNERS.md) # c.SlurmSpawner.req_srun = '' # Customize the submit script (Jinja2) c.SlurmSpawner.batch_script = '''#!/bin/bash #SBATCH --output={{homedir}}/jupyter_%j.log #SBATCH --job-name=jupyter-{{username}} #SBATCH --chdir={{homedir}} #SBATCH --export={{keepvars}} #SBATCH --get-user-env=L {% if partition %}#SBATCH --partition={{partition}}{% endif %} {% if runtime %}#SBATCH --time={{runtime}}{% endif %} {% if memory %}#SBATCH --mem={{memory}}{% endif %} {% if gres %}#SBATCH --gres={{gres}}{% endif %} {% if nprocs %}#SBATCH --cpus-per-task={{nprocs}}{% endif %} {% if reservation%}#SBATCH --reservation={{reservation}}{% endif %} {% if options %}#SBATCH {{options}}{% endif %} set -euo pipefail trap 'echo SIGTERM received' TERM {{prologue}} {% if srun %}{{srun}} {% endif %}{{cmd}} echo "jupyterhub-singleuser ended gracefully" {{epilogue}} ''' ``` -------------------------------- ### Custom Scheduler Spawner with Regex States Source: https://context7.com/jupyterhub/batchspawner/llms.txt Create a custom spawner by inheriting from BatchSpawnerRegexStates. Define batch script template, commands, and regexes for state detection. ```python from batchspawner.batchspawner import BatchSpawnerRegexStates from traitlets import Unicode class MySchedulerSpawner(BatchSpawnerRegexStates): """Spawner for a custom batch scheduler.""" batch_script = Unicode('''#!/bin/bash #MY --queue={queue} #MY --cpus={nprocs} #MY --mem={memory} {cmd} ''').tag(config=True) batch_submit_cmd = Unicode('myjob submit').tag(config=True) batch_query_cmd = Unicode('myjob status {job_id}').tag(config=True) batch_cancel_cmd = Unicode('myjob cancel {job_id}').tag(config=True) # Regexes matched against stdout of batch_query_cmd state_pending_re = Unicode(r'status:\s+QUEUED').tag(config=True) state_running_re = Unicode(r'status:\s+RUNNING').tag(config=True) state_unknown_re = Unicode(r'connection refused').tag(config=True) # First capture group (or state_exechost_exp expansion) becomes notebook IP state_exechost_re = Unicode(r'running_on:\s+([\w.\-]+)').tag(config=True) state_exechost_exp = Unicode(r'\1.internal.example.com').tag(config=True) # Register in jupyterhub_config.py: # import batchspawner # from mymodule import MySchedulerSpawner # c.JupyterHub.spawner_class = MySchedulerSpawner ``` -------------------------------- ### Configure MultiSlurmSpawner Source: https://context7.com/jupyterhub/batchspawner/llms.txt Set the spawner class to MultiSlurmSpawner for SLURM clusters with multiple daemons. Configure the daemon resolver, partition, number of processes, and GPU resources. ```python import batchspawner c.JupyterHub.spawner_class = 'batchspawner.MultiSlurmSpawner' # Map SLURM daemon node names -> real hostnames c.MultiSlurmSpawner.daemon_resolver = { 'node001d': 'node001.cluster.example.edu', 'node002d': 'node002.cluster.example.edu', 'gpunode01d': 'gpu01.cluster.example.edu', } c.MultiSlurmSpawner.req_partition = 'gpu' c.MultiSlurmSpawner.req_nprocs = '4' c.MultiSlurmSpawner.req_gres = 'gpu:v100:1' ``` -------------------------------- ### batchspawner-singleuser internal logic Source: https://context7.com/jupyterhub/batchspawner/llms.txt This Python comment outlines the internal steps performed by the batchspawner-singleuser script: port selection, notifying JupyterHub, updating environment variables or arguments, and executing the singleuser server. ```python # batchspawner/singleuser.py — what main() does internally: # 1. port = random_port() — pick a free TCP port # 2. POST /api/batchspawner {"port": port} — notify JupyterHub # 3. patch JUPYTERHUB_SERVICE_URL or append --port= to sys.argv # 4. run_path(which(sys.argv[1])) — exec the real singleuser server ``` -------------------------------- ### Running batchspawner-singleuser Source: https://context7.com/jupyterhub/batchspawner/llms.txt The batchspawner-singleuser script is the entry point for batch jobs. It selects a free port, notifies the hub, and then executes the real singleuser server. You can specify a custom path for this script in your JupyterHub configuration. ```bash # The batch script ultimately runs something like: batchspawner-singleuser jupyterhub-singleuser \ --ip=0.0.0.0 \ --SingleUserNotebookApp.default_url=/lab # To use a non-default path (e.g., in a virtualenv): c.BatchSpawnerBase.batchspawner_singleuser_cmd = '/opt/conda/bin/batchspawner-singleuser' ``` -------------------------------- ### Tag Release Version with tbump Source: https://github.com/jupyterhub/batchspawner/blob/main/RELEASE.md Use tbump to set the new release version, create a commit, and push a git tag. tbump will prompt for confirmation. ```shell # Example versions to set: 1.0.0, 1.0.0b1 VERSION= tbump ${VERSION} ``` -------------------------------- ### format_template Utility for Batch Script Templating Source: https://context7.com/jupyterhub/batchspawner/llms.txt Renders batch script templates using Jinja2 or Python's `str.format()`. This utility is called automatically by `_get_batch_script()` but can be used directly for custom subclasses or testing. ```python from batchspawner.batchspawner import format_template from jinja2 import Template # str.format() style (legacy, backward-compatible) tmpl = "#!/bin/bash\n#SBATCH --partition={partition}\n#SBATCH --mem={memory}\n{cmd}" result = format_template(tmpl, partition='gpu', memory='16gb', cmd='srun jupyter-server') print(result) # #!/bin/bash # #SBATCH --partition=gpu # #SBATCH --mem=16gb # srun jupyter-server # Jinja2 style — detected automatically by presence of {{ or {% tmpl_jinja = "#!/bin/bash\n{% if partition %}#SBATCH --partition={{partition}}{% endif %}\n{% if memory %}#SBATCH --mem={{memory}}{% endif %}\n{{cmd}}"} result = format_template(tmpl_jinja, partition='gpu', memory='', cmd='srun jupyter-server') print(result) # #!/bin/bash # #SBATCH --partition=gpu # # srun jupyter-server # Pre-compiled Jinja2 Template object is also accepted compiled = Template("#SBATCH --job-name={{username}}-jupyter") result = format_template(compiled, username='alice') # '#SBATCH --job-name=alice-jupyter' ``` -------------------------------- ### Configure JupyterHub Spawner Class Source: https://github.com/jupyterhub/batchspawner/blob/main/README.md Add these lines to your jupyterhub_config.py to specify the spawner class. Ensure batchspawner is imported to register its interface. ```python c = get_config() c.JupyterHub.spawner_class = 'batchspawner.TorqueSpawner' import batchspawner # Even though not used, needed to register batchspawner interface ``` -------------------------------- ### Add Tracing to Batch Script Source: https://context7.com/jupyterhub/batchspawner/llms.txt Enable debugging by adding 'set -x' and 'env | sort' to the prologue of your SlurmSpawner configuration to trace script execution and environment variables. ```python c.SlurmSpawner.req_prologue = 'set -x\nenv | sort' ``` -------------------------------- ### Configure CondorSpawner Source: https://context7.com/jupyterhub/batchspawner/llms.txt Set the spawner class to CondorSpawner and specify requested number of processes, memory, and other options for HTCondor jobs. ```python import batchspawner c.JupyterHub.spawner_class = 'batchspawner.CondorSpawner' c.CondorSpawner.req_nprocs = '2' c.CondorSpawner.req_memory = '4096' # MB c.CondorSpawner.req_options = 'Requirements = (OpSys == "LINUX") && (Arch == "X86_64")' ``` -------------------------------- ### Configure TorqueSpawner Host Regex Source: https://github.com/jupyterhub/batchspawner/blob/main/README.md Sets a regular expression for TorqueSpawner to parse the execution hostname from qstat output. This is specific to the 'mesabi.xyz.edu' domain. ```python r'int-\1.mesabi.xyz.edu' ``` -------------------------------- ### Configure MoabSpawner for Moab Workload Manager Source: https://context7.com/jupyterhub/batchspawner/llms.txt Configure MoabSpawner for Moab/TORQUE environments. Uses Moab equivalents for commands and inherits the TorqueSpawner batch script. ```python # jupyterhub_config.py import batchspawner c.JupyterHub.spawner_class = 'batchspawner.MoabSpawner' c.MoabSpawner.req_queue = 'interactive' c.MoabSpawner.req_nprocs = '8' c.MoabSpawner.req_memory = '16gb' c.MoabSpawner.req_runtime = '04:00:00' # Inherits TorqueSpawner batch_script; uses msub/mdiag/mjobctl # state_pending_re = r'State="Idle"' # state_running_re = r'State="Running"' ``` -------------------------------- ### Reset Version to Development with tbump Source: https://github.com/jupyterhub/batchspawner/blob/main/RELEASE.md After releasing, reset the version to the next development iteration using tbump with the --no-tag option. This prepares for subsequent development. ```shell # Example version to set: 1.0.1.dev NEXT_VERSION= tbump --no-tag ${NEXT_VERSION}.dev ``` -------------------------------- ### Configure TorqueSpawner Batch Script Source: https://github.com/jupyterhub/batchspawner/blob/main/README.md Defines the default batch script template for TorqueSpawner. Customize variables like queue, runtime, memory, and processes as needed. ```python #!/bin/sh #PBS -q {queue}@{host} #PBS -l walltime={runtime} #PBS -l nodes=1:ppn={nprocs} #PBS -l mem={memory} #PBS -N jupyterhub-singleuser #PBS -v {keepvars} module load python3 {cmd} ``` -------------------------------- ### Inspect Batch Job Output Files Source: https://context7.com/jupyterhub/batchspawner/llms.txt Examine the stdout and stderr log files for runtime errors. The log file path varies depending on the scheduler and job ID. ```bash cat ~/jupyterhub_slurmspawner_98765.log ``` -------------------------------- ### Job State Management with get_state, load_state, clear_state Source: https://context7.com/jupyterhub/batchspawner/llms.txt Persist and restore job tracking information across JupyterHub restarts using `get_state`, `load_state`, and `clear_state`. `job_id` and `job_status` are saved to the database, allowing the spawner to reconnect to running jobs. ```python # Illustrative use — normally called automatically by JupyterHub internals # After spawner.start() succeeds: state = spawner.get_state() # {'job_id': '98765', 'job_status': 'RUNNING compute-node-04'} # On hub restart — reload state and reconnect to the live job spawner2 = new_spawner(db=db) spawner2.load_state(state) assert spawner2.job_id == '98765' # Explicitly wipe state (e.g. after confirmed job termination) spawner2.clear_state() assert spawner2.get_state() == {} assert spawner2.job_id == '' ``` -------------------------------- ### BatchSpawnerBase Core Configuration Traits Source: https://context7.com/jupyterhub/batchspawner/llms.txt Configure resource requests and script fragments for the abstract base class. Traits named `req_*` are automatically exposed as template variables in batch scripts and commands. ```python # jupyterhub_config.py — shared base configuration import batchspawner # Resource request traits — available as {queue}, {nprocs}, {memory}, etc. in templates c.BatchSpawnerBase.req_queue = 'compute' c.BatchSpawnerBase.req_host = 'scheduler.cluster.example.edu' c.BatchSpawnerBase.req_nprocs = '4' c.BatchSpawnerBase.req_ngpus = '1' c.BatchSpawnerBase.req_memory = '8gb' c.BatchSpawnerBase.req_runtime = '04:00:00' c.BatchSpawnerBase.req_account = 'myproject' c.BatchSpawnerBase.req_partition = 'gpu' c.BatchSpawnerBase.req_options = '--constraint=infiniband' # Script fragments inserted before/after the singleuser server command c.BatchSpawnerBase.req_prologue = 'module load anaconda3/2023.09\nconda activate myenv' c.BatchSpawnerBase.req_epilogue = 'echo "Server exited cleanly"' # Extra environment variables to forward into the job (comma-separated) c.BatchSpawnerBase.req_keepvars_extra = 'MYAPP_TOKEN,SCRATCH_DIR' # Prefix prepended to every batch command (default: "sudo -E -u {username}") c.BatchSpawnerBase.exec_prefix = 'sudo -E -u {username}' # Polling interval (seconds) while waiting for the job to start c.BatchSpawnerBase.startup_poll_interval = 1.0 ``` -------------------------------- ### Test Port Communication Manually Source: https://context7.com/jupyterhub/batchspawner/llms.txt Inside a batch job shell, use the 'batchspawner-singleuser' command to test port communication for the JupyterHub single-user server. ```bash batchspawner-singleuser jupyterhub-singleuser --ip=0.0.0.0 ``` -------------------------------- ### Update Main Branch Source: https://github.com/jupyterhub/batchspawner/blob/main/RELEASE.md Ensure your local main branch is up-to-date with the remote repository before proceeding with release steps. ```shell git checkout main git fetch origin main git reset --hard origin/main ``` -------------------------------- ### Verify Scheduler Job Acceptance Source: https://context7.com/jupyterhub/batchspawner/llms.txt Check if the job was accepted by the scheduler using commands specific to SLURM, Torque/PBS, or LSF. ```bash squeue -u $USER --format="%.18i %.9P %.30j %.8T %.10M %.9l %R" # SLURM ``` ```bash qstat -u $USER # Torque/PBS ``` ```bash bjobs -u $USER # LSF ``` -------------------------------- ### POST /api/batchspawner API Request Source: https://context7.com/jupyterhub/batchspawner/llms.txt Manually send a POST request to the batchspawner API to report a dynamically chosen port. This is typically handled internally by batchspawner-singleuser. Ensure the correct API URL and token are used. For internal SSL, specify cert and verify options. ```python import requests JUPYTERHUB_API_URL = "https://hub.example.edu/hub/api" JUPYTERHUB_API_TOKEN = "token-from-env" # $JUPYTERHUB_API_TOKEN response = requests.post( f"{JUPYTERHUB_API_URL}/batchspawner", headers={"Authorization": f"token {JUPYTERHUB_API_TOKEN}"}, json={"port": 54321}, # For internal SSL: # cert=("/path/to/certfile", "/path/to/keyfile"), # verify="/path/to/client-ca.crt", ) # Expected: HTTP 201, body: {"message": "BatchSpawner data configured"} print(response.status_code, response.json()) ``` -------------------------------- ### Check JupyterHub Logs Source: https://context7.com/jupyterhub/batchspawner/llms.txt Use journalctl to view JupyterHub logs from the last 10 minutes, filtering for submission commands and batch script information. ```bash journalctl -u jupyterhub --since "10 minutes ago" | grep -E 'Spawner submit|batch_script' ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.