コード例 #1
0
ファイル: build_version.py プロジェクト: envzhu/barreleye
    def save(self, path):
        """
        Save the version to dest .py file. This is a command for internal
        build process.

        :param path: the python file to save the version.
        """
        # pylint: disable=no-self-use,unused-argument
        log = clog.get_log(console_format=clog.FMT_NORMAL, overwrite=True)
        local_host = ssh_host.get_local_host(ssh=False)
        source_dir = os.path.dirname(os.path.dirname(__file__))
        version_string = coral_get_version_string(log, source_dir)
        if version_string is None:
            cmd_general.cmd_exit(log, -1)
        version_string = coral_uniformed_version(version_string)
        version_data = '"""'
        version_data += """
Please DO NOT edit this file directly!
This file is generated by "coral" command.
"""
        version_data += '"""'
        version_data += "\n"
        version_data += "CORAL_VERSION = \"%s\"\n" % (version_string)

        try:
            with open(path, 'w') as version_file:
                version_file.write(version_data)
        except:
            log.cl_error("failed to write version to file [%s] on host [%s]: %s",
                         path, local_host.sh_hostname,
                         traceback.format_exc())
            cmd_general.cmd_exit(log, -1)
        cmd_general.cmd_exit(log, 0)
コード例 #2
0
ファイル: coral.py プロジェクト: ldd91/barreleye
def build_bootstrap():
    """
    Bootstrap the command by installing the dependencies.
    """
    # pylint: disable=unused-variable
    local_host = ssh_host.get_local_host(ssh=False)
    log = clog.get_log(console_format=clog.FMT_NORMAL)
    distro = local_host.sh_distro(log)
    if distro is None:
        log.cl_error("failed to get distro of host [%s]",
                     local_host.sh_hostname)
        sys.exit(-1)

    missing_rpms, missing_pips = \
        install_common.command_missing_packages(distro)
    if missing_rpms is None:
        log.cl_error("failed to get the missing packages of host [%s]",
                     local_host.sh_hostname)
        sys.exit(-1)

    command = "mkdir -p %s" % constant.CORAL_BUILD_CACHE_PIP_DIR
    retval = local_host.sh_run(log, command, timeout=None)
    if retval.cr_exit_status:
        log.cl_error("failed to run command [%s] on host [%s], "
                     "ret = %d, stdout = [%s], stderr = [%s]",
                     command, local_host.sh_hostname,
                     retval.cr_exit_status, retval.cr_stdout,
                     retval.cr_stderr)
        sys.exit(-1)

    ret = install_common.bootstrap_from_internet(log, local_host, missing_rpms,
                                                 missing_pips,
                                                 pip_dir=constant.CORAL_BUILD_CACHE_PIP_DIR)
    if ret:
        sys.exit(ret)
コード例 #3
0
ファイル: build_doc.py プロジェクト: LiXi-storage/barreleye
def check_doc(log, doc_dir):
    """
    Check the doc
    """
    local_host = ssh_host.get_local_host(ssh=False)
    languages = local_host.sh_get_dir_fnames(log, doc_dir)
    if languages is None:
        log.cl_error("failed to get fnames under [%s] of host [%s]",
                     doc_dir, local_host.sh_hostname)
        return -1
    # Key is the relative file path under language dir. The value is the
    # line number of the file. If the line numbers are different between
    # different languages, that means inconsistency.
    line_number_dict = {}
    for language in languages:
        if language not in LANGUAGES:
            log.cl_error("unexpected language [%s] under [%s] of host [%s]",
                         language, doc_dir, local_host.sh_hostname)
            return -1

        lang_dir = doc_dir + "/" + language
        command = "cd %s && find . -type f" % lang_dir
        retval = local_host.sh_run(log, command)
        if retval.cr_exit_status:
            log.cl_error("failed to run command [%s] on host [%s], "
                         "ret = [%d], stdout = [%s], stderr = [%s]",
                         command,
                         local_host.sh_hostname,
                         retval.cr_exit_status,
                         retval.cr_stdout,
                         retval.cr_stderr)
            return -1

        relative_fpaths = retval.cr_stdout.splitlines()
        for relative_fpath in relative_fpaths:
            doc_file = CoralDocFile(local_host, doc_dir, language,
                                    relative_fpath)
            log.cl_info("checking doc [%s]", doc_file.cdf_fpath)
            line_number = doc_file.cdf_line_number(log)
            if relative_fpath in line_number_dict:
                old_line_number = line_number_dict[relative_fpath]
                if old_line_number != line_number:
                    log.cl_error("inconsistent line number of doc [%s] "
                                 "between languages, %s vs. %s",
                                 relative_fpath, old_line_number,
                                 line_number)
                    return -1
            else:
                line_number_dict[relative_fpath] = line_number
    return 0
