示例#1
0
def avail_job_backends(check_usable=True):
    """
    Return all known job execution backends.
    """
    import_available_modules('easybuild.tools.job')
    class_dict = dict([(x.__name__, x) for x in get_subclasses(JobBackend)])
    return class_dict
示例#2
0
def avail_job_backends(check_usable=True):
    """
    Return all known job execution backends.
    """
    import_available_modules('easybuild.tools.job')
    class_dict = dict([(x.__name__, x) for x in get_subclasses(JobBackend)])
    return class_dict
示例#3
0
def get_convert_class(class_name):
    """Return the Convert class with specified class name class_name"""
    res = [x for x in nub(get_subclasses(Convert)) if x.__name__ == class_name]
    if len(res) == 1:
        return res[0]
    else:
        _log.error('More then one Convert subclass found for name %s: %s' % (class_name, res))
示例#4
0
def what_sched(requested):
    """Return the scheduler class """

    def sched_to_key(klass):
        """Return key for specified scheduler class which can be used for sorting."""
        # use lowercase class name for sorting
        key = klass.__name__.lower()
        # prefix key for SLURM scheduler class with '_'
        # this is done to consider SLURM before PBS, since $PBS* environment variables may be defined in SLURM job env
        if key == 'slurm':
            key = '_' + key

        return key

    # exclude Coupler class which also is a subclass of Sched, since it's not an actual scheduler
    found_sched = sorted([c for c in get_subclasses(Sched) if c.__name__ != 'Coupler'], key=sched_to_key)

    # Get local scheduler
    local_sched = get_local_sched(found_sched)

    # first, try to use the scheduler that was requested
    if requested:
        for sched in found_sched:
            if sched._is_sched_for(requested):
                return sched, found_sched
        LOGGER.warn("%s scheduler was requested, but mympirun failed to find an implementation", requested)

    # next, try to use the scheduler defined by environment variables
    for sched in found_sched:
        if sched.SCHED_ENVIRON_NODE_INFO in os.environ and sched.SCHED_ENVIRON_ID in os.environ:
            return sched, found_sched

    # If that fails, try to force the local scheduler
    LOGGER.debug("No scheduler found in environment, trying local")
    return local_sched, found_sched
示例#5
0
def get_convert_class(class_name):
    """Return the Convert class with specified class name class_name"""
    res = [x for x in nub(get_subclasses(Convert)) if x.__name__ == class_name]
    if len(res) == 1:
        return res[0]
    else:
        _log.error('More then one Convert subclass found for name %s: %s' % (class_name, res))
示例#6
0
def get_convert_class(class_name):
    """Return the Convert class with specified class name class_name"""
    res = [x for x in nub(get_subclasses(Convert)) if x.__name__ == class_name]
    if len(res) == 1:
        return res[0]
    else:
        raise EasyBuildError("More than one Convert subclass found for name %s: %s", class_name, res)
示例#7
0
def whatMPI(name):
    """
    Return the scriptname and the MPI class
    """
    fullscriptname = os.path.abspath(name)
    scriptname = os.path.basename(fullscriptname)

    found_mpi = get_subclasses(MPI)

    # check on scriptname
    for mpi in found_mpi:
        if mpi._is_mpiscriptname_for(scriptname):
            stripfake()  # mandatory before return at this point
            return scriptname, mpi, found_mpi

    # not called through alias
    # stripfake is in which
    mpirunname = which(['mpirun'])
    if mpirunname is None:
        return None, None, found_mpi

    for mpi in found_mpi:
        if mpi._is_mpirun_for(mpirunname):
            return scriptname, mpi, found_mpi

    # return found mpirunname
    return mpirunname, None, found_mpi
示例#8
0
    def pingpongfactory(pptype, comm, p, log):
        """a factory for creating PingPong objects"""

        for cls in get_subclasses(PingPongSR, include_base_class=True):
            if "PingPong%s" % pptype == cls.__name__:
                return cls(comm, p, log)
        raise KeyError
示例#9
0
def what_sched(requested):
    """Return the scheduler class """

    # import all modules in this dir: http://stackoverflow.com/a/16853487
    for loader, modulename, _ in pkgutil.walk_packages(
        [os.path.dirname(__file__)]):
        loader.find_module(modulename).load_module(modulename)

    found_sched = get_subclasses(Sched)

    # first, try to use the scheduler that was requested
    if requested:
        for sched in found_sched:
            if sched._is_sched_for(requested):
                return sched, found_sched
        LOGGER.warn(
            "%s scheduler was requested, but mympirun failed to find an implementation",
            requested)

    # next, try to use the scheduler defined by environment variables
    for sched in found_sched:
        if sched.SCHED_ENVIRON_ID in os.environ:
            return sched, found_sched

    # If that fails, try to force the local scheduler
    for sched in found_sched:
        LOGGER.debug("No scheduler found in environment, trying local")
        if sched._is_sched_for("local"):
            return sched, found_sched

    # if there is no local scheduler, return None
    return None, found_sched
示例#10
0
def what_sched(requested):
    """Return the scheduler class """

    # import all modules in this dir: http://stackoverflow.com/a/16853487
    for loader, modulename, _ in pkgutil.walk_packages([os.path.dirname(__file__)]):
        loader.find_module(modulename).load_module(modulename)

    found_sched = get_subclasses(Sched)

    # first, try to use the scheduler that was requested
    if requested:
        for sched in found_sched:
            if sched._is_sched_for(requested):
                return sched, found_sched
        LOGGER.warn("%s scheduler was requested, but mympirun failed to find an implementation", requested)

    # next, try to use the scheduler defined by environment variables
    for sched in found_sched:
        if sched.SCHED_ENVIRON_ID in os.environ:
            return sched, found_sched

    # If that fails, try to force the local scheduler
    for sched in found_sched:
        LOGGER.debug("No scheduler found in environment, trying local")
        if sched._is_sched_for("local"):
            return sched, found_sched


    # if there is no local scheduler, return None
    return None, found_sched
