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

Download: Get DSL2 singularity containers #832

Merged
merged 33 commits into from
Feb 8, 2021
Merged
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
70215b1
download: Scrape DSL2 style container addresses.
ewels Jan 20, 2021
36dbda7
Fix download filenames, bugtesting
ewels Jan 20, 2021
35317cf
Code refactor into smaller functions.
ewels Jan 21, 2021
616d913
Added overall progress bar for container downloads.
ewels Jan 21, 2021
1a7795f
Download progress bar tweaks
ewels Jan 21, 2021
5192e83
Download: fix tests
ewels Jan 21, 2021
4251df7
Download: image filenames cleaned à la Nextflow
ewels Jan 21, 2021
de071fd
Tidy up some logging
ewels Jan 21, 2021
d306bf2
Download: Add --force flag
ewels Jan 21, 2021
9610ef8
Few more log statements, simplify progress bar code a little
ewels Jan 22, 2021
f1de9ce
Download: Code refactor again.
ewels Jan 25, 2021
78d5b0d
Download singularity images in parallel
ewels Jan 25, 2021
b5c6ddc
Download: Use '.partial' extensions whilst downloading.
ewels Jan 25, 2021
625db05
Download: Fix tests
ewels Jan 25, 2021
7dd36f0
Download: Make ctrl-c work with multithreading
ewels Jan 31, 2021
a9e9258
Revert wait to as_completed
ewels Jan 31, 2021
ad4bc6b
Download: New --use_singularity_cache option
ewels Jan 31, 2021
aae3388
Download: add 'singularity.cacheDir' to workflow config for image paths.
ewels Feb 1, 2021
e469b94
Fix error with singularity_pull_image()
ewels Feb 1, 2021
d0e7cbc
Make singularity image directories if they don't already exist instea…
ewels Feb 1, 2021
04362e3
- not _ in cli flags, makedirs bugfix
ewels Feb 1, 2021
4a95a5b
Tidy up download cli options a little
ewels Feb 1, 2021
5bd1766
Download: Nicer logging for exceptions in download threads
ewels Feb 1, 2021
acdf5ba
Bugfix: Creating missing directories moved upstream
ewels Feb 1, 2021
c5173d4
Download: New docs and changelog
ewels Feb 1, 2021
503d75b
Changelog - link to PR
ewels Feb 1, 2021
6e943dc
Try to simplify exception handling for threaded downloads again
ewels Feb 1, 2021
154822b
Revert the download exception handling stuff as it was working before…
ewels Feb 1, 2021
0316fa0
Better verbose debug logging
ewels Feb 1, 2021
3e719a1
Minor refactor
ewels Feb 1, 2021
e28efa4
Download: Make logging for singularity-pull as pretty as for downloads
ewels Feb 1, 2021
62a37a7
fix tests
ewels Feb 1, 2021
e4a397e
Use Popen arg name for Python 3.6
ewels Feb 1, 2021
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
Prev Previous commit
Next Next commit
Download: New --use_singularity_cache option
  • Loading branch information