コード例 #4
0
def build(log,
          source_dir,
          workspace,
          cache=constant.CORAL_BUILD_CACHE,
          lustre_rpms_dir=None,
          e2fsprogs_rpms_dir=None,
          collectd=None,
          enable_zfs=False,
          enable_devel=False,
          disable_plugin=None,
          tsinghua_mirror=False):
    """
    Build the Coral ISO.
    """
    # pylint: disable=too-many-locals,too-many-branches
    # pylint: disable=too-many-statements
    if disable_plugin is None:
        disabled_plugins = []
    else:
        disabled_plugins = cmd_general.parse_list_string(log, disable_plugin)
        if disabled_plugins is None:
            log.cl_error("invalid option [%s] of --disable_plugin",
                         disable_plugin)
            return -1

    plugins = list(build_common.CORAL_RELEASE_PLUGIN_DICT.values())
    if enable_devel:
        plugins += list(build_common.CORAL_DEVEL_PLUGIN_DICT.values())

    sync_cache_back = True
    disable_plugins_str = ""
    for plugin_name in disabled_plugins:
        if plugin_name not in build_common.CORAL_PLUGIN_DICT:
            log.cl_error("unknown plugin [%s] of --disable_plugin",
                         plugin_name)
            log.cl_error("possible plugins are %s",
                         list(build_common.CORAL_PLUGIN_DICT.keys()))
            return -1

        if ((not enable_devel) and
            (plugin_name not in build_common.CORAL_RELEASE_PLUGIN_DICT)):
            log.cl_info(
                "plugin [%s] will not be included in release "
                "ISO anyway", plugin_name)
            continue

        sync_cache_back = False
        plugin = build_common.CORAL_PLUGIN_DICT[plugin_name]
        if plugin in plugins:
            plugins.remove(plugin)
        disable_plugins_str += " --disable-%s" % plugin_name

    if len(plugins) == 0:
        log.cl_error("everything has been disabled, nothing to build")
        return -1

    need_lustre_rpms = False
    need_collectd = False
    install_lustre = False
    enabled_plugin_str = ""
    for plugin in plugins:
        if enabled_plugin_str == "":
            enabled_plugin_str = plugin.cpt_plugin_name
        else:
            enabled_plugin_str += ", " + plugin.cpt_plugin_name
        if plugin.cpt_need_lustre_rpms:
            need_lustre_rpms = True
        if plugin.cpt_need_collectd:
            need_collectd = True
        if plugin.cpt_install_lustre:
            install_lustre = True

    type_fname = constant.CORAL_BUILD_CACHE_TYPE_OPEN
    if type_fname == constant.CORAL_BUILD_CACHE_TYPE_OPEN:
        log.cl_info("building ISO with %s", enabled_plugin_str)

    local_host = ssh_host.get_local_host(ssh=False)
    distro = local_host.sh_distro(log)
    if distro not in (ssh_host.DISTRO_RHEL7, ssh_host.DISTRO_RHEL8):
        log.cl_error("build on distro [%s] is not supported yet", distro)
        return -1

    shared_cache = cache.rstrip("/")
    # Shared cache for this build type
    shared_type_cache = shared_cache + "/" + type_fname
    # Extra RPMs to download
    extra_rpm_names = []
    # Extra RPM file names under package directory
    extra_package_fnames = []
    # Extra file names under ISO directory
    extra_iso_fnames = []

    enable_zfs_string = ""
    if enable_zfs:
        enable_zfs_string = ", ZFS support disabled"

    type_cache = workspace + "/" + type_fname
    build_pip_dir = type_cache + "/" + constant.BUILD_PIP
    iso_cache = type_cache + "/" + constant.ISO_CACHE_FNAME
    # Directory path of package under ISO cache
    packages_dir = iso_cache + "/" + constant.BUILD_PACKAGES
    default_lustre_rpms_dir = (iso_cache + "/" +
                               constant.LUSTRE_RPM_DIR_BASENAME)
    default_e2fsprogs_rpms_dir = (iso_cache + "/" +
                                  constant.E2FSPROGS_RPM_DIR_BASENAME)

    if not need_collectd:
        if collectd is not None:
            log.cl_warning(
                "option [--collectd %s] has been ignored since "
                "no need to have Collectd RPMs", collectd)
    elif collectd is not None:
        sync_cache_back = False

    if not need_lustre_rpms and not install_lustre:
        if lustre_rpms_dir is not None:
            log.cl_warning(
                "option [--lustre %s] has been ignored since "
                "no need to have Lustre RPMs", lustre_rpms_dir)
        if e2fsprogs_rpms_dir is not None:
            log.cl_warning(
                "option [--e2fsprogs %s] has been ignored since "
                "no need to have Lustre RPMs", e2fsprogs_rpms_dir)
    else:
        if lustre_rpms_dir is None:
            lustre_rpms_dir = default_lustre_rpms_dir
        if e2fsprogs_rpms_dir is None:
            e2fsprogs_rpms_dir = default_e2fsprogs_rpms_dir

    command = ("mkdir -p %s" % workspace)
    retval = local_host.sh_run(log, command)
    if retval.cr_exit_status:
        log.cl_error(
            "failed to run command [%s] on host [%s], "
            "ret = [%d], stdout = [%s], stderr = [%s]", command,
            local_host.sh_hostname, retval.cr_exit_status, retval.cr_stdout,
            retval.cr_stderr)
        return -1

    ret = get_shared_build_cache(log, local_host, workspace, shared_type_cache)
    if ret:
        log.cl_error("failed to get shared build cache")
        return -1

    target_cpu = local_host.sh_target_cpu(log)
    if target_cpu is None:
        log.cl_error("failed to get the target cpu on host [%s]",
                     local_host.sh_hostname)
        return -1

    ret = install_build_dependency(log,
                                   workspace,
                                   local_host,
                                   distro,
                                   target_cpu,
                                   type_cache,
                                   plugins,
                                   build_pip_dir,
                                   tsinghua_mirror=tsinghua_mirror)
    if ret:
        log.cl_error("failed to install dependency for building")
        return -1

    command = ("mkdir -p %s" % (packages_dir))
    retval = local_host.sh_run(log, command)
    if retval.cr_exit_status:
        log.cl_error(
            "failed to run command [%s] on host [%s], "
            "ret = [%d], stdout = [%s], stderr = [%s]", command,
            local_host.sh_hostname, retval.cr_exit_status, retval.cr_stdout,
            retval.cr_stderr)
        return -1

    for plugin in plugins:
        ret = plugin.cpt_build(log, workspace, local_host, source_dir,
                               target_cpu, type_cache, iso_cache, packages_dir,
                               extra_iso_fnames, extra_package_fnames,
                               extra_rpm_names, collectd)
        if ret:
            log.cl_error("failed to build plugin [%s]", plugin.cpt_plugin_name)
            return -1

    ret = download_dependent_rpms(log, workspace, local_host, distro,
                                  target_cpu, packages_dir, type_cache,
                                  extra_package_fnames, extra_rpm_names)
    if ret:
        log.cl_error("failed to download dependent rpms")
        return -1

    pip_dir = iso_cache + "/" + constant.BUILD_PIP
    command = ("mkdir -p %s" % (pip_dir))
    retval = local_host.sh_run(log, command)
    if retval.cr_exit_status:
        log.cl_error(
            "failed to run command [%s] on host [%s], "
            "ret = [%d], stdout = [%s], stderr = [%s]", command,
            local_host.sh_hostname, retval.cr_exit_status, retval.cr_stdout,
            retval.cr_stderr)
        return -1

    ret = install_common.download_pip3_packages(
        log,
        local_host,
        pip_dir,
        constant.CORAL_DEPENDENT_PIPS,
        tsinghua_mirror=tsinghua_mirror)
    if ret:
        log.cl_error("failed to download pip3 packages")
        return -1

    lustre_distribution = None
    if need_lustre_rpms or install_lustre:
        if lustre_distribution is None:
            log.cl_error("Lustre distribution is needed unexpectedly")
            return -1

    contents = ([constant.BUILD_PACKAGES, constant.BUILD_PIP] +
                extra_iso_fnames)
    ret = local_host.sh_check_dir_content(log,
                                          iso_cache,
                                          contents,
                                          cleanup=True)
    if ret:
        log.cl_error("directory [%s] does not have expected content",
                     iso_cache)
        return -1

    log.cl_info("generating Coral ISO")

    enable_zfs_string = ""
    if enable_zfs:
        enable_zfs_string = " --enable-zfs"
    enable_devel_string = ""
    if enable_devel:
        enable_devel_string = " --enable-devel"
    command = ("cd %s && rm coral-*.tar.bz2 coral-*.tar.gz -f && "
               "sh autogen.sh && "
               "./configure --with-iso-cache=%s%s%s%s && "
               "make -j8 && "
               "make iso" % (source_dir, iso_cache, enable_zfs_string,
                             enable_devel_string, disable_plugins_str))
    retval = local_host.sh_watched_run(log,
                                       command,
                                       None,
                                       None,
                                       return_stdout=False,
                                       return_stderr=False)
    if retval.cr_exit_status:
        log.cl_error("failed to run command [%s] on host [%s]", command,
                     local_host.sh_hostname)
        return -1

    # If there is any plugin disabled or Collectd is special, the local cache
    # might have some things missing thus should not be used by other build.
    if sync_cache_back:
        ret = sync_shared_build_cache(log, local_host, type_cache,
                                      shared_cache)
        if ret:
            log.cl_error("failed to sync to shared build cache")
            return -1

    log.cl_info("Built Coral ISO successfully")
    return 0