示例#11
0
def whatMPI(name):
    """
    Return the scriptname and the MPI class
    """
    fullscriptname = os.path.abspath(name)
    scriptname = os.path.basename(fullscriptname)

    found_mpi = get_subclasses(MPI)

    # check on scriptname
    for mpi in found_mpi:
        if mpi._is_mpiscriptname_for(scriptname):
            stripfake()  # mandatory before return at this point
            return scriptname, mpi, found_mpi

    # not called through alias
    # stripfake is in which
    mpirunname = which(['mpirun'])
    if mpirunname is None:
        return None, None, found_mpi

    for mpi in found_mpi:
        if mpi._is_mpirun_for(mpirunname):
            return scriptname, mpi, found_mpi

    # return found mpirunname
    return mpirunname, None, found_mpi
示例#12
0
def get_format_version_classes(version=None):
    """Return the (usable) subclasses from EasyConfigFormat that have a matching version."""
    all_classes = get_subclasses(EasyConfigFormat)
    if version is None:
        return all_classes
    else:
        return [x for x in all_classes if x.VERSION == version and x.USABLE]
def avail_package_naming_schemes():
    """
    Returns the list of valed naming schemes that are in the easybuild.package.package_naming_scheme namespace
    """
    import_available_modules('easybuild.tools.package.package_naming_scheme')
    class_dict = dict([(x.__name__, x) for x in get_subclasses(PackageNamingScheme)])
    return class_dict
示例#14
0
def search_toolchain(name):
    """
    Obtain a Toolchain instance for the toolchain with specified name, next to a list of available toolchains.
    :param name: toolchain name
    :return: Toolchain instance (or None), found_toolchains
    """

    package = easybuild.tools.toolchain
    check_attr_name = '%s_PROCESSED' % TC_CONST_PREFIX

    if not hasattr(package, check_attr_name) or not getattr(package, check_attr_name):
        # import all available toolchains, so we know about them
        tc_modules = import_available_modules('easybuild.toolchains')

        # make sure all defined toolchain constants are available in toolchain module
        tc_const_re = re.compile('^%s(.*)$' % TC_CONST_PREFIX)
        for tc_mod in tc_modules:
            # determine classes imported in this module
            mod_classes = []
            for elem in [getattr(tc_mod, x) for x in dir(tc_mod)]:
                if hasattr(elem, '__module__'):
                    # exclude the toolchain class defined in that module
                    if not tc_mod.__file__ == sys.modules[elem.__module__].__file__:
                        _log.debug("Adding %s to list of imported classes used for looking for constants" % elem.__name__)
                        mod_classes.append(elem)

            # look for constants in modules of imported classes, and make them available
            for mod_class_mod in [sys.modules[mod_class.__module__] for mod_class in mod_classes]:
                for elem in dir(mod_class_mod):
                    res = tc_const_re.match(elem)
                    if res:
                        tc_const_name = res.group(1)
                        tc_const_value = getattr(mod_class_mod, elem)
                        _log.debug("Found constant %s ('%s') in module %s, adding it to %s",
                                   tc_const_name, tc_const_value, mod_class_mod.__name__, package.__name__)
                        if hasattr(package, tc_const_name):
                            cur_value = getattr(package, tc_const_name)
                            if not tc_const_value == cur_value:
                                raise EasyBuildError("Constant %s.%s defined as '%s', can't set it to '%s'.",
                                                     package.__name__, tc_const_name, cur_value, tc_const_value)
                        else:
                            setattr(package, tc_const_name, tc_const_value)

        # indicate that processing of toolchain constants is done, so it's not done again
        setattr(package, check_attr_name, True)
    else:
        _log.debug("Skipping importing of toolchain modules, processing of toolchain constants is already done.")

    # obtain all subclasses of toolchain
    found_tcs = nub(get_subclasses(Toolchain))

    # filter found toolchain subclasses based on whether they can be used a toolchains
    found_tcs = [tc for tc in found_tcs if tc._is_toolchain_for(None)]

    for tc in found_tcs:
        if tc._is_toolchain_for(name):
            return tc, found_tcs

    return None, found_tcs
示例#15
0
    def pairfactory(pairmode, seed=None, rng=None, pairid=None, logger=None):
        """A factory for creating Pair objects"""

        logger.debug("in pairfactory with pairmode %s", pairmode)
        for cls in get_subclasses(Pair, include_base_class=True):
            if pairmode == cls.__name__.lower():
                return cls(seed, rng, pairid, logger)
        raise KeyError
示例#16
0
def get_convert_class(class_name):
    """Return the Convert class with specified class name class_name"""
    res = [x for x in nub(get_subclasses(Convert)) if x.__name__ == class_name]
    if len(res) == 1:
        return res[0]
    else:
        raise EasyBuildError(
            "More than one Convert subclass found for name %s: %s", class_name,
            res)
示例#17
0
def avail_modules_tools():
    """
    Return all known modules tools.
    """
    class_dict = dict([(x.__name__, x) for x in get_subclasses(ModulesTool)])
    # filter out legacy Modules class
    if 'Modules' in class_dict:
        del class_dict['Modules']
    return class_dict
def avail_modules_tools():
    """
    Return all known modules tools.
    """
    class_dict = dict([(x.__name__, x) for x in get_subclasses(ModulesTool)])
    # filter out legacy Modules class
    if 'Modules' in class_dict:
        del class_dict['Modules']
    return class_dict
示例#19
0
def what_licenses():
    """Return a dict of License subclasses names and license instances"""
    res = {}
    for lic in get_subclasses(License):
        if lic.HIDDEN:
            continue
        res[lic.__name__] = lic

    return res