ewels committed Jan 31, 2021
commit ad4bc6b2c667ffb53e5b5f202bcb4f85f5ddff22
21 changes: 14 additions & 7 deletions nf_core/__main__.py
Original file line number Diff line number Diff line change
@@ -202,23 +202,30 @@ def launch(pipeline, id, revision, command_only, params_in, params_out, save_all
@nf_core_cli.command(help_priority=3)
@click.argument("pipeline", required=True, metavar="<pipeline name>")
@click.option("-r", "--release", type=str, help="Pipeline release")
@click.option("-s", "--singularity", is_flag=True, default=False, help="Download singularity containers")
@click.option("-s", "--singularity", is_flag=True, default=False, help="Download singularity images")
@click.option("-o", "--outdir", type=str, help="Output directory")
@click.option(
"-c",
"--compress",
type=click.Choice(["tar.gz", "tar.bz2", "zip", "none"]),
default="tar.gz",
help="Compression type",
help="Archive compression type",
)
@click.option("-f", "--force", is_flag=True, default=False, help="Overwrite existing files")
@click.option("-p", "--parallel_downloads", type=int, default=4, help="Number of parallel container downloads")
def download(pipeline, release, singularity, outdir, compress, force, parallel_downloads):
@click.option(
"-c",
"--use_singularity_cache",
is_flag=True,
default=False,
help="Don't copy images to the output directory and don't configure singularity.cacheDir",
)
@click.option("-p", "--parallel_downloads", type=int, default=4, help="Number of parallel image downloads")
def download(pipeline, release, singularity, outdir, compress, force, use_singularity_cache, parallel_downloads):
"""
Download a pipeline, configs and singularity container.
Download a pipeline, nf-core/configs and pipeline singularity images.

Collects all workflow files and shared configs from nf-core/configs.
Configures the downloaded workflow to use the relative path to the configs.
Collects all files in a single archive and configures the downloaded
workflow to use relative paths to the configs and singularity images.
"""
dl = nf_core.download.DownloadWorkflow(pipeline, release, singularity, outdir, compress, force, parallel_downloads)
dl.download_workflow()
33 changes: 27 additions & 6 deletions nf_core/download.py
Original file line number Diff line number Diff line change
@@ -73,6 +73,7 @@ def __init__(
outdir=None,
compress_type="tar.gz",
force=False,
use_singularity_cache=False,
parallel_downloads=4,
):
self.pipeline = pipeline
@@ -84,6 +85,7 @@ def __init__(
if self.compress_type == "none":
self.compress_type = None
self.force = force
self.use_singularity_cache = use_singularity_cache
self.parallel_downloads = parallel_downloads

self.wf_name = None
@@ -339,7 +341,8 @@ def get_singularity_images(self):
if len(self.containers) == 0:
log.info("No container names found in workflow")
else:
os.mkdir(os.path.join(self.outdir, "singularity-images"))
if not self.use_singularity_cache:
os.mkdir(os.path.join(self.outdir, "singularity-images"))
if not os.environ.get("NXF_SINGULARITY_CACHEDIR"):
log.info(
"[magenta]Tip: Set env var $NXF_SINGULARITY_CACHEDIR to use a central cache for container downloads"
@@ -401,8 +404,10 @@ def get_singularity_images(self):
try:
# Iterate over each threaded download, waiting for them to finish
for future in concurrent.futures.as_completed(future_downloads):
if future.exception():
raise future.exception()
try:
future.result()
except Exception:
raise
else:
progress.update(task, advance=1)

@@ -464,6 +469,12 @@ def singularity_image_filenames(self, container):
cache_path = None
if os.environ.get("NXF_SINGULARITY_CACHEDIR"):
cache_path = os.path.join(os.environ["NXF_SINGULARITY_CACHEDIR"], out_name)
# Use only the cache - set this as the main output path
if self.use_singularity_cache:
out_path = cache_path
cache_path = None
elif self.use_singularity_cache:
raise FileNotFoundError("'--use_singularity_cache' specified but no $NXF_SINGULARITY_CACHEDIR set!")

return (out_path, cache_path)

@@ -487,6 +498,14 @@ def singularity_download_image(self, container, out_path, cache_path, progress):
progress (Progress): Rich progress bar instance to add tasks to.
"""
log.debug(f"Downloading Singularity image: '{container}'")

# Check that download directories exist
if not os.path.isdir(os.path.dirname(out_path)):
raise FileNotFoundError("Output directory not found: '{}'".format(os.path.dirname(out_path)))
if cache_path and not os.path.isdir(os.path.dirname(cache_path)):
raise FileNotFoundError("Output directory not found: '{}'".format(os.path.dirname(cache_path)))

# Set output path to save file to
output_path = cache_path or out_path
output_path_tmp = None

@@ -534,9 +553,11 @@ def singularity_download_image(self, container, out_path, cache_path, progress):
for t in progress.task_ids:
progress.remove_task(t)
# Try to delete the incomplete download
log.warning(f"Deleting incompleted singularity image download:\n'{output_path_tmp}'")
os.remove(output_path_tmp)
os.remove(output_path)
log.debug(f"Deleting incompleted singularity image download:\n'{output_path_tmp}'")
if output_path_tmp and os.path.exists(output_path_tmp):
os.remove(output_path_tmp)
if output_path and os.path.exists(output_path):
os.remove(output_path)
# Re-raise the caught exception
raise