Install the passed package, add refresh=True to update the opkg database.

    name
        The name of the package to be installed. Note that this parameter is
        ignored if either "pkgs" or "sources" is passed. Additionally, please
        note that this option can only be used to install packages from a
        software repository. To install a package file manually, use the
        "sources" option.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install <package name>

    refresh
        Whether or not to refresh the package database before installing.

    version
        Install a specific version of the package, e.g. 1.2.3~0ubuntu0. Ignored
        if "pkgs" or "sources" is passed.

        .. versionadded:: 2017.7.0

    reinstall : False
        Specifying reinstall=True will use ``opkg install --force-reinstall``
        rather than simply ``opkg install`` for requested packages that are
        already installed.

        If a version is specified with the requested package, then ``opkg
        install --force-reinstall`` will only be used if the installed version
        matches the requested version.

        .. versionadded:: 2017.7.0


    Multiple Package Installation Options:

    pkgs
        A list of packages to install from a software repository. Must be
        passed as a python list.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install pkgs='["foo", "bar"]'
            salt '*' pkg.install pkgs='["foo", {"bar": "1.2.3-0ubuntu0"}]'

    sources
        A list of IPK packages to install. Must be passed as a list of dicts,
        with the keys being package names, and the values being the source URI
        or local path to the package.  Dependencies are automatically resolved
        and marked as auto-installed.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install sources='[{"foo": "salt://foo.deb"},{"bar": "salt://bar.deb"}]'

    install_recommends
        Whether to install the packages marked as recommended. Default is True.

    only_upgrade
        Only upgrade the packages (disallow downgrades), if they are already
        installed. Default is False.

        .. versionadded:: 2017.7.0

    always_restart_services
        Whether to restart services even if a reboot is required. Default is True.

    Returns a dict containing the new package names and versions::

        {'<package>': {'old': '<old-version>',
                       'new': '<new-version>'}}