示例#20
0
    def get_job(classname, options):
        """
        This is a job factory.

        Returns an instance of classname initialized with options
        """
        for cls in get_subclasses(Job):
            if cls._is_job_for(classname):
                return cls(options)
        getLogger().error("No job class found for %s", classname)
示例#21
0
    def get_job(classname, options):
        """
        This is a job factory.

        Returns an instance of classname initialized with options
        """
        for cls in get_subclasses(Job):
            if cls._is_job_for(classname):
                return cls(options)
        getLogger().error("No job class found for %s", classname)
示例#22
0
def avail_module_naming_schemes():
    """
    Returns a list of available module naming schemes.
    """
    # all ModuleNamingScheme subclasses available in easybuild.tools.module_naming_scheme namespace are eligible
    import_available_modules('easybuild.tools.module_naming_scheme')

    # construct name-to-class dict of available module naming scheme
    avail_mnss = dict([(x.__name__, x) for x in get_subclasses(ModuleNamingScheme)])

    return avail_mnss
示例#23
0
def avail_module_naming_schemes():
    """
    Returns a list of available module naming schemes.
    """
    # all ModuleNamingScheme subclasses available in easybuild.tools.module_naming_scheme namespace are eligible
    import_available_modules('easybuild.tools.module_naming_scheme')

    # construct name-to-class dict of available module naming scheme
    avail_mnss = dict([(x.__name__, x) for x in get_subclasses(ModuleNamingScheme)])

    return avail_mnss
def avail_repositories(check_useable=True):
    """
    Return all available repositories.
        check_useable: boolean, if True, only return usable repositories
    """
    class_dict = dict([(x.__name__, x) for x in get_subclasses(Repository) if x.USABLE or not check_useable])

    if not 'FileRepository' in class_dict:
        _log.error('avail_repositories: FileRepository missing from list of repositories')

    return class_dict
示例#25
0
def avail_repositories(check_useable=True):
    """
    Return all available repositories.
        check_useable: boolean, if True, only return usable repositories
    """
    import_available_modules('easybuild.tools.repository')

    class_dict = dict([(x.__name__, x) for x in get_subclasses(Repository) if x.USABLE or not check_useable])

    if not 'FileRepository' in class_dict:
        raise EasyBuildError("avail_repositories: FileRepository missing from list of repositories")

    return class_dict
示例#26
0
    def test_mympirun_aliases_setup(self):
        """Make sure that list of mympirun aliases included in setup.py is synced"""
        from setup import MYMPIRUN_ALIASES

        # make sure all modules in vsc.mympirun.mpi are imported
        for loader, modname, _ in pkgutil.walk_packages([os.path.dirname(mpim.__file__)]):
            loader.find_module(modname).load_module(modname)

        # determine actual list of mympirun aliases
        mympirun_aliases = ['myscoop']
        for mpiclass in get_subclasses(mpim.MPI):
            mympirun_aliases.extend(mpiclass._mpiscriptname_for)

        self.assertEqual(MYMPIRUN_ALIASES, nub(sorted(mympirun_aliases)))
示例#27
0
def what_mpi(name):
    """
    Return the path of the selected mpirun and its class.

    @param name: The name of the executable used to run mympirun

    @return: A triplet containing the following variables:
      - The path to the executable used to run mympirun (should be the path to an mpirun implementation)
      - The corresponding python class of the MPI variant
      - The python classes of the supported MPI flavors (from the various .py files in mympirun/mpi)
    """

    # import all modules in this dir: http://stackoverflow.com/a/16853487
    for loader, modulename, _ in pkgutil.walk_packages([os.path.dirname(__file__)]):
        loader.find_module(modulename).load_module(modulename)

    supp_mpi_impl = get_subclasses(MPI)  # supported MPI implementations

    # remove fake mpirun from $PATH
    stripfake()

    # get the path of the mpirun executable
    mpirun_path = which('mpirun')
    if mpirun_path is None:
        # no MPI implementation installed
        LOGGER.warn("no mpirun command found")
        return None, None, supp_mpi_impl

    scriptname = os.path.basename(os.path.abspath(name))

    # check if mympirun was called by a known mpirun alias (like
    # ompirun for OpenMPI or mhmpirun for mpich)
    for mpi in supp_mpi_impl:
        if mpi._is_mpiscriptname_for(scriptname):
            LOGGER.debug("%s was used to call mympirun", scriptname)
            return scriptname, mpi, supp_mpi_impl

    # mympirun was not called through a known alias, so find out which MPI
    # implementation the user has installed
    for mpi in supp_mpi_impl:
        if mpi._is_mpirun_for(mpirun_path):
            return scriptname, mpi, supp_mpi_impl

    # no specific flavor found, default to mpirun_path
    LOGGER.warn("The executable that called mympirun (%s) isn't supported"
                ", defaulting to %s", name, mpirun_path)
    return mpirun_path, None, supp_mpi_impl
def avail_module_naming_schemes():
    """
    Returns a list of available module naming schemes.
    """
    mns_attr = 'AVAIL_MODULE_NAMING_SCHEMES'
    if not hasattr(module_naming_scheme, mns_attr):
        # all subclasses of ModuleNamingScheme available in the easybuild.tools.module_naming_scheme namespace are eligible
        import_available_modules('easybuild.tools.module_naming_scheme')

        # construct name-to-class dict of available module naming scheme
        avail_mnss = dict([(x.__name__, x) for x in get_subclasses(ModuleNamingScheme)])

        # cache dict of available module naming scheme in module constant
        setattr(module_naming_scheme, mns_attr, avail_mnss)
        return avail_mnss
    else:
        return getattr(module_naming_scheme, mns_attr)
