Exemple #1
0
 def __init__(self, easyconfigs):
     self.container_base = build_option('container_base')
     self.container_build_image = build_option('container_build_image')
     self.container_path = container_path()
     self.easyconfigs = easyconfigs
     self.image_format = build_option('container_image_format')
     self.img_name = build_option('container_image_name')
     self.log = fancylogger.getLogger(self.__class__.__name__, fname=False)
     self.mns = ActiveMNS()
     self.tmpdir = build_option('container_tmpdir')
Exemple #2
0
 def __init__(self, easyconfigs):
     self.container_base = build_option('container_base')
     self.container_build_image = build_option('container_build_image')
     self.container_path = container_path()
     self.easyconfigs = easyconfigs
     self.image_format = build_option('container_image_format')
     self.img_name = build_option('container_image_name')
     self.log = fancylogger.getLogger(self.__class__.__name__, fname=False)
     self.mns = ActiveMNS()
     self.tmpdir = build_option('container_tmpdir')
Exemple #3
0
def build_singularity_image(def_path):
    """Build Singularity container image by calling out to 'singularity' (requires admin privileges!)."""

    cont_path = container_path()
    def_file = os.path.basename(def_path)

    # use --imagename if specified, otherwise derive based on filename of recipe
    img_name = build_option('container_image_name')
    if img_name is None:
        # definition file Singularity.<app>-<version, container name <app>-<version>.<img|simg>
        img_name = def_file.split('.', 1)[1]

    cmd_opts = ''

    image_format = build_option('container_image_format')

    # squashfs image format (default for Singularity)
    if image_format in [None, CONT_IMAGE_FORMAT_SQUASHFS]:
        img_path = os.path.join(cont_path, img_name + '.simg')

    # ext3 image format, creating as writable container
    elif image_format == CONT_IMAGE_FORMAT_EXT3:
        img_path = os.path.join(cont_path, img_name + '.img')
        cmd_opts = '--writable'

    # sandbox image format, creates as a directory but acts like a container
    elif image_format == CONT_IMAGE_FORMAT_SANDBOX:
        img_path = os.path.join(cont_path, img_name)
        cmd_opts = '--sandbox'

    else:
        raise EasyBuildError("Unknown container image format specified for Singularity: %s" % image_format)

    if os.path.exists(img_path):
        if build_option('force'):
            print_msg("WARNING: overwriting existing container image at %s due to --force" % img_path)
            remove_file(img_path)
        else:
            raise EasyBuildError("Container image already exists at %s, not overwriting it without --force", img_path)

    # resolve full path to 'singularity' binary, since it may not be available via $PATH under sudo...
    singularity = which('singularity')
    cmd_env = ''

    singularity_tmpdir = build_option('container_tmpdir')
    if singularity_tmpdir:
        cmd_env += 'SINGULARITY_TMPDIR=%s' % singularity_tmpdir

    cmd = ' '.join(['sudo', cmd_env, singularity, 'build', cmd_opts, img_path, def_path])
    print_msg("Running '%s', you may need to enter your 'sudo' password..." % cmd)
    run_cmd(cmd, stream_output=True)
    print_msg("Singularity image created at %s" % img_path, log=_log)
Exemple #4
0
def generate_singularity_recipe(easyconfigs, container_base):
    """Main function to Singularity definition file and image."""

    cont_path = container_path()

    # make sure location to write container recipes & images exists
    mkdir(cont_path, parents=True)

    base_specs = parse_container_base(container_base)

    # extracting application name,version, version suffix, toolchain name, toolchain version from
    # easyconfig class

    bootstrap_agent = base_specs['bootstrap_agent']

    base_image, base_image_tag = None, None

    # with localimage it only takes 2 arguments. --container-base localimage:/path/to/image
    # checking if path to image is valid and verify image extension is '.img' or '.simg'
    if base_specs['bootstrap_agent'] == LOCALIMAGE:
        base_image = base_specs['arg1']
        if os.path.exists(base_image):
            # get the extension of container image
            image_ext = os.path.splitext(base_image)[1]
            if image_ext == '.img' or image_ext == '.simg':
                _log.debug("Extension for base container image to use is OK: %s", image_ext)
            else:
                raise EasyBuildError("Invalid image extension '%s' must be .img or .simg", image_ext)
        else:
            raise EasyBuildError("Singularity base image at specified path does not exist: %s", base_image)

    # otherwise, bootstrap agent is 'docker' or 'shub'
    # format --container-base {docker|shub}:<image>:<tag>
    else:
        base_image = base_specs['arg1']
        # image tag is optional
        base_image_tag = base_specs.get('arg2', None)

    bootstrap_from = base_image
    if base_image_tag:
        bootstrap_from += ':' + base_image_tag

    # if there is osdependencies in easyconfig then add them to Singularity recipe
    install_os_deps = ''
    for ec in easyconfigs:
        for osdep in ec['ec']['osdependencies']:
            if isinstance(osdep, basestring):
                install_os_deps += "yum install -y %s\n" % osdep
            # tuple entry indicates multiple options
            elif isinstance(osdep, tuple):
                install_os_deps += "yum --skip-broken -y install %s\n" % ' '.join(osdep)
            else:
                raise EasyBuildError("Unknown format of OS dependency specification encountered: %s", osdep)

    # module names to load in container environment
    mod_names = [e['ec'].full_mod_name for e in easyconfigs]

    # name of Singularity definition file
    img_name = build_option('container_image_name')
    if img_name:
        def_file_label = os.path.splitext(img_name)[0]
    else:
        def_file_label = mod_names[0].replace('/', '-')

    def_file = 'Singularity.%s' % def_file_label

    # adding all the regions for writing the  Singularity definition file
    content = SINGULARITY_TEMPLATE % {
        'bootstrap': bootstrap_agent,
        'from': bootstrap_from,
        'install_os_deps': install_os_deps,
        'easyconfigs': ' '.join(os.path.basename(e['spec']) for e in easyconfigs),
        'mod_names': ' '.join(mod_names),
    }
    def_path = os.path.join(cont_path, def_file)

    if os.path.exists(def_path):
        if build_option('force'):
            print_msg("WARNING: overwriting existing container recipe at %s due to --force" % def_path)
        else:
            raise EasyBuildError("Container recipe at %s already exists, not overwriting it without --force", def_path)

    write_file(def_path, content)
    print_msg("Singularity definition file created at %s" % def_path, log=_log)

    return def_path