def default_provider(**opts)
      opts[:exclude]       = Set.new(opts[:exclude]) if opts[:exclude]
      opts[:force_default] = true if !opts.key?(:force_default)
      opts[:check_usable] = true if !opts.key?(:check_usable)

      # Implement the algorithm from
      # https://www.vagrantup.com/docs/providers/basic_usage.html#default-provider
      # with additional steps 2.5 and 3.5 from
      # https://bugzilla.redhat.com/show_bug.cgi?id=1444492
      # to allow system-configured provider priorities.
      #
      # 1. The --provider flag on a vagrant up is chosen above all else, if it is
      #    present.
      #
      # (Step 1 is done by the caller; this method is only called if --provider
      # wasn't given.)
      #
      # 2. If the VAGRANT_DEFAULT_PROVIDER environmental variable is set, it
      #    takes next priority and will be the provider chosen.

      default = ENV["VAGRANT_DEFAULT_PROVIDER"].to_s
      if default.empty?
        default = nil
      else
        default = default.to_sym
        @logger.debug("Default provider: `#{default}`")
      end

      # If we're forcing the default, just short-circuit and return
      # that (the default behavior)
      if default && opts[:force_default]
        @logger.debug("Using forced default provider: `#{default}`")
        return default
      end

      # Determine the config to use to look for provider definitions. By
      # default it is the global but if we're targeting a specific machine,
      # then look there.
      root_config = vagrantfile.config
      if opts[:machine]
        machine_info = vagrantfile.machine_config(opts[:machine], nil, nil, nil)
        root_config = machine_info[:config]
      end

      # Get the list of providers within our configuration, in order.
      config = root_config.vm.__providers

      # Get the list of usable providers with their internally-declared
      # priorities.
      usable = []
      Vagrant.plugin("2").manager.providers.each do |key, data|
        impl  = data[0]
        popts = data[1]

        # Skip excluded providers
        next if opts[:exclude] && opts[:exclude].include?(key)

        # Skip providers that can't be defaulted, unless they're in our
        # config, in which case someone made our decision for us.
        if !config.include?(key)
          next if popts.key?(:defaultable) && !popts[:defaultable]
        end

        # Skip providers that aren't usable.
        next if opts[:check_usable] && !impl.usable?(false)

        # Each provider sets its own priority, defaulting to 5 so we can trust
        # it's always set.
        usable << [popts[:priority], key]
      end
      @logger.debug("Initial usable provider list: #{usable}")

      # Sort the usable providers by priority. Higher numbers are higher
      # priority, otherwise alpha sort.
      usable = usable.sort {|a, b| a[0] == b[0] ? a[1] <=> b[1] : b[0] <=> a[0]}
                      .map {|prio, key| key}
      @logger.debug("Priority sorted usable provider list: #{usable}")

      # If we're not forcing the default, but it's usable and hasn't been
      # otherwise excluded, return it now.
      if usable.include?(default)
        @logger.debug("Using default provider `#{default}` as it was found in usable list.")
        return default
      end

      # 2.5. Vagrant will go through all of the config.vm.provider calls in the
      #      Vagrantfile and try each in order. It will choose the first
      #      provider that is usable and listed in VAGRANT_PREFERRED_PROVIDERS.

      preferred = ENV.fetch('VAGRANT_PREFERRED_PROVIDERS', '')
                     .split(',')
                     .map {|s| s.strip}
                     .select {|s| !s.empty?}
                     .map {|s| s.to_sym}
      @logger.debug("Preferred provider list: #{preferred}")

      config.each do |key|
        if usable.include?(key) && preferred.include?(key)
          @logger.debug("Using preferred provider `#{key}` detected in configuration and usable.")
          return key
        end
      end

      # 3. Vagrant will go through all of the config.vm.provider calls in the
      #    Vagrantfile and try each in order. It will choose the first provider
      #    that is usable. For example, if you configure Hyper-V, it will never
      #    be chosen on Mac this way. It must be both configured and usable.

      config.each do |key|
        if usable.include?(key)
          @logger.debug("Using provider `#{key}` detected in configuration and usable.")
          return key
        end
      end

      # 3.5. Vagrant will go through VAGRANT_PREFERRED_PROVIDERS and find the
      #      first plugin that reports it is usable.

      preferred.each do |key|
        if usable.include?(key)
          @logger.debug("Using preferred provider `#{key}` found in usable list.")
          return key
        end
      end

      # 4. Vagrant will go through all installed provider plugins (including the
      #    ones that come with Vagrant), and find the first plugin that reports
      #    it is usable. There is a priority system here: systems that are known
      #    better have a higher priority than systems that are worse. For
      #    example, if you have the VMware provider installed, it will always
      #    take priority over VirtualBox.

      if !usable.empty?
        @logger.debug("Using provider `#{usable[0]}` as it is the highest priority in the usable list.")
        return usable[0]
      end

      # 5. If Vagrant still has not found any usable providers, it will error.

      # No providers available is a critical error for Vagrant.
      raise Errors::NoDefaultProvider
    end