def avail_module_naming_schemes():
    """
    Returns a list of available module naming schemes.
    """
    mns_attr = 'AVAIL_MODULE_NAMING_SCHEMES'
    if not hasattr(module_naming_scheme, mns_attr):
        # all subclasses of ModuleNamingScheme available in the easybuild.tools.module_naming_scheme namespace are eligible
        import_available_modules('easybuild.tools.module_naming_scheme')

        # construct name-to-class dict of available module naming scheme
        avail_mnss = dict([(x.__name__, x)
                           for x in get_subclasses(ModuleNamingScheme)])

        # cache dict of available module naming scheme in module constant
        setattr(module_naming_scheme, mns_attr, avail_mnss)
        return avail_mnss
    else:
        return getattr(module_naming_scheme, mns_attr)
示例#30
0
def what_mpi(name):
    """
    Return the path of the selected mpirun and its class.

    @param name: The name of the executable used to run mympirun

    @return: A triplet containing the following variables:
      - The path to the executable used to run mympirun (should be the path to an mpirun implementation)
      - The corresponding python class of the MPI variant
      - The python classes of the supported MPI flavors (from the various .py files in mympirun/mpi)
    """

    # The coupler is also a subclass of MPI, but it isn't and MPI implementation
    supp_mpi_impl = [x for x in get_subclasses(MPI) if x.__name__ != 'Coupler']  # supported MPI implementations

    # remove fake mpirun from $PATH
    stripfake()

    # get the path of the mpirun executable
    mpirun_path = which('mpirun')
    if mpirun_path is None:
        # no MPI implementation installed
        LOGGER.warn("no mpirun command found")
        return None, None, supp_mpi_impl

    scriptname = os.path.basename(os.path.abspath(name))

    # check if mympirun was called by a known mpirun alias (like
    # ompirun for OpenMPI or mhmpirun for mpich)
    for mpi in supp_mpi_impl:
        if mpi._is_mpiscriptname_for(scriptname) and mpi._is_mpirun_for(mpirun_path):
            LOGGER.debug("%s was used to call mympirun", scriptname)
            return scriptname, mpi, supp_mpi_impl

    # mympirun was not called through a known alias, so find out which MPI
    # implementation the user has installed
    for mpi in supp_mpi_impl:
        if mpi._is_mpirun_for(mpirun_path):
            return scriptname, mpi, supp_mpi_impl

    # no specific flavor found, default to mpirun_path
    LOGGER.warn("The executable that called mympirun (%s) isn't supported, defaulting to %s", name, mpirun_path)
    return mpirun_path, None, supp_mpi_impl
