docs: 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