def default_provider(**opts)
      opts[:exclude]       = Set.new(opts[:exclude]) if opts[:exclude]
      opts[:force_default] = true if !opts.key?(:force_default)
      opts[:check_usable] = true if !opts.key?(:check_usable)

      # Implement the algorithm from
      # https://www.vagrantup.com/docs/providers/basic_usage.html#default-provider
      # with additional steps 2.5 and 3.5 from
      # https://bugzilla.redhat.com/show_bug.cgi?id=1444492
      # to allow system-configured provider priorities.
      #
      # 1. The --provider flag on a vagrant up is chosen above all else, if it is
      #    present.
      #
      # (Step 1 is done by the caller; this method is only called if --provider
      # wasn't given.)
      #
      # 2. If the VAGRANT_DEFAULT_PROVIDER environmental variable is set, it
      #    takes next priority and will be the provider chosen.

      default = ENV["VAGRANT_DEFAULT_PROVIDER"].to_s
      if default.empty?
        default = nil
      else
        default = default.to_sym
        @logger.debug("Default provider: `#{default}`")
      end

      # If we're forcing the default, just short-circuit and return
      # that (the default behavior)
      if default && opts[:force_default]
        @logger.debug("Using forced default provider: `#{default}`")
        return default
      end

      # Determine the config to use to look for provider definitions. By
      # default it is the global but if we're targeting a specific machine,
      # then look there.
      root_config = vagrantfile.config
      if opts[:machine]
        machine_info = vagrantfile.machine_config(opts[:machine], nil, nil, nil)
        root_config = machine_info[:config]
      end

      # Get the list of providers within our configuration, in order.
      config = root_config.vm.__providers

      # Get the list of usable providers with their internally-declared
      # priorities.
      usable = []
      Vagrant.plugin("2").manager.providers.each do |key, data|
        impl  = data[0]
        popts = data[1]

        # Skip excluded providers
        next if opts[:exclude] && opts[:exclude].include?(key)

        # Skip providers that can't be defaulted, unless they're in our
        # config, in which case someone made our decision for us.
        if !config.include?(key)
          next if popts.key?(:defaultable) && !popts[:defaultable]
        end

        # Skip providers that aren't usable.
        next if opts[:check_usable] && !impl.usable?(false)

        # Each provider sets its own priority, defaulting to 5 so we can trust
        # it's always set.
        usable << [popts[:priority], key]
      end
      @logger.debug("Initial usable provider list: #{usable}")

      # Sort the usable providers by priority. Higher numbers are higher
      # priority, otherwise alpha sort.
      usable = usable.sort {|a, b| a[0] == b[0] ? a[1] <=> b[1] : b[0] <=> a[0]}
                      .map {|prio, key| key}
      @logger.debug("Priority sorted usable provider list: #{usable}")

      # If we're not forcing the default, but it's usable and hasn't been
      # otherwise excluded, return it now.
      if usable.include?(default)
        @logger.debug("Using default provider `#{default}` as it was found in usable list.")
        return default
      end

      # 2.5. Vagrant will go through all of the config.vm.provider calls in the
      #      Vagrantfile and try each in order. It will choose the first
      #      provider that is usable and listed in VAGRANT_PREFERRED_PROVIDERS.

      preferred = ENV.fetch('VAGRANT_PREFERRED_PROVIDERS', '')
                     .split(',')
                     .map {|s| s.strip}
                     .select {|s| !s.empty?}
                     .map {|s| s.to_sym}
      @logger.debug("Preferred provider list: #{preferred}")

      config.each do |key|
        if usable.include?(key) && preferred.include?(key)
          @logger.debug("Using preferred provider `#{key}` detected in configuration and usable.")
          return key
        end
      end

      # 3. Vagrant will go through all of the config.vm.provider calls in the
      #    Vagrantfile and try each in order. It will choose the first provider
      #    that is usable. For example, if you configure Hyper-V, it will never
      #    be chosen on Mac this way. It must be both configured and usable.

      config.each do |key|
        if usable.include?(key)
          @logger.debug("Using provider `#{key}` detected in configuration and usable.")
          return key
        end
      end

      # 3.5. Vagrant will go through VAGRANT_PREFERRED_PROVIDERS and find the
      #      first plugin that reports it is usable.

      preferred.each do |key|
        if usable.include?(key)
          @logger.debug("Using preferred provider `#{key}` found in usable list.")
          return key
        end
      end

      # 4. Vagrant will go through all installed provider plugins (including the
      #    ones that come with Vagrant), and find the first plugin that reports
      #    it is usable. There is a priority system here: systems that are known
      #    better have a higher priority than systems that are worse. For
      #    example, if you have the VMware provider installed, it will always
      #    take priority over VirtualBox.

      if !usable.empty?
        @logger.debug("Using provider `#{usable[0]}` as it is the highest priority in the usable list.")
        return usable[0]
      end

      # 5. If Vagrant still has not found any usable providers, it will error.

      # No providers available is a critical error for Vagrant.
      raise Errors::NoDefaultProvider
    end
This returns the provider name for the default provider for this
 environment.

 @return [Symbol] Name of the default provider.