def avail_module_generators():
    """
    Return all known module syntaxes.
    """
    return dict([(k.SYNTAX, k) for k in get_subclasses(ModuleGenerator)])
    def test_module_naming_scheme(self):
        """Test using default module naming scheme."""
        all_stops = [x[0] for x in EasyBlock.get_steps()]
        init_config(build_options={'valid_stops': all_stops})

        ecs_dir = os.path.join(os.path.dirname(__file__), 'easyconfigs')
        ec_files = [os.path.join(subdir, fil) for (subdir, _, files) in os.walk(ecs_dir) for fil in files]
        ec_files = [fil for fil in ec_files if not "v2.0" in fil]  # TODO FIXME: drop this once 2.0 support works

        build_options = {
            'check_osdeps': False,
            'robot_path': [ecs_dir],
            'valid_stops': all_stops,
            'validate': False,
        }
        init_config(build_options=build_options)

        def test_mns():
            """Test default module naming scheme."""
            # test default naming scheme
            for ec_file in ec_files:
                ec_path = os.path.abspath(ec_file)
                ecs = process_easyconfig(ec_path, validate=False)
                # derive module name directly from easyconfig file name
                ec_fn = os.path.basename(ec_file)
                if ec_fn in ec2mod_map:
                    # only check first, ignore any others (occurs when blocks are used (format v1.0 only))
                    self.assertEqual(ec2mod_map[ec_fn], det_full_module_name_mg(ecs[0]['ec']))

        # test default module naming scheme
        default_ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/4.6.3',
            'gzip-1.4.eb': 'gzip/1.4',
            'gzip-1.4-GCC-4.6.3.eb': 'gzip/1.4-GCC-4.6.3',
            'gzip-1.5-goolf-1.4.10.eb': 'gzip/1.5-goolf-1.4.10',
            'gzip-1.5-ictce-4.1.13.eb': 'gzip/1.5-ictce-4.1.13',
            'toy-0.0.eb': 'toy/0.0',
            'toy-0.0-multiple.eb': 'toy/0.0-somesuffix',  # first block sets versionsuffix to '-somesuffix'
        }
        ec2mod_map = default_ec2mod_map
        test_mns()

        # generating module name from non-parsed easyconfig works fine
        non_parsed = {
            'name': 'foo',
            'version': '1.2.3',
            'versionsuffix': '-bar',
            'toolchain': {
                'name': 't00ls',
                'version': '6.6.6',
            },
        }
        self.assertEqual('foo/1.2.3-t00ls-6.6.6-bar', det_full_module_name_ec(non_parsed))

        # install custom module naming scheme dynamically
        test_mns_parent_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'sandbox')
        sys.path.append(test_mns_parent_dir)
        reload(easybuild)
        reload(easybuild.tools)
        reload(easybuild.tools.module_naming_scheme)

        # make sure test module naming schemes are available
        for test_mns_mod in ['test_module_naming_scheme', 'test_module_naming_scheme_all']:
            mns_path = "easybuild.tools.module_naming_scheme.%s" % test_mns_mod
            mns_mod = __import__(mns_path, globals(), locals(), [''])
            test_mnss = dict([(x.__name__, x) for x in get_subclasses(mns_mod.ModuleNamingScheme)])
            easybuild.tools.module_naming_scheme.AVAIL_MODULE_NAMING_SCHEMES.update(test_mnss)
        init_config(build_options=build_options)

        # test simple custom module naming scheme
        os.environ['EASYBUILD_MODULE_NAMING_SCHEME'] = 'TestModuleNamingScheme'
        init_config(build_options=build_options)
        ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/4.6.3',
            'gzip-1.4.eb': 'gzip/1.4',
            'gzip-1.4-GCC-4.6.3.eb': 'gnu/gzip/1.4',
            'gzip-1.5-goolf-1.4.10.eb': 'gnu/openmpi/gzip/1.5',
            'gzip-1.5-ictce-4.1.13.eb': 'intel/intelmpi/gzip/1.5',
            'toy-0.0.eb': 'toy/0.0',
            'toy-0.0-multiple.eb': 'toy/0.0',  # test module naming scheme ignores version suffixes
        }
        test_mns()

        # test module naming scheme using all available easyconfig parameters
        os.environ['EASYBUILD_MODULE_NAMING_SCHEME'] = 'TestModuleNamingSchemeAll'
        init_config(build_options=build_options)
        # note: these checksums will change if another easyconfig parameter is added
        ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/698cacc77167c6824f597f0b6371cad5e6749922',
            'gzip-1.4.eb': 'gzip/d240a51c643ec42e709d405d958c7b26f5a25d5a',
            'gzip-1.4-GCC-4.6.3.eb': 'gzip/cea02d332af7044ae5faf762cea2ef6ffed014d2',
            'gzip-1.5-goolf-1.4.10.eb': 'gzip/f1dbb38c4518a15fc8bb1fbf797ceda02f0cacd0',
            'gzip-1.5-ictce-4.1.13.eb': 'gzip/3ef9ac73b468c989f5a47b30098d340e92c3d0da',
            'toy-0.0.eb': 'toy/778417f0e140ebbaebd60d0f98c8b2411f980edf',
            'toy-0.0-multiple.eb': 'toy/2d45f3cde87dedf30662f4a005023d56d2532bf0',
        }
        test_mns()

        # test determining module name for dependencies (i.e. non-parsed easyconfigs)
        # using a module naming scheme that requires all easyconfig parameters
        for dep_ec, dep_spec in [
            ('GCC-4.6.3.eb', {
                'name': 'GCC',
                'version': '4.6.3',
                'versionsuffix': '',
                'toolchain': {'name': 'dummy', 'version': 'dummy'},
            }),
            ('gzip-1.5-goolf-1.4.10.eb', {
                'name': 'gzip',
                'version': '1.5',
                'versionsuffix': '',
                'toolchain': {'name': 'goolf', 'version': '1.4.10'},
            }),
            ('toy-0.0-multiple.eb', {
                'name': 'toy',
                'version': '0.0',
                'versionsuffix': '-multiple',
                'toolchain': {'name': 'dummy', 'version': 'dummy'},
            }),
        ]:
            self.assertEqual(det_full_module_name_ec(dep_spec), ec2mod_map[dep_ec])

        # restore default module naming scheme, and retest
        os.environ['EASYBUILD_MODULE_NAMING_SCHEME'] = self.orig_module_naming_scheme
        init_config(build_options=build_options)
        ec2mod_map = default_ec2mod_map
        test_mns()
    def test_module_naming_scheme(self):
        """Test using default module naming scheme."""
        all_stops = [x[0] for x in EasyBlock.get_steps()]
        init_config(build_options={'valid_stops': all_stops})

        ecs_dir = os.path.join(os.path.dirname(__file__), 'easyconfigs')
        ec_files = [
            os.path.join(subdir, fil)
            for (subdir, _, files) in os.walk(ecs_dir) for fil in files
        ]
        ec_files = [fil for fil in ec_files if not "v2.0" in fil
                    ]  # TODO FIXME: drop this once 2.0 support works

        build_options = {
            'check_osdeps': False,
            'robot_path': [ecs_dir],
            'valid_stops': all_stops,
            'validate': False,
        }
        init_config(build_options=build_options)

        def test_mns():
            """Test default module naming scheme."""
            # test default naming scheme
            for ec_file in ec_files:
                ec_path = os.path.abspath(ec_file)
                ecs = process_easyconfig(ec_path, validate=False)
                # derive module name directly from easyconfig file name
                ec_fn = os.path.basename(ec_file)
                if ec_fn in ec2mod_map:
                    # only check first, ignore any others (occurs when blocks are used (format v1.0 only))
                    self.assertEqual(ec2mod_map[ec_fn],
                                     det_full_module_name_mg(ecs[0]['ec']))

        # test default module naming scheme
        default_ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/4.6.3',
            'gzip-1.4.eb': 'gzip/1.4',
            'gzip-1.4-GCC-4.6.3.eb': 'gzip/1.4-GCC-4.6.3',
            'gzip-1.5-goolf-1.4.10.eb': 'gzip/1.5-goolf-1.4.10',
            'gzip-1.5-ictce-4.1.13.eb': 'gzip/1.5-ictce-4.1.13',
            'toy-0.0.eb': 'toy/0.0',
            'toy-0.0-multiple.eb':
            'toy/0.0-somesuffix',  # first block sets versionsuffix to '-somesuffix'
        }
        ec2mod_map = default_ec2mod_map
        test_mns()

        # generating module name from non-parsed easyconfig works fine
        non_parsed = {
            'name': 'foo',
            'version': '1.2.3',
            'versionsuffix': '-bar',
            'toolchain': {
                'name': 't00ls',
                'version': '6.6.6',
            },
        }
        self.assertEqual('foo/1.2.3-t00ls-6.6.6-bar',
                         det_full_module_name_ec(non_parsed))

        # install custom module naming scheme dynamically
        test_mns_parent_dir = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'sandbox')
        sys.path.append(test_mns_parent_dir)
        reload(easybuild)
        reload(easybuild.tools)
        reload(easybuild.tools.module_naming_scheme)

        # make sure test module naming schemes are available
        for test_mns_mod in [
                'test_module_naming_scheme', 'test_module_naming_scheme_all'
        ]:
            mns_path = "easybuild.tools.module_naming_scheme.%s" % test_mns_mod
            mns_mod = __import__(mns_path, globals(), locals(), [''])
            test_mnss = dict([
                (x.__name__, x)
                for x in get_subclasses(mns_mod.ModuleNamingScheme)
            ])
            easybuild.tools.module_naming_scheme.AVAIL_MODULE_NAMING_SCHEMES.update(
                test_mnss)
        init_config(build_options=build_options)

        # test simple custom module naming scheme
        os.environ['EASYBUILD_MODULE_NAMING_SCHEME'] = 'TestModuleNamingScheme'
        init_config(build_options=build_options)
        ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/4.6.3',
            'gzip-1.4.eb': 'gzip/1.4',
            'gzip-1.4-GCC-4.6.3.eb': 'gnu/gzip/1.4',
            'gzip-1.5-goolf-1.4.10.eb': 'gnu/openmpi/gzip/1.5',
            'gzip-1.5-ictce-4.1.13.eb': 'intel/intelmpi/gzip/1.5',
            'toy-0.0.eb': 'toy/0.0',
            'toy-0.0-multiple.eb':
            'toy/0.0',  # test module naming scheme ignores version suffixes
        }
        test_mns()

        # test module naming scheme using all available easyconfig parameters
        os.environ[
            'EASYBUILD_MODULE_NAMING_SCHEME'] = 'TestModuleNamingSchemeAll'
        init_config(build_options=build_options)
        # note: these checksums will change if another easyconfig parameter is added
        ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/698cacc77167c6824f597f0b6371cad5e6749922',
            'gzip-1.4.eb': 'gzip/d240a51c643ec42e709d405d958c7b26f5a25d5a',
            'gzip-1.4-GCC-4.6.3.eb':
            'gzip/cea02d332af7044ae5faf762cea2ef6ffed014d2',
            'gzip-1.5-goolf-1.4.10.eb':
            'gzip/f1dbb38c4518a15fc8bb1fbf797ceda02f0cacd0',
            'gzip-1.5-ictce-4.1.13.eb':
            'gzip/3ef9ac73b468c989f5a47b30098d340e92c3d0da',
            'toy-0.0.eb': 'toy/778417f0e140ebbaebd60d0f98c8b2411f980edf',
            'toy-0.0-multiple.eb':
            'toy/2d45f3cde87dedf30662f4a005023d56d2532bf0',
        }
        test_mns()

        # test determining module name for dependencies (i.e. non-parsed easyconfigs)
        # using a module naming scheme that requires all easyconfig parameters
        for dep_ec, dep_spec in [
            ('GCC-4.6.3.eb', {
                'name': 'GCC',
                'version': '4.6.3',
                'versionsuffix': '',
                'toolchain': {
                    'name': 'dummy',
                    'version': 'dummy'
                },
            }),
            ('gzip-1.5-goolf-1.4.10.eb', {
                'name': 'gzip',
                'version': '1.5',
                'versionsuffix': '',
                'toolchain': {
                    'name': 'goolf',
                    'version': '1.4.10'
                },
            }),
            ('toy-0.0-multiple.eb', {
                'name': 'toy',
                'version': '0.0',
                'versionsuffix': '-multiple',
                'toolchain': {
                    'name': 'dummy',
                    'version': 'dummy'
                },
            }),
        ]:
            self.assertEqual(det_full_module_name_ec(dep_spec),
                             ec2mod_map[dep_ec])

        # restore default module naming scheme, and retest
        os.environ[
            'EASYBUILD_MODULE_NAMING_SCHEME'] = self.orig_module_naming_scheme
        init_config(build_options=build_options)
        ec2mod_map = default_ec2mod_map
        test_mns()
