diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aa3bf1f4..13b35157f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,15 @@ IMPROVEMENTS: BUG FIXES: -- provider/virtualbox: De-duplicate machine port forward info [GH-13056] - communicator/ssh: Use netssh builtin keep alive functionality [GH-13069] +- communicator/ssh: Update connection settings when using a password to connect ssh [GH-13052] +- core: Add a file mutex when downloading box files [GH-13057] +- guest/arch: Support differentiating between Artix and Arch Linux [GH-13055] +- host/windows: Get state of Windows feature "Microsoft-Hyper-V-Hypervisor" [GH-11933] +- provider/virtualbox: De-duplicate machine port forward info [GH-13056] +- provider/virtualbox: Remove check for hyperv being enabled when verifying virtualbox is usable on windows [GH-13090] +- provider/hyperv: Check for hyper-v feature "EnhancedSessionTransportType" [GH-12280] +- provisioner/ansible: Fix installing Ansible provisioner with version and pip [GH-13054] - synced_folders/rsync: allow rsync-auto to also ignore relative paths [GH-13066] VAGRANT-GO: diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index c9307beea..3b5624c4f 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -6,6 +6,7 @@ require "uri" require "vagrant/box_metadata" require "vagrant/util/downloader" require "vagrant/util/file_checksum" +require "vagrant/util/file_mutex" require "vagrant/util/platform" module Vagrant @@ -479,12 +480,21 @@ module Vagrant end begin - d.download! - rescue Errors::DownloaderInterrupted - # The downloader was interrupted, so just return, because that - # means we were interrupted as well. - @download_interrupted = true - env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted")) + mutex_path = d.destination + ".lock" + Util::FileMutex.new(mutex_path).with_lock do + begin + d.download! + rescue Errors::DownloaderInterrupted + # The downloader was interrupted, so just return, because that + # means we were interrupted as well. + @download_interrupted = true + env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted")) + end + end + rescue Errors::VagrantLocked + raise Errors::DownloadAlreadyInProgress, + dest_path: d.destination, + lock_file_path: mutex_path end Pathname.new(d.destination) diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 664da86e5..8e6bb8989 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -376,6 +376,10 @@ module Vagrant error_key(:dotfile_upgrade_json_error) end + class DownloadAlreadyInProgress < VagrantError + error_key(:download_already_in_progress_error) + end + class DownloaderError < VagrantError error_key(:downloader_error) end @@ -920,6 +924,10 @@ module Vagrant error_key(:uploader_interrupted) end + class VagrantLocked < VagrantError + error_key(:vagrant_locked) + end + class VagrantInterrupt < VagrantError error_key(:interrupted) end diff --git a/lib/vagrant/util.rb b/lib/vagrant/util.rb index 4b3e0ff09..8e3cbd2af 100644 --- a/lib/vagrant/util.rb +++ b/lib/vagrant/util.rb @@ -20,6 +20,7 @@ module Vagrant autoload :Experimental, 'vagrant/util/experimental' autoload :FileChecksum, 'vagrant/util/file_checksum' autoload :FileMode, 'vagrant/util/file_mode' + autoload :FileMutex, 'vagrant/util/file_mutex' autoload :GuestHosts, 'vagrant/util/guest_hosts' autoload :GuestInspection, 'vagrant/util/guest_inspection' autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access' diff --git a/lib/vagrant/util/file_mutex.rb b/lib/vagrant/util/file_mutex.rb new file mode 100644 index 000000000..0844726dd --- /dev/null +++ b/lib/vagrant/util/file_mutex.rb @@ -0,0 +1,31 @@ +module Vagrant + module Util + class FileMutex + def initialize(mutex_path) + @mutex_path = mutex_path + end + + def with_lock(&block) + lock + begin + block.call + rescue => e + raise e + ensure + unlock + end + end + + def lock + f = File.open(@mutex_path, "w+") + if f.flock(File::LOCK_EX|File::LOCK_NB) === false + raise Errors::VagrantLocked, lock_file_path: @mutex_path + end + end + + def unlock + File.delete(@mutex_path) if File.file?(@mutex_path) + end + end + end +end diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index c8658e185..6091d84dd 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -139,14 +139,20 @@ module Vagrant return @_windows_hyperv_enabled if defined?(@_windows_hyperv_enabled) @_windows_hyperv_enabled = -> { - ["Get-WindowsOptionalFeature", "Get-WindowsFeature"].each do |cmd_name| - ps_cmd = "$(#{cmd_name} -FeatureName Microsoft-Hyper-V-Hypervisor).State" + check_commands = Array.new.tap do |c| + c << "(Get-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V-Hypervisor -Online).State" + c << "(Get-WindowsFeature -FeatureName Microsoft-Hyper-V-Hypervisor).State" + end + check_commands.each do |ps_cmd| begin output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd) return true if output == "Enabled" rescue Errors::PowerShellInvalidVersion logger.warn("Invalid PowerShell version detected during Hyper-V enable check") return false + rescue Errors::PowerShellError + logger.warn("Powershell command not found or error on execution of command") + return false end end return false diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index 3e660710e..8835b94f2 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -404,7 +404,7 @@ module VagrantPlugins # Set some valid auth methods. We disable the auth methods that # we're not using if we don't have the right auth info. - auth_methods = ["none", "hostbased"] + auth_methods = ["none", "hostbased", "keyboard-interactive"] auth_methods << "publickey" if ssh_info[:private_key_path] auth_methods << "password" if ssh_info[:password] @@ -460,6 +460,10 @@ module VagrantPlugins connect_opts[:keepalive] = true connect_opts[:keepalive_interval] = 5 end + + if ssh_info[:password] + connect_opts[:non_interactive] = true + end @logger.info("Attempting to connect to SSH...") @logger.info(" - Host: #{ssh_info[:host]}") @@ -469,7 +473,7 @@ module VagrantPlugins @logger.info(" - Key Path: #{ssh_info[:private_key_path]}") @logger.debug(" - connect_opts: #{connect_opts}") - Net::SSH.start(ssh_info[:host], ssh_info[:username], connect_opts) + Net::SSH.start(ssh_info[:host], ssh_info[:username], **connect_opts) ensure # Make sure we output the connection log @logger.debug("== Net-SSH connection debug-level log START ==") diff --git a/plugins/hosts/arch/host.rb b/plugins/hosts/arch/host.rb index 0384eb25e..ed6339689 100644 --- a/plugins/hosts/arch/host.rb +++ b/plugins/hosts/arch/host.rb @@ -4,7 +4,7 @@ module VagrantPlugins module HostArch class Host < Vagrant.plugin("2", :host) def detect?(env) - File.exist?("/etc/arch-release") + File.exist?("/etc/arch-release") && !File.exist?("/etc/artix-release") end end end diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 50b2aa842..8fa6e8dd4 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -1,4 +1,5 @@ require "json" +require "log4r" require "vagrant/util/powershell" @@ -26,6 +27,7 @@ module VagrantPlugins def initialize(id) @vm_id = id + @logger = Log4r::Logger.new("vagrant::hyperv::driver") end # @return [Boolean] Supports VMCX @@ -294,7 +296,10 @@ module VagrantPlugins # @param [String] enhanced session transport type of the VM # @return [nil] def set_enhanced_session_transport_type(transport_type) - execute(:set_enhanced_session_transport_type, VmID: vm_id, type: transport_type) + result = execute(:set_enhanced_session_transport_type, VmID: vm_id, type: transport_type) + if !result.nil? + @logger.debug("EnhancedSessionTransportType is not supported by this version of hyperv, ignoring") + end end protected diff --git a/plugins/providers/hyperv/scripts/set_enhanced_session_transport_type.ps1 b/plugins/providers/hyperv/scripts/set_enhanced_session_transport_type.ps1 index 29191db37..6a591816f 100644 --- a/plugins/providers/hyperv/scripts/set_enhanced_session_transport_type.ps1 +++ b/plugins/providers/hyperv/scripts/set_enhanced_session_transport_type.ps1 @@ -17,8 +17,17 @@ try { } try { - Hyper-V\Set-VM -VM $VM -EnhancedSessionTransportType $Type + # HyperV 1.1 (Windows Server 2012R2) crashes on this call. Vagrantfiles before 2.2.10 do break without skipping this. + $present = Get-Command Hyper-V\Set-VM -ParameterName EnhancedSessionTransportType -ErrorAction SilentlyContinue + if($present) { + Hyper-V\Set-VM -VM $VM -EnhancedSessionTransportType $Type + }else{ + $message = @{ + "EnhancedSessionTransportTypeSupportPresent"=$false; + } | ConvertTo-Json + Write-OutputMessage $message + } } catch { - Write-ErrorMessage "Failed to assign EnhancedSessionTransportType to ${Type}: ${PSItem}" + Write-ErrorMessage "Failed to assign EnhancedSessionTransportType to ${Type}:${PSItem}" exit 1 } diff --git a/plugins/providers/virtualbox/action/check_virtualbox.rb b/plugins/providers/virtualbox/action/check_virtualbox.rb index 800852c2a..1ae3eee30 100644 --- a/plugins/providers/virtualbox/action/check_virtualbox.rb +++ b/plugins/providers/virtualbox/action/check_virtualbox.rb @@ -16,12 +16,6 @@ module VagrantPlugins # which will break us out of execution of the middleware sequence. Driver::Meta.new.verify! - if Vagrant::Util::Platform.windows? && Vagrant::Util::Platform.windows_hyperv_enabled? - @logger.error("Virtualbox and Hyper-V cannot be used together at the same time on Windows and will result in a system crash.") - - raise Vagrant::Errors::HypervVirtualBoxError - end - # Carry on. @app.call(env) end diff --git a/plugins/provisioners/ansible/cap/guest/posix/ansible_installed.rb b/plugins/provisioners/ansible/cap/guest/posix/ansible_installed.rb index 329eab8a9..ab171ee5d 100644 --- a/plugins/provisioners/ansible/cap/guest/posix/ansible_installed.rb +++ b/plugins/provisioners/ansible/cap/guest/posix/ansible_installed.rb @@ -10,8 +10,8 @@ module VagrantPlugins def self.ansible_installed(machine, version) command = 'test -x "$(command -v ansible)"' - if !version.empty? - command << "&& ansible --version | grep 'ansible #{version}'" + unless version.empty? + command << "&& [[ $(python3 -c \"import importlib.metadata; print(importlib.metadata.version('ansible'))\") == \"#{version}\" ]]" end machine.communicate.test command, sudo: false diff --git a/plugins/provisioners/ansible/provisioner/guest.rb b/plugins/provisioners/ansible/provisioner/guest.rb index 1474b837b..2e800a999 100644 --- a/plugins/provisioners/ansible/provisioner/guest.rb +++ b/plugins/provisioners/ansible/provisioner/guest.rb @@ -75,7 +75,7 @@ module VagrantPlugins raw_output = "" result = @machine.communicate.execute( - "ansible --version", + "python3 -c \"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))\"", error_class: Ansible::Errors::AnsibleNotFoundOnGuest, error_key: :ansible_not_found_on_guest) do |type, output| if type == :stdout && output.lines[0] diff --git a/plugins/provisioners/ansible/provisioner/host.rb b/plugins/provisioners/ansible/provisioner/host.rb index f2a57133c..ef700f03a 100644 --- a/plugins/provisioners/ansible/provisioner/host.rb +++ b/plugins/provisioners/ansible/provisioner/host.rb @@ -108,8 +108,9 @@ module VagrantPlugins end def gather_ansible_version - raw_output = "" - command = %w(ansible --version) + raw_output = '' + command = ['python3', '-c', + "\"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))\""] command << { notify: [:stdout, :stderr] diff --git a/templates/commands/init/Vagrantfile.erb b/templates/commands/init/Vagrantfile.erb index 5b9bff115..a9b33125d 100644 --- a/templates/commands/init/Vagrantfile.erb +++ b/templates/commands/init/Vagrantfile.erb @@ -54,6 +54,13 @@ Vagrant.configure("2") do |config| # argument is a set of non-required options. # config.vm.synced_folder "../data", "/vagrant_data" + # Disable the default share of the current code directory. Doing this + # provides improved isolation between the vagrant box and your host + # by making sure your Vagrantfile isn't accessable to the vagrant box. + # If you use this you may want to enable additional shared subfolders as + # shown above. + # config.vm.synced_folder ".", "/vagrant", disabled: true + # Provider-specific configuration so you can fine-tune various # backing providers for Vagrant. These expose provider-specific options. # Example for VirtualBox: diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 9e6d7ca16..4a18ff7f6 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -895,6 +895,13 @@ en: support. State file path: %{state_file} + download_already_in_progress_error: |- + Download to global Vagrant location already in progress. This + may be caused by other Vagrant processes attempting to download + a file to the same location. + + Download path: %{dest_path} + Lock file path: %{lock_file_path} downloader_error: |- An error occurred while downloading the remote file. The error message, if any, is reproduced below. Please fix this error and try @@ -1668,6 +1675,11 @@ en: uploader_interrupted: |- The upload was interrupted by an external signal. It did not complete. + vagrant_locked: |- + The requested Vagrant action is locked. This may be caused + by other Vagrant processes attempting to do a similar action. + + Lock file path: %{lock_file_path} vagrantfile_exists: |- `Vagrantfile` already exists in this directory. Remove it before running `vagrant init`. diff --git a/test/unit/plugins/communicators/ssh/communicator_test.rb b/test/unit/plugins/communicators/ssh/communicator_test.rb index 314bceb66..90694923d 100644 --- a/test/unit/plugins/communicators/ssh/communicator_test.rb +++ b/test/unit/plugins/communicators/ssh/communicator_test.rb @@ -664,7 +664,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do it "includes `none` and `hostbased` auth methods" do expect(Net::SSH).to receive(:start).with( nil, nil, hash_including( - auth_methods: ["none", "hostbased"] + auth_methods: ["none", "hostbased", "keyboard-interactive"] ) ).and_return(true) communicator.send(:connect) @@ -780,7 +780,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do it "includes `publickey` auth method" do expect(Net::SSH).to receive(:start).with( anything, anything, hash_including( - auth_methods: ["none", "hostbased", "publickey"] + auth_methods: ["none", "hostbased", "keyboard-interactive", "publickey"] ) ).and_return(true) communicator.send(:connect) @@ -809,7 +809,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do it "has password defined" do expect(Net::SSH).to receive(:start).with( anything, anything, hash_including( - password: 'vagrant' + password: 'vagrant', non_interactive: true ) ).and_return(true) communicator.send(:connect) @@ -818,7 +818,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do it "includes `password` auth method" do expect(Net::SSH).to receive(:start).with( anything, anything, hash_including( - auth_methods: ["none", "hostbased", "password"] + auth_methods: ["none", "hostbased", "keyboard-interactive", "password"] ) ).and_return(true) communicator.send(:connect) @@ -860,7 +860,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do it "includes `publickey` and `password` auth methods" do expect(Net::SSH).to receive(:start).with( anything, anything, hash_including( - auth_methods: ["none", "hostbased", "publickey", "password"] + auth_methods: ["none", "hostbased", "keyboard-interactive", "publickey", "password"] ) ).and_return(true) communicator.send(:connect) diff --git a/test/unit/plugins/communicators/winssh/communicator_test.rb b/test/unit/plugins/communicators/winssh/communicator_test.rb index b0c189f4a..e71e474df 100644 --- a/test/unit/plugins/communicators/winssh/communicator_test.rb +++ b/test/unit/plugins/communicators/winssh/communicator_test.rb @@ -328,7 +328,7 @@ describe VagrantPlugins::CommunicatorWinSSH::Communicator do it "includes `none` and `hostbased` auth methods" do expect(Net::SSH).to receive(:start).with( nil, nil, hash_including( - auth_methods: ["none", "hostbased"] + auth_methods: ["none", "hostbased", "keyboard-interactive"] ) ).and_return(connection) communicator.send(:connect) @@ -420,7 +420,7 @@ describe VagrantPlugins::CommunicatorWinSSH::Communicator do it "includes `publickey` auth method" do expect(Net::SSH).to receive(:start).with( anything, anything, hash_including( - auth_methods: ["none", "hostbased", "publickey"] + auth_methods: ["none", "hostbased", "keyboard-interactive", "publickey"] ) ).and_return(connection) communicator.send(:connect) @@ -458,7 +458,7 @@ describe VagrantPlugins::CommunicatorWinSSH::Communicator do it "includes `password` auth method" do expect(Net::SSH).to receive(:start).with( anything, anything, hash_including( - auth_methods: ["none", "hostbased", "password"] + auth_methods: ["none", "hostbased", "keyboard-interactive", "password"] ) ).and_return(connection) communicator.send(:connect) @@ -500,7 +500,7 @@ describe VagrantPlugins::CommunicatorWinSSH::Communicator do it "includes `publickey` and `password` auth methods" do expect(Net::SSH).to receive(:start).with( anything, anything, hash_including( - auth_methods: ["none", "hostbased", "publickey", "password"] + auth_methods: ["none", "hostbased", "keyboard-interactive", "publickey", "password"] ) ).and_return(connection) communicator.send(:connect) diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index fdf9aa67e..2cb9f7bce 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -71,12 +71,14 @@ VF # Class methods for code reuse across examples # - def self.it_should_check_ansible_version() - it "execute 'ansible --version' before executing 'ansible-playbook'" do - expect(Vagrant::Util::Subprocess).to receive(:execute). - once.with('ansible', '--version', { :notify => [:stdout, :stderr] }) - expect(Vagrant::Util::Subprocess).to receive(:execute). - once.with('ansible-playbook', any_args) + def self.it_should_check_ansible_version + it "execute 'Python ansible version check before executing 'ansible-playbook'" do + expect(Vagrant::Util::Subprocess).to receive(:execute) + .once.with('python3', '-c', "\"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))\"", { notify: %i[ + stdout stderr + ] }) + expect(Vagrant::Util::Subprocess).to receive(:execute) + .once.with('ansible-playbook', any_args) end end @@ -326,6 +328,7 @@ VF "2.x.y.z": VagrantPlugins::Ansible::COMPATIBILITY_MODE_V2_0, "4.3.2.1": VagrantPlugins::Ansible::COMPATIBILITY_MODE_V2_0, "[core 2.11.0]": VagrantPlugins::Ansible::COMPATIBILITY_MODE_V2_0, + "7.1.0": VagrantPlugins::Ansible::COMPATIBILITY_MODE_V2_0 } valid_versions.each_pair do |ansible_version, mode| describe "and ansible version #{ansible_version}" do @@ -347,7 +350,7 @@ VF "2.9.2.1", ] invalid_versions.each do |unknown_ansible_version| - describe "and `ansible --version` returning '#{unknown_ansible_version}'" do + describe "and `ansible version check returning '#{unknown_ansible_version}'" do before do allow(subject).to receive(:gather_ansible_version).and_return(unknown_ansible_version) end @@ -1044,10 +1047,11 @@ VF expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleCommandFailed) end - it "execute three commands: ansible --version, ansible-galaxy, and ansible-playbook" do + it 'execute three commands: Python ansible version check, ansible-galaxy, and ansible-playbook' do expect(Vagrant::Util::Subprocess).to receive(:execute) .once - .with('ansible', '--version', { :notify => [:stdout, :stderr] }) + .with('python3', '-c', + "\"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))\"", { notify: %i[stdout stderr] }) .and_return(default_execute_result) expect(Vagrant::Util::Subprocess).to receive(:execute) .once diff --git a/test/unit/vagrant/action/builtin/box_add_test.rb b/test/unit/vagrant/action/builtin/box_add_test.rb index 67652d501..a28bcb16a 100644 --- a/test/unit/vagrant/action/builtin/box_add_test.rb +++ b/test/unit/vagrant/action/builtin/box_add_test.rb @@ -84,6 +84,27 @@ describe Vagrant::Action::Builtin::BoxAdd, :skip_windows, :bsdtar do allow(box_collection).to receive(:find).and_return(nil) end + context "the download location is locked" do + let(:box_path) { iso_env.box2_file(:virtualbox) } + let(:mutex_path) { env[:tmp_path].join("box" + Digest::SHA1.hexdigest("file://" + box_path.to_s) + ".lock").to_s } + + before do + # Lock file + @f = File.open(mutex_path, "w+") + @f.flock(File::LOCK_EX|File::LOCK_NB) + end + + after { @f.close } + + it "raises a download error" do + env[:box_name] = "foo" + env[:box_url] = box_path.to_s + + expect { subject.call(env) }. + to raise_error(Vagrant::Errors::DownloadAlreadyInProgress) + end + end + context "with box file directly" do it "adds it" do box_path = iso_env.box2_file(:virtualbox) diff --git a/test/unit/vagrant/util/file_mutex_test.rb b/test/unit/vagrant/util/file_mutex_test.rb new file mode 100644 index 000000000..eacbd9ffd --- /dev/null +++ b/test/unit/vagrant/util/file_mutex_test.rb @@ -0,0 +1,81 @@ +require File.expand_path("../../../base", __FILE__) +require 'vagrant/util/file_mutex' + +describe Vagrant::Util::FileMutex do + include_context "unit" + + let(:temp_dir) { Dir.mktmpdir("vagrant-test-util-mutex_test") } + + after do + FileUtils.rm_rf(temp_dir) + end + + it "should create a lock file" do + mutex_path = temp_dir + "test.lock" + instance = described_class.new(mutex_path) + instance.lock + expect(File).to exist(mutex_path) + end + + it "should create and delete lock file" do + mutex_path = temp_dir + "test.lock" + instance = described_class.new(mutex_path) + instance.lock + expect(File).to exist(mutex_path) + instance.unlock + expect(File).to_not exist(mutex_path) + end + + it "should not raise an error if the lock file does not exist" do + mutex_path = temp_dir + "test.lock" + instance = described_class.new(mutex_path) + instance.unlock + expect(File).to_not exist(mutex_path) + end + + it "should run a function with a lock" do + mutex_path = temp_dir + "test.lock" + instance = described_class.new(mutex_path) + instance.with_lock { true } + expect(File).to_not exist(mutex_path) + end + + it "should fail running a function when locked" do + mutex_path = temp_dir + "test.lock" + # create a lock + instance = described_class.new(mutex_path) + instance.lock + # create a new lock that will run a function + instance2 = described_class.new(mutex_path) + # lock should persist for multiple runs + expect {instance2.with_lock { true }}. + to raise_error(Vagrant::Errors::VagrantLocked) + expect {instance2.with_lock { true }}. + to raise_error(Vagrant::Errors::VagrantLocked) + # mutex should exist until its unlocked + expect(File).to exist(mutex_path) + instance.unlock + expect(File).to_not exist(mutex_path) + end + + it "should fail running a function within a locked" do + mutex_path = temp_dir + "test.lock" + # create a lock + instance = described_class.new(mutex_path) + # create a new lock that will run a function + instance2 = described_class.new(mutex_path) + expect { + instance.with_lock { instance2.with_lock{true} } + }.to raise_error(Vagrant::Errors::VagrantLocked) + expect(File).to_not exist(mutex_path) + end + + it "should delete the lock even when the function fails" do + mutex_path = temp_dir + "test.lock" + instance = described_class.new(mutex_path) + expect { + instance.with_lock { raise Vagrant::Errors::VagrantError.new } + }.to raise_error(Vagrant::Errors::VagrantError) + expect(File).to_not exist(mutex_path) + end +end diff --git a/website/content/docs/boxes/base.mdx b/website/content/docs/boxes/base.mdx index f6d352757..c32f50b5e 100644 --- a/website/content/docs/boxes/base.mdx +++ b/website/content/docs/boxes/base.mdx @@ -116,10 +116,11 @@ users, passwords, private keys, etc.). By default, Vagrant expects a "vagrant" user to SSH into the machine as. This user should be setup with the [insecure keypair](https://github.com/hashicorp/vagrant/tree/main/keys) -that Vagrant uses as a default to attempt to SSH. Also, even though -Vagrant uses key-based authentication by default, it is a general convention -to set the password for the "vagrant" user to "vagrant". This lets people -login as that user manually if they need to. +that Vagrant uses as a default to attempt to SSH. It should belong to a +group named "vagrant". Also, even though Vagrant uses key-based +authentication by default, it is a general convention to set the +password for the "vagrant" user to "vagrant". This lets people login as +that user manually if they need to. To configure SSH access with the insecure keypair, place the public key into the `~/.ssh/authorized_keys` file for the "vagrant" user. Note diff --git a/website/content/docs/cli/package.mdx b/website/content/docs/cli/package.mdx index c93362d3d..1bae2dfcf 100644 --- a/website/content/docs/cli/package.mdx +++ b/website/content/docs/cli/package.mdx @@ -20,7 +20,9 @@ and if the provider supports it. - `--base NAME` - Instead of packaging a VirtualBox machine that Vagrant manages, this will package a VirtualBox machine that VirtualBox manages. `NAME` should be the name or UUID of the machine from the VirtualBox GUI. - Currently this option is only available for VirtualBox. + Currently this option is only available for VirtualBox. + **In a multi-machine environment, the UUID is required.** This info can be + gathered in two different ways `ls -l ~/VirtualBox\ VMs` or `vboxmanage list vms`. - `--output NAME` - The resulting package will be saved as `NAME`. By default, it will be saved as `package.box`. diff --git a/website/content/docs/networking/private_network.mdx b/website/content/docs/networking/private_network.mdx index f52b06cbe..79770e5c9 100644 --- a/website/content/docs/networking/private_network.mdx +++ b/website/content/docs/networking/private_network.mdx @@ -40,7 +40,7 @@ end This will automatically assign an IP address from the reserved address space. The IP address can be determined by using `vagrant ssh` to SSH into the machine and using the appropriate command line tool to find the IP, -such as `ifconfig`. +such as `ifconfig` or `ip addr show`. ## Static IP diff --git a/website/content/docs/providers/hyperv/configuration.mdx b/website/content/docs/providers/hyperv/configuration.mdx index 7bc4c8790..3fab824f2 100644 --- a/website/content/docs/providers/hyperv/configuration.mdx +++ b/website/content/docs/providers/hyperv/configuration.mdx @@ -22,7 +22,7 @@ you may set. A complete reference is shown below: - `ip_address_timeout` (integer) - Number of seconds to wait for the VM to report an IP address. Default: 120. - `linked_clone` (boolean) - Use differencing disk instead of cloning entire VHD. Default: false - `mac` (string) - MAC address for the guest network interface -- `maxmemory` (integer) - Maximum number of megabytes allowed to be allocated for the VM. When set Dynamic Memory Allocation will be enabled. +- `maxmemory` (integer) - Maximum number of megabytes allowed to be allocated for the VM. When set Dynamic Memory Allocation will be enabled. Set to `nil` to disable Dynamic Memory. - `memory` (integer) - Number of megabytes allocated to VM at startup. If `maxmemory` is set, this will be amount of memory allocated at startup. - `vlan_id` (integer) - VLAN ID for the guest network interface. - `vmname` (string) - Name of virtual machine as shown in Hyper-V manager. Default: Generated name. diff --git a/website/content/docs/provisioning/ansible_intro.mdx b/website/content/docs/provisioning/ansible_intro.mdx index 0c834840d..326a2b9a2 100644 --- a/website/content/docs/provisioning/ansible_intro.mdx +++ b/website/content/docs/provisioning/ansible_intro.mdx @@ -89,7 +89,9 @@ When using Ansible, it needs to know on which machines a given playbook should r The first and simplest option is to not provide one to Vagrant at all. Vagrant will generate an inventory file encompassing all of the virtual machines it manages, and use it for provisioning machines. -#### Example with the [`ansible`](/vagrant/docs/provisioning/ansible) provisioner +#### Ansible provisioner example + +Example with the [`ansible`](/vagrant/docs/provisioning/ansible) provisioner. ```text # Generated by Vagrant @@ -100,7 +102,9 @@ default ansible_host=127.0.0.1 ansible_port=2200 ansible_user='vagrant' ansible_ Note that the generated inventory file is stored as part of your local Vagrant environment in `.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory`. -#### Example with the [`ansible_local`](/vagrant/docs/provisioning/ansible_local) provisioner +#### Ansible local provision + +Example with the [`ansible_local`](/vagrant/docs/provisioning/ansible_local) provisioner ```text # Generated by Vagrant diff --git a/website/content/docs/provisioning/file.mdx b/website/content/docs/provisioning/file.mdx index aae5e7fd3..a49309d91 100644 --- a/website/content/docs/provisioning/file.mdx +++ b/website/content/docs/provisioning/file.mdx @@ -27,10 +27,11 @@ end ``` If you want to upload a folder to your guest system, it can be accomplished by -using a file provisioner seen below. When copied, the resulting folder on the guest will -replace `folder` as `newfolder` and place its on the guest machine. Note that if -you'd like the same folder name on your guest machine, make sure that the destination -path has the same name as the folder on your host. +using a file provisioner seen below. This will copy the your local `folder` +(specified as the `source`) to the the `newfolder` on the guest machine +(specified as the `destination`). Note that if you'd like the same folder name +on your guest machine, make sure that the destination path has the same name as +the folder on your host. ```ruby Vagrant.configure("2") do |config| diff --git a/website/content/docs/vagrantfile/machine_settings.mdx b/website/content/docs/vagrantfile/machine_settings.mdx index 4a437f03c..4a59d81ea 100644 --- a/website/content/docs/vagrantfile/machine_settings.mdx +++ b/website/content/docs/vagrantfile/machine_settings.mdx @@ -76,7 +76,9 @@ the name of the synced folder plugin. to pass to the downloader. For example, a path to a key that the downloader should use could be specified as `{key: ""}`. The keys should be options supported by `curl` using the unshortened form of the flag. For - example, use `append` instead of `a`. + example, use `append` instead of `a`. To pass a curl option that does not + accept a value, include the option in the map with the value `true`. For + example specify the `--fail` flag as `{fail: true}`. - `config.vm.box_download_insecure` (boolean) - If true, then SSL certificates from the server will not be verified. By default, if the URL is an HTTPS diff --git a/website/content/vagrant-cloud/organizations/index.mdx b/website/content/vagrant-cloud/organizations/index.mdx index a2baeca30..c26bcb9a2 100755 --- a/website/content/vagrant-cloud/organizations/index.mdx +++ b/website/content/vagrant-cloud/organizations/index.mdx @@ -1,6 +1,6 @@ --- layout: vagrant-cloud -page_page_title: Organizations in Vagrant Cloud +page_title: Organizations in Vagrant Cloud description: "Organizations are a group of users in Vagrant Cloud that have access and ownership over shared resources." ---