コード例 #5
0
ファイル: build_version.py プロジェクト: envzhu/barreleye
def _update_version(log, workspace, source_dir, add_version=False,
                    add_major=False, add_minor=False,
                    new_extra=None):
    """
    Update the version
    """
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements
    # pylint: disable=unused-argument
    add_number = 0
    changing = False
    if add_version:
        add_number += 1
        changing = True
    if add_major:
        add_number += 1
        changing = True
    if add_minor:
        add_number += 1
        changing = True
    if add_number > 1:
        log.cl_error("it is not reasonable to update multiple numbers of "
                     "revision")
        return -1
    if new_extra is not None:
        changing = True
        if len(new_extra) != 0:
            rc = cmd_general.check_version_extra(log, new_extra)
            if rc:
                log.cl_error("extra part [%s] of reviesion is illegal",
                             new_extra)
                return -1
            uniformed_extra = coral_uniformed_version(new_extra)

    if not changing:
        log.cl_error("please specify which part of revision do you want "
                     "to update by:\n"
                     "    --add_version, --add_major, --add_minor, or/and --new_extra")
        return -1

    local_host = ssh_host.get_local_host(ssh=False)
    path = source_dir + "/" + ".git"
    has_git = local_host.sh_path_exists(log, path)
    if has_git < 0:
        log.cl_error("failed to check whether path [%s] exists",
                     path)
        return -1

    if not has_git:
        log.cl_error("current directory is not a git repository")
        return -1

    rc = git_tree_is_clean(log, local_host, source_dir)
    if rc < 0:
        log.cl_error("failed to check whether git tree is clean or not")
        return -1
    if rc == 0:
        log.cl_error("git tree is not clean")
        return -1

    ret = check_tag_meaningful(log, local_host, source_dir)
    if ret:
        log.cl_error("please do not add meaningless empty tags")
        return -1

    version, major, minor, extra = coral_get_version(log, source_dir)
    if version is None:
        log.cl_error("failed to get version")
        return -1
    old_version_string = coral_assemble_version(version, major, minor,
                                                extra)
    message = ""
    if add_version:
        version += 1
        major = 0
        minor = 0
        message = "Version part of revision has been increased.\n"
    elif add_major:
        major += 1
        minor = 0
        message = "Major part of revision has been increased.\n"
    elif add_minor:
        minor += 1
        message = "Minor part of revision has been increased.\n"
    if new_extra is not None:
        if len(new_extra) == 0:
            message += ("Extra part of revision has been cleaned, "
                        "old: [%s].\n" % (extra))
            extra = None
        else:
            if (not add_number) and uniformed_extra == extra:
                log.cl_error("the current reversion has identical extra field [%s]",
                             extra)
                return -1
            message += ("Extra part of revision has been changed from "
                        "[%s] to [%s].\n" % (extra, uniformed_extra))
            extra = new_extra
    else:
        extra = None
    version_string = coral_assemble_version(version, major, minor, extra)

    tags = get_git_tags(log, local_host, source_dir)
    if tags is None:
        log.cl_error("failed to get git tags")
        return -1

    for tag in tags:
        if (coral_uniformed_version(tag) ==
                coral_uniformed_version(version_string)):
            log.cl_error("old tag [%s] has identical reversion",
                         tag)
            return -1

    user_name = get_git_user_name(log, local_host)
    if user_name is None:
        log.cl_error("failed to get git user name")
        return -1

    user_email = get_git_user_email(log, local_host)
    if user_email is None:
        log.cl_error("failed to get git user email")
        return -1

    input_result = input("Are you sure to update the version from [%s] to "
                         "[%s]? [y/N] " % (old_version_string, version_string))
    if ((not input_result.startswith("y")) and
            (not input_result.startswith("Y"))):
        log.cl_stdout("Quiting without touching anything")
        return -1

    rc = update_version_file(log, local_host, version_string, source_dir)
    if rc:
        log.cl_error("failed to update version file")
        return -1

    message += "Tag [%s] has been added\n" % version_string

    command = ("""cd %s && git commit -av -m "release: new tag %s

%s
Signed-off-by: %s <%s>
" """ % (source_dir, version_string, message, user_name, user_email))
    retval = local_host.sh_run(log, command)
    if retval.cr_exit_status:
        log.cl_error("failed to run command [%s] on host [%s], "
                     "ret = [%d], stdout = [%s], stderr = [%s]",
                     command,
                     local_host.sh_hostname,
                     retval.cr_exit_status,
                     retval.cr_stdout,
                     retval.cr_stderr)
        return -1

    command = ('cd %s && git tag -a %s -m "%s"' %
               (source_dir, version_string, version_string))
    retval = local_host.sh_run(log, command)
    if retval.cr_exit_status:
        log.cl_error("failed to run command [%s] on host [%s], "
                     "ret = [%d], stdout = [%s], stderr = [%s]",
                     command,
                     local_host.sh_hostname,
                     retval.cr_exit_status,
                     retval.cr_stdout,
                     retval.cr_stderr)
        return -1

    new_version_string = coral_get_version_string(log, source_dir)
    if new_version_string is None:
        log.cl_error("failed to get version after adding tag")
        return -1

    if new_version_string != version_string:
        log.cl_error("got different version [%s] after tagging with [%s]",
                     new_version_string, version_string)
        return -1
    log.cl_info("tag [%s] has been added", version_string)
    return 0