示例#34
0
def search_toolchain(name):
    """
    Find a toolchain with matching name
    returns toolchain (or None), found_toolchains
    """

    log = fancylogger.getLogger("search_toolchain")

    # import all available toolchains, so we know about them
    tc_modules = []
    for path in sys.path:
        for module in glob.glob(os.path.join(path, 'easybuild', 'toolchains', '*.py')):
            if not module.endswith('__init__.py'):
                modpath = "easybuild.toolchains.%s" % module.split(os.path.sep)[-1].split('.')[0]
                log.debug("importing toolchain module %s" % modpath)
                tc_modules.append(__import__(modpath, globals(), locals(), ['']))

    # make sure all defined toolchain constants are available in toolchain module
    package = easybuild.tools.toolchain
    tc_const_prefix = 'TC_CONSTANT_'
    tc_const_re = re.compile('^%s(.*)$' % tc_const_prefix)
    for tc_mod in tc_modules:
        # determine classes imported in this module
        mod_classes = []
        for elem in [getattr(tc_mod, x) for x in dir(tc_mod)]:
            if hasattr(elem, '__module__'):
                # exclude the toolchain class defined in that module
                if not tc_mod.__file__ == sys.modules[elem.__module__].__file__:
                    log.debug("Adding %s to list of imported classes used for looking for constants" % elem.__name__)
                    mod_classes.append(elem)

        # look for constants in modules of imported classes, and make them available
        for mod_class_mod in [sys.modules[mod_class.__module__] for mod_class in mod_classes]:
            for elem in dir(mod_class_mod):
                res = tc_const_re.match(elem)
                if res:
                    tc_const_name = res.group(1)
                    tc_const_value = getattr(mod_class_mod, elem)
                    log.debug("Found constant %s ('%s') in module %s, adding it to %s" % (tc_const_name,
                                                                                          tc_const_value,
                                                                                          mod_class_mod.__name__,
                                                                                          package.__name__))
                    if hasattr(package, tc_const_name):
                        cur_value = getattr(package, tc_const_name)
                        if not tc_const_value == cur_value:
                            log.error("Constant %s.%s defined as '%s', can't set it to '%s'." % (package.__name__,
                                                                                                 tc_const_name,
                                                                                                 cur_value,
                                                                                                 tc_const_value
                                                                                                ))
                    else:
                        setattr(package, tc_const_name, tc_const_value)

    # obtain all subclasses of toolchain
    found_tcs = nub(get_subclasses(Toolchain))

    # filter found toolchain subclasses based on whether they can be used a toolchains
    found_tcs = [tc for tc in found_tcs if tc._is_toolchain_for(None)]

    for tc in found_tcs:
        if tc._is_toolchain_for(name):
            return tc, found_tcs

    return None, found_tcs
    def test_module_naming_scheme(self):
        """Test using default module naming scheme."""
        all_stops = [x[0] for x in EasyBlock.get_steps()]
        init_config(build_options={'valid_stops': all_stops})

        ecs_dir = os.path.join(os.path.dirname(__file__), 'easyconfigs')
        ec_files = [os.path.join(subdir, fil) for (subdir, _, files) in os.walk(ecs_dir) for fil in files]
        ec_files = [fil for fil in ec_files if not "v2.0" in fil]  # TODO FIXME: drop this once 2.0 support works

        build_options = {
            'check_osdeps': False,
            'robot_path': [ecs_dir],
            'valid_stops': all_stops,
            'validate': False,
        }
        init_config(build_options=build_options)

        def test_mns():
            """Test default module naming scheme."""
            # test default naming scheme
            for ec_file in ec_files:
                ec_path = os.path.abspath(ec_file)
                ecs = process_easyconfig(ec_path, validate=False)
                # derive module name directly from easyconfig file name
                ec_fn = os.path.basename(ec_file)
                if ec_fn in ec2mod_map:
                    # only check first, ignore any others (occurs when blocks are used (format v1.0 only))
                    self.assertEqual(ec2mod_map[ec_fn], det_full_module_name_mg(ecs[0]['ec']))

        # test default module naming scheme
        default_ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/4.6.3',
            'gzip-1.4.eb': 'gzip/1.4',
            'gzip-1.4-GCC-4.6.3.eb': 'gzip/1.4-GCC-4.6.3',
            'gzip-1.5-goolf-1.4.10.eb': 'gzip/1.5-goolf-1.4.10',
            'gzip-1.5-ictce-4.1.13.eb': 'gzip/1.5-ictce-4.1.13',
            'toy-0.0.eb': 'toy/0.0',
            'toy-0.0-multiple.eb': 'toy/0.0-somesuffix',  # first block sets versionsuffix to '-somesuffix'
        }
        ec2mod_map = default_ec2mod_map
        test_mns()

        # generating module name from non-parsed easyconfig works fine
        non_parsed = {
            'name': 'foo',
            'version': '1.2.3',
            'versionsuffix': '-bar',
            'toolchain': {
                'name': 't00ls',
                'version': '6.6.6',
            },
        }
        self.assertEqual('foo/1.2.3-t00ls-6.6.6-bar', det_full_module_name_ec(non_parsed))

        # install custom module naming scheme dynamically
        test_mns_parent_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'sandbox')
        sys.path.append(test_mns_parent_dir)
        reload(easybuild)
        reload(easybuild.tools)
        reload(easybuild.tools.module_naming_scheme)

        # make sure test module naming schemes are available
        for test_mns_mod in ['test_module_naming_scheme', 'test_module_naming_scheme_all']:
            mns_path = "easybuild.tools.module_naming_scheme.%s" % test_mns_mod
            mns_mod = __import__(mns_path, globals(), locals(), [''])
            test_mnss = dict([(x.__name__, x) for x in get_subclasses(mns_mod.ModuleNamingScheme)])
            easybuild.tools.module_naming_scheme.AVAIL_MODULE_NAMING_SCHEMES.update(test_mnss)
        init_config(build_options=build_options)

        # test simple custom module naming scheme
        os.environ['EASYBUILD_MODULE_NAMING_SCHEME'] = 'TestModuleNamingScheme'
        init_config(build_options=build_options)
        ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/4.6.3',
            'gzip-1.4.eb': 'gzip/1.4',
            'gzip-1.4-GCC-4.6.3.eb': 'gnu/gzip/1.4',
            'gzip-1.5-goolf-1.4.10.eb': 'gnu/openmpi/gzip/1.5',
            'gzip-1.5-ictce-4.1.13.eb': 'intel/intelmpi/gzip/1.5',
            'toy-0.0.eb': 'toy/0.0',
            'toy-0.0-multiple.eb': 'toy/0.0',  # test module naming scheme ignores version suffixes
        }
        test_mns()

        # test module naming scheme using all available easyconfig parameters
        os.environ['EASYBUILD_MODULE_NAMING_SCHEME'] = 'TestModuleNamingSchemeAll'
        init_config(build_options=build_options)
        ec2mod_map = {
            'GCC-4.6.3.eb': 'GCC/afd4d25a1a2cdb1364c55274fb6929fab622f652',
            'gzip-1.4.eb': 'gzip/b6306986fb95a06ad8bd2a09689d8997ff3e80dd',
            'gzip-1.4-GCC-4.6.3.eb': 'gzip/3c2d54583487828c21e17ed185eac372cabc5bb0',
            'gzip-1.5-goolf-1.4.10.eb': 'gzip/1fb1e3787d6063e05a04b2c054faf00dbe1dfe97',
            'gzip-1.5-ictce-4.1.13.eb': 'gzip/78c9afa1ff09994fe38d796b7569ce4b175e3551',
            'toy-0.0.eb': 'toy/494518267cc5ed64c4250c5fbd1730a6e48fde17',
            'toy-0.0-multiple.eb': 'toy/02822d81743944e1c072fc3c717c666da70f1be6',
        }
        test_mns()

        # test determining module name for dependencies (i.e. non-parsed easyconfigs)
        # using a module naming scheme that requires all easyconfig parameters
        for dep_ec, dep_spec in [
            ('GCC-4.6.3.eb', {
                'name': 'GCC',
                'version': '4.6.3',
                'versionsuffix': '',
                'toolchain': {'name': 'dummy', 'version': 'dummy'},
            }),
            ('gzip-1.5-goolf-1.4.10.eb', {
                'name': 'gzip',
                'version': '1.5',
                'versionsuffix': '',
                'toolchain': {'name': 'goolf', 'version': '1.4.10'},
            }),
            ('toy-0.0-multiple.eb', {
                'name': 'toy',
                'version': '0.0',
                'versionsuffix': '-multiple',
                'toolchain': {'name': 'dummy', 'version': 'dummy'},
            }),
        ]:
            self.assertEqual(det_full_module_name_ec(dep_spec), ec2mod_map[dep_ec])

        # restore default module naming scheme, and retest
        os.environ['EASYBUILD_MODULE_NAMING_SCHEME'] = self.orig_module_naming_scheme
        init_config(build_options=build_options)
        ec2mod_map = default_ec2mod_map
        test_mns()