def install(name=None,
            refresh=False,
            pkgs=None,
            sources=None,
            reinstall=False,
            **kwargs):
    '''
    Install the passed package, add refresh=True to update the opkg database.

    name
        The name of the package to be installed. Note that this parameter is
        ignored if either "pkgs" or "sources" is passed. Additionally, please
        note that this option can only be used to install packages from a
        software repository. To install a package file manually, use the
        "sources" option.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install <package name>

    refresh
        Whether or not to refresh the package database before installing.

    version
        Install a specific version of the package, e.g. 1.2.3~0ubuntu0. Ignored
        if "pkgs" or "sources" is passed.

        .. versionadded:: 2017.7.0

    reinstall : False
        Specifying reinstall=True will use ``opkg install --force-reinstall``
        rather than simply ``opkg install`` for requested packages that are
        already installed.

        If a version is specified with the requested package, then ``opkg
        install --force-reinstall`` will only be used if the installed version
        matches the requested version.

        .. versionadded:: 2017.7.0


    Multiple Package Installation Options:

    pkgs
        A list of packages to install from a software repository. Must be
        passed as a python list.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install pkgs='["foo", "bar"]'
            salt '*' pkg.install pkgs='["foo", {"bar": "1.2.3-0ubuntu0"}]'

    sources
        A list of IPK packages to install. Must be passed as a list of dicts,
        with the keys being package names, and the values being the source URI
        or local path to the package.  Dependencies are automatically resolved
        and marked as auto-installed.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install sources='[{"foo": "salt://foo.deb"},{"bar": "salt://bar.deb"}]'

    install_recommends
        Whether to install the packages marked as recommended. Default is True.

    only_upgrade
        Only upgrade the packages (disallow downgrades), if they are already
        installed. Default is False.

        .. versionadded:: 2017.7.0

    always_restart_services
        Whether to restart services even if a reboot is required. Default is True.

    Returns a dict containing the new package names and versions::

        {'<package>': {'old': '<old-version>',
                       'new': '<new-version>'}}
    '''
    refreshdb = salt.utils.data.is_true(refresh)

    try:
        pkg_params, pkg_type = __salt__['pkg_resource.parse_targets'](
            name, pkgs, sources, **kwargs
        )
    except MinionError as exc:
        raise CommandExecutionError(exc)

    old = list_pkgs()
    cmd_prefix = ['opkg', 'install']
    to_install = []
    to_reinstall = []
    to_downgrade = []

    _append_noaction_if_testmode(cmd_prefix, **kwargs)
    if not pkg_params:
        return {}
    elif pkg_type == 'file':
        if reinstall:
            cmd_prefix.append('--force-reinstall')
        if not kwargs.get('only_upgrade', False):
            cmd_prefix.append('--force-downgrade')
        to_install.extend(pkg_params)
    elif pkg_type == 'repository':
        if not kwargs.get('install_recommends', True):
            cmd_prefix.append('--no-install-recommends')
        for pkgname, pkgversion in six.iteritems(pkg_params):
            if (name and pkgs is None and kwargs.get('version') and
                    len(pkg_params) == 1):
                # Only use the 'version' param if 'name' was not specified as a
                # comma-separated list
                version_num = kwargs['version']
            else:
                version_num = pkgversion

            if version_num is None:
                # Don't allow downgrades if the version
                # number is not specified.
                if reinstall and pkgname in old:
                    to_reinstall.append(pkgname)
                else:
                    to_install.append(pkgname)
            else:
                pkgstr = '{0}={1}'.format(pkgname, version_num)
                cver = old.get(pkgname, '')
                if reinstall and cver and salt.utils.versions.compare(
                        ver1=version_num,
                        oper='==',
                        ver2=cver,
                        cmp_func=version_cmp):
                    to_reinstall.append(pkgstr)
                elif not cver or salt.utils.versions.compare(
                        ver1=version_num,
                        oper='>=',
                        ver2=cver,
                        cmp_func=version_cmp):
                    to_install.append(pkgstr)
                else:
                    if not kwargs.get('only_upgrade', False):
                        to_downgrade.append(pkgstr)
                    else:
                        # This should cause the command to fail.
                        to_install.append(pkgstr)

    cmds = _build_install_command_list(cmd_prefix, to_install, to_downgrade, to_reinstall)

    if not cmds:
        return {}

    if refreshdb:
        refresh_db()

    errors = []
    is_testmode = _is_testmode(**kwargs)
    test_packages = {}
    for cmd in cmds:
        _execute_install_command(cmd, is_testmode, errors, test_packages)

    __context__.pop('pkg.list_pkgs', None)
    new = list_pkgs()
    if is_testmode:
        new = copy.deepcopy(new)
        new.update(test_packages)

    ret = salt.utils.data.compare_dicts(old, new)

    if pkg_type == 'file' and reinstall:
        # For file-based packages, prepare 'to_reinstall' to have a list
        # of all the package names that may have been reinstalled.
        # This way, we could include reinstalled packages in 'ret'.
        for pkgfile in to_install:
            # Convert from file name to package name.
            cmd = ['opkg', 'info', pkgfile]
            out = __salt__['cmd.run_all'](
                cmd,
                output_loglevel='trace',
                python_shell=False
            )
            if out['retcode'] == 0:
                # Just need the package name.
                pkginfo_dict = _process_info_installed_output(
                    out['stdout'], []
                )
                if pkginfo_dict:
                    to_reinstall.append(list(pkginfo_dict.keys())[0])

    for pkgname in to_reinstall:
        if pkgname not in ret or pkgname in old:
            ret.update({pkgname: {'old': old.get(pkgname, ''),
                                  'new': new.get(pkgname, '')}})

    rs_result = _get_restartcheck_result(errors)

    if errors:
        raise CommandExecutionError(
            'Problem encountered installing package(s)',
            info={'errors': errors, 'changes': ret}
        )

    _process_restartcheck_result(rs_result, **kwargs)

    return ret