コード例 #6
0
ファイル: build_version.py プロジェクト: envzhu/barreleye
def coral_get_version(log, source_dir):
    """
    Get coral version from git.
    Two possible version formats:
        version.major.minor
        version.major.minor-extra
    In the first format, return (version, major, minor, None)
    Return (version, major, minor, extra)
    """
    # pylint: disable=too-many-locals,too-many-branches
    local_host = ssh_host.get_local_host(ssh=False)
    version_fpath = CORAL_VERSION_FPATH

    version_data = read_version_file(log, local_host, source_dir)
    if version_data is None:
        log.cl_error("failed to read version file")
        return None, None, None, None

    version_line = None
    lines = version_data.strip().splitlines()
    for line in lines:
        if line.startswith("#"):
            continue
        if version_line is not None:
            log.cl_error("version file [%s] has multiple uncommented lines",
                         version_fpath)
            return None, None, None, None
        version_line = line

    if version_line is None:
        log.cl_error("version file [%s] has no uncommented line",
                     version_fpath)
        return None, None, None, None

    version, major, minor, extra = \
        cmd_general.coral_parse_version(log, version_line,
                                        minus_as_delimiter=True)
    if version is None:
        log.cl_error("invalid version [%s] in file [%s]",
                     version_line, version_fpath)
        return None, None, None, None

    path = source_dir + "/.git"
    has_git = local_host.sh_path_exists(log, path)
    if has_git < 0:
        log.cl_error("failed to check whether path [%s] exists",
                     path)
        return None, None, None, None

    if not has_git:
        return version, major, minor, extra

    git_version, git_major, git_minor, git_extra = \
        coral_version_from_git(log, local_host, source_dir)
    if git_version is None:
        log.cl_error("failed to get version from git")
        return None, None, None, None

    if git_version != version:
        log.cl_error("inconsistent version numbers got from file [%s] "
                     "and git, [%s] vs. [%s]", version_fpath,
                     version, git_version)
        return None, None, None, None

    if git_major != major:
        log.cl_error("inconsistent major numbers got from file [%s] "
                     "and git, [%s] vs. [%s]", version_fpath,
                     major, git_major)
        return None, None, None, None

    if git_minor != minor:
        log.cl_error("inconsistent minor numbers got from file [%s] "
                     "and git, [%s] vs. [%s]", version_fpath,
                     minor, git_minor)
        return None, None, None, None

    if extra is None or extra == git_extra:
        return version, major, minor, git_extra

    # If extra field from git has more things than extra field from file, the
    # it should be seperated by the first "-"
    minus_index = git_extra.find("-")
    if minus_index < 0:
        log.cl_error("the extra field [%s] from git is not equal to the "
                     "extra field [%s] from file, and does not have [-]",
                     git_extra, extra)
        return None, None, None, None

    git_extra_start = git_extra[:minus_index]
    if git_extra_start != extra:
        log.cl_error("the extra field [%s] from git does not start "
                     "with [%s-] which is the extra field from file",
                     git_extra, extra)
        return None, None, None, None

    return version, major, minor, git_extra