示例#36
0
    def make_init(self):
        """ add all the options to generaloption, so it can correctly parse the command line arguments """

        opts = {
            # long option: (description, type, action, default, short option)

            "basepath": ("Directory (preferably shared) to use for temporary mympirun files (default: HOME).",
                         "str", "store", None),

            'branchcount': ("Set the hydra branchcount", "int", "store", None),

            "debuglvl": ("Specify debug level", "int", "store", 0),

            "debugmpi": ("Enable MPI level debugging", None, "store_true", False),

            "dry-run": ("Dry run mode, just print command that will be executed", None, 'store_true', False, 'D'),

            "double": ("Run double the amount of processes (equivalent to --multi 2)", None, "store_true", False),

            "hybrid": ("Run in hybrid mode, specify number of processes per node.", "int", "store", None, 'h'),

            "launcher": ("The launcher to be used by Hydra (used in recent Intel MPI versions (> 4.1))"
                         "for example: ssh, pbsdsh, ..", "str", "store", None),

            "logtofile": ("redirect the logging of mympirun to a file (instead of stdout/stderr)",
                          "str", "store", None),

            "mpdbootverbose": ("Run verbose mpdboot", None, "store_true", False),

            "mpirunoptions": ("String with options to pass to mpirun (will be appended to generate command)",
                              "str", "store", None),

            "multi": ("Run the amount of processes multiplied by the given integer", "int", "store", None),

            "noenvmodules": ("Don't pass the environment modules variables",
                             None, "store_true", False),

            "order": ("Reorder the generated nodelist (default: normal. supports: sort, random[_<seed>])",
                      "str", "store", None),

            "output": ("redirect the output of mpirun to a file (instead of stdout/stderr)",
                       "str", "store", None),

            "output-check-timeout": ("Warn when no stdout/stderr was seen after start (in seconds; negative number "
                                     "disables this test", "int", "store", DEFAULT_TIMEOUT),

            "output-check-fatal": ("Exit with code %s instead of warn in case of output check timeout" % TIMEOUT_CODE,
                                    None, "store_true", False),

            "overridepin": (("Let mympriun set the affinity (default: disabled, left over to MPI implementation). "
                             "Supported types: 'compact','spread','cycle' (add 'pin' postfix for single core pinning, "
                             "e.g. 'cyclepin')."), "str", "store", None),

            # don't set it by default. It will be set if needed (eg ipath)
            "pinmpi": ("Disable MPI pinning", None, "store_true", True),

            "rdma": ("Force rdma device", None, "store_true", None),

            "schedtype": ("Specify scheduler (eg local, pbs...; will try to guess by default).",
                      "str", "store", None, "S"),

            "setmpi": ("Specify MPI flavor (eg mpich2, openmpi...; will try to guess by default).",
                       "str", "store", None, "M"),

            "showmpi": ("Print the known MPI classes and exit", None, "store_true", False, 'm'),

            "showsched": ("Print the known Sched classes and exit", None, "store_true", False, 's'),

            "sockets-per-node": ("Number of sockets per node (default: 0, i.e. try to detect #sockets "
                                 "from /proc/cpuinfo)", "int", "store", 0),

            "ssh": ("Force ssh for mpd startup (will try to use optimised method by default)",
                    None, "store_false", True),

            "stats": ("Set MPI statistics level", "int", "store", 0),

            "universe": (("Start only this number of processes instead of all (e.g. for MPI_Spawn) Total size of the "
                          "universe is all requested processes.)"), "int", "store", None),

            'use_psm': ("Use Performance Scaled Messaging", None, "store_true", None),

            "variablesprefix": (("Comma-separated list of exact names or prefixes to match environment variables "
                                 "(<prefix>_ should match) to pass through."), "string", "extend", []),

        }

        descr = ["mympirun options", "General advanced mympirun options"]

        prefix = ''
        self.log.debug("Add advanced option parser: options %s, description %s, prefix %s", opts, descr, prefix)
        self.add_group_parser(opts, descr, prefix=prefix)

        # for all MPI classes, get the additional options
        for mpi in get_subclasses(MPI):
            if mpi.RUNTIMEOPTION is not None:
                # don't try to add the same set of options twice (based on prefix)
                prefix = mpi.RUNTIMEOPTION['prefix']
                if prefix not in self.dict_by_prefix():
                    opts = mpi.RUNTIMEOPTION['options']
                    descr = mpi.RUNTIMEOPTION['description']
                    self.log.debug("Add MPI subclass %s option parser prefix %s descr %s opts %s",
                                   mpi.__name__, prefix, descr, opts)
                    self.add_group_parser(opts, descr, prefix=prefix)
def avail_module_generators():
    """
    Return all known module syntaxes.
    """
    return dict([(k.SYNTAX, k) for k in get_subclasses(ModuleGenerator)])