# Buggy code
def _get_yum_config():
    """
    Returns a dict representing the yum config options and values.

    We try to pull all of the yum config options into a standard dict object.
    This is currently only used to get the reposdir settings, but could be used
    for other things if needed.

    If the yum python library is available, use that, which will give us all of
    the options, including all of the defaults not specified in the yum config.
    Additionally, they will all be of the correct object type.

    If the yum library is not available, we try to read the yum.conf
    directly ourselves with a minimal set of "defaults".
    """
    # in case of any non-fatal failures, these defaults will be used
    conf = {
        "reposdir": ["/etc/yum/repos.d", "/etc/yum.repos.d"],
    }

    if HAS_YUM:
        try:
            yb = yum.YumBase()
            yb.preconf.init_plugins = False
            for name, value in six.iteritems(yb.conf):
                conf[name] = value
        except (AttributeError, yum.Errors.ConfigError) as exc:
            raise CommandExecutionError("Could not query yum config: {0}".format(exc))
    else:
        # fall back to parsing the config ourselves
        # Look for the config the same order yum does
        fn = None
        paths = ("/etc/yum/yum.conf", "/etc/yum.conf", "/etc/dnf/dnf.conf")
        for path in paths:
            if os.path.exists(path):
                fn = path
                break

        if not fn:
            raise CommandExecutionError(
                "No suitable yum config file found in: {0}".format(paths)
            )

        cp = configparser.ConfigParser()
        try:
            cp.read(fn)
        except (IOError, OSError) as exc:
            raise CommandExecutionError("Unable to read from {0}: {1}".format(fn, exc))

        if cp.has_section("main"):
            for opt in cp.options("main"):
                if opt in ("reposdir", "commands", "excludes"):
                    # these options are expected to be lists
                    conf[opt] = [x.strip() for x in cp.get("main", opt).split(",")]
                else:
                    conf[opt] = cp.get("main", opt)
        else:
            log.warning(
                "Could not find [main] section in %s, using internal defaults", fn
            )

    return conf


# Traceback (YumBaseError)
ID: soe-packages
Function: pkg.installed
Result: False
Comment: An exception occurred in this state: Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/salt/state.py", line 1843, in call
**cdata['kwargs'])
File "/usr/lib/python2.7/site-packages/salt/loader.py", line 1795, in wrapper
return f(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/states/pkg.py", line 1631, in installed
**kwargs)
File "/usr/lib/python2.7/site-packages/salt/modules/yumpkg.py", line 1284, in install
_available = list_repo_pkgs(*has_wildcards, byrepo=False, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/modules/yumpkg.py", line 792, in list_repo_pkgs
repo_name for repo_name, repo_info in six.iteritems(list_repos())
File "/usr/lib/python2.7/site-packages/salt/modules/yumpkg.py", line 2456, in list_repos
basedirs = _normalize_basedir(basedir)
File "/usr/lib/python2.7/site-packages/salt/modules/yumpkg.py", line 382, in _normalize_basedir
basedir = _get_yum_config_value('reposdir')
File "/usr/lib/python2.7/site-packages/salt/modules/yumpkg.py", line 359, in _get_yum_config_value
conf = _get_yum_config()
File "/usr/lib/python2.7/site-packages/salt/modules/yumpkg.py", line 308, in _get_yum_config
for name, value in six.iteritems(yb.conf):
File "/usr/lib/python2.7/site-packages/yum/__init__.py", line 1078, in <lambda>
conf = property(fget=lambda self: self._getConfig(),
File "/usr/lib/python2.7/site-packages/yum/__init__.py", line 349, in _getConfig
startupconf = config.readStartupConfig(fn, root, releasever)
File "/usr/lib/python2.7/site-packages/yum/config.py", line 1093, in readStartupConfig
startupconf.distroverpkg)
File "/usr/lib/python2.7/site-packages/yum/config.py", line 1235, in _getsysver
raise Errors.YumBaseError("Error: " + str(e))
YumBaseError: Error: rpmdb open failed
Started: 17:29:53.115194
Duration: 28718.161 ms
Changes:

# Fixed code
def _get_yum_config():
    """
    Returns a dict representing the yum config options and values.

    We try to pull all of the yum config options into a standard dict object.
    This is currently only used to get the reposdir settings, but could be used
    for other things if needed.

    If the yum python library is available, use that, which will give us all of
    the options, including all of the defaults not specified in the yum config.
    Additionally, they will all be of the correct object type.

    If the yum library is not available, we try to read the yum.conf
    directly ourselves with a minimal set of "defaults".
    """
    # in case of any non-fatal failures, these defaults will be used
    conf = {
        "reposdir": ["/etc/yum/repos.d", "/etc/yum.repos.d"],
    }

    if HAS_YUM:
        try:
            yb = yum.YumBase()
            yb.preconf.init_plugins = False
            for name, value in six.iteritems(yb.conf):
                conf[name] = value
        except (AttributeError, yum.Errors.ConfigError) as exc:
            raise CommandExecutionError("Could not query yum config: {0}".format(exc))
        except yum.Errors.YumBaseError as yum_base_error:
            raise CommandExecutionError(
                "Error accessing yum or rpmdb: {0}".format(yum_base_error)
            )
    else:
        # fall back to parsing the config ourselves
        # Look for the config the same order yum does
        fn = None
        paths = ("/etc/yum/yum.conf", "/etc/yum.conf", "/etc/dnf/dnf.conf")
        for path in paths:
            if os.path.exists(path):
                fn = path
                break

        if not fn:
            raise CommandExecutionError(
                "No suitable yum config file found in: {0}".format(paths)
            )

        cp = configparser.ConfigParser()
        try:
            cp.read(fn)
        except (IOError, OSError) as exc:
            raise CommandExecutionError("Unable to read from {0}: {1}".format(fn, exc))

        if cp.has_section("main"):
            for opt in cp.options("main"):
                if opt in ("reposdir", "commands", "excludes"):
                    # these options are expected to be lists
                    conf[opt] = [x.strip() for x in cp.get("main", opt).split(",")]
                else:
                    conf[opt] = cp.get("main", opt)
        else:
            log.warning(
                "Could not find [main] section in %s, using internal defaults", fn
            )

    return conf