コード例 #7
0
ファイル: barrele_instance.py プロジェクト: ldd91/barreleye
def barrele_init_instance(log, workspace, config, config_fpath, log_to_file,
                          logdir_is_default):
    """
    Parse the config and init the instance
    """
    # pylint: disable=too-many-locals,too-many-branches,too-many-statements
    collect_interval = utils.config_value(
        config, barrele_constant.BRL_COLLECT_INTERVAL)
    if collect_interval is None:
        log.cl_debug(
            "no [%s] is configured in the config file [%s], "
            "using default value [%s]", barrele_constant.BRL_COLLECT_INTERVAL,
            config_fpath, BARRELE_COLLECT_INTERVAL)
        collect_interval = BARRELE_COLLECT_INTERVAL

    continuous_query_periods = utils.config_value(
        config, barrele_constant.BRL_CONTINUOUS_QUERY_PERIODS)
    if continuous_query_periods is None:
        log.cl_debug(
            "no [%s] is configured in the config file [%s], "
            "using default value [%s]",
            barrele_constant.BRL_CONTINUOUS_QUERY_PERIODS, config_fpath,
            BARRELE_CONTINUOUS_QUERY_PERIODS)
        continuous_query_periods = BARRELE_CONTINUOUS_QUERY_PERIODS

    jobstat_pattern = utils.config_value(config,
                                         barrele_constant.BRL_JOBSTAT_PATTERN)
    if jobstat_pattern is None:
        log.cl_debug(
            "no [%s] is configured in the config file [%s], "
            "using default value [%s]", barrele_constant.BRL_JOBSTAT_PATTERN,
            config_fpath, barrele_constant.BARRELE_JOBSTAT_PATTERN_UNKNOWN)
        jobstat_pattern = barrele_constant.BARRELE_JOBSTAT_PATTERN_UNKNOWN
    if jobstat_pattern not in barrele_constant.BARRELE_JOBSTAT_PATTERNS:
        log.cl_error("unsupported jobstat_pattern [%s], supported: %s",
                     jobstat_pattern,
                     barrele_constant.BARRELE_JOBSTAT_PATTERNS)
        return None

    lustre_fallback_version_name = \
        utils.config_value(config,
                           barrele_constant.BRL_LUSTRE_FALLBACK_VERSION)
    if lustre_fallback_version_name is None:
        log.cl_debug(
            "no [%s] is configured in the config file [%s], "
            "using default value [%s]",
            barrele_constant.BRL_LUSTRE_FALLBACK_VERSION, config_fpath,
            BARRELE_LUSTRE_FALLBACK_VERSION)
        lustre_fallback_version_name = BARRELE_LUSTRE_FALLBACK_VERSION

    if lustre_fallback_version_name not in lustre_version.LUSTRE_VERSION_DICT:
        log.cl_error(
            "unsupported Lustre version [%s] is configured in the "
            "config file [%s]", lustre_fallback_version_name, config_fpath)
        return None

    lustre_fallback_version = \
        lustre_version.LUSTRE_VERSION_DICT[lustre_fallback_version_name]

    enable_lustre_exp_mdt = utils.config_value(
        config, barrele_constant.BRL_ENABLE_LUSTRE_EXP_MDT)
    if enable_lustre_exp_mdt is None:
        log.cl_debug(
            "no [%s] is configured in the config file [%s], "
            "using default value [False]",
            barrele_constant.BRL_ENABLE_LUSTRE_EXP_MDT, config_fpath)
        enable_lustre_exp_mdt = False

    enable_lustre_exp_ost = utils.config_value(
        config, barrele_constant.BRL_ENABLE_LUSTRE_EXP_OST)
    if enable_lustre_exp_ost is None:
        log.cl_debug(
            "no [%s] is configured in the config file [%s], "
            "using default value [False]",
            barrele_constant.BRL_ENABLE_LUSTRE_EXP_OST, config_fpath)
        enable_lustre_exp_ost = False

    agent_configs = utils.config_value(config, barrele_constant.BRL_AGENTS)
    if agent_configs is None:
        log.cl_error(
            "can NOT find [%s] in the config file, "
            "please correct file [%s]", barrele_constant.BRL_AGENTS,
            config_fpath)
        return None

    host_dict = {}
    barreleye_server = parse_server_config(log, config, config_fpath,
                                           host_dict)
    if barreleye_server is None:
        log.cl_error("failed to parse server config")
        return None

    agent_dict = {}
    for agent_config in agent_configs:
        hostname_config = utils.config_value(agent_config,
                                             barrele_constant.BRL_HOSTNAME)
        if hostname_config is None:
            log.cl_error(
                "can NOT find [%s] in the config of SSH host "
                "[%s], please correct file [%s]",
                barrele_constant.BRL_HOSTNAME, hostname_config, config_fpath)
            return None

        hostnames = cmd_general.parse_list_string(log, hostname_config)
        if hostnames is None:
            log.cl_error("[%s] as [%s] is invalid in the config file [%s]",
                         hostname_config, barrele_constant.BRL_HOSTNAME,
                         config_fpath)
            return None

        ssh_identity_file = utils.config_value(
            agent_config, barrele_constant.BRL_SSH_IDENTITY_FILE)

        enable_disk = utils.config_value(agent_config,
                                         barrele_constant.BRL_ENABLE_DISK)
        if enable_disk is None:
            log.cl_debug(
                "no [%s] is configured in the config file [%s], "
                "using default value [False]",
                barrele_constant.BRL_ENABLE_DISK, config_fpath)
            enable_disk = False

        enable_infiniband = utils.config_value(
            agent_config, barrele_constant.BRL_ENABLE_INFINIBAND)
        if enable_infiniband is None:
            log.cl_debug(
                "no [%s] is configured in the config file [%s], "
                "using default value [False]",
                barrele_constant.BRL_ENABLE_INFINIBAND, config_fpath)
            enable_infiniband = False

        enable_lustre_client = utils.config_value(
            agent_config, barrele_constant.BRL_ENABLE_LUSTRE_CLIENT)
        if enable_lustre_client is None:
            log.cl_debug(
                "no [%s] is configured in the config file [%s], "
                "using default value [False]",
                barrele_constant.BRL_ENABLE_LUSTRE_CLIENT, config_fpath)
            enable_lustre_client = False

        enable_lustre_mds = utils.config_value(
            agent_config, barrele_constant.BRL_ENABLE_LUSTRE_MDS)
        if enable_lustre_mds is None:
            log.cl_debug(
                "no [%s] is configured in the config file [%s], "
                "using default value [True]",
                barrele_constant.BRL_ENABLE_LUSTRE_MDS, config_fpath)
            enable_lustre_mds = True

        enable_lustre_oss = utils.config_value(
            agent_config, barrele_constant.BRL_ENABLE_LUSTRE_OSS)
        if enable_lustre_oss is None:
            log.cl_debug(
                "no [%s] is configured in the config file [%s], "
                "using default value [True]",
                barrele_constant.BRL_ENABLE_LUSTRE_OSS, config_fpath)
            enable_lustre_oss = True

        for hostname in hostnames:
            if hostname in agent_dict:
                log.cl_error(
                    "agent of host [%s] is configured for multiple times",
                    hostname)
                return None
            host = ssh_host.get_or_add_host_to_dict(log, host_dict, hostname,
                                                    ssh_identity_file)
            if host is None:
                return None

            agent = barrele_agent.BarreleAgent(
                host,
                barreleye_server,
                enable_disk=enable_disk,
                enable_lustre_oss=enable_lustre_oss,
                enable_lustre_mds=enable_lustre_mds,
                enable_lustre_client=enable_lustre_client,
                enable_infiniband=enable_infiniband)
            agent_dict[hostname] = agent

    local_host = ssh_host.get_local_host()
    instance = BarreleInstance(workspace, config, config_fpath, log_to_file,
                               logdir_is_default, local_host, collect_interval,
                               continuous_query_periods, jobstat_pattern,
                               lustre_fallback_version, enable_lustre_exp_mdt,
                               enable_lustre_exp_ost, host_dict, agent_dict,
                               barreleye_server)
    return instance