Merge branch 'main' into kc.descriptions-docs
This commit is contained in:
commit
1a76d40460
@ -6,8 +6,15 @@ IMPROVEMENTS:
|
|||||||
|
|
||||||
BUG FIXES:
|
BUG FIXES:
|
||||||
|
|
||||||
- provider/virtualbox: De-duplicate machine port forward info [GH-13056]
|
|
||||||
- communicator/ssh: Use netssh builtin keep alive functionality [GH-13069]
|
- 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]
|
- synced_folders/rsync: allow rsync-auto to also ignore relative paths [GH-13066]
|
||||||
|
|
||||||
VAGRANT-GO:
|
VAGRANT-GO:
|
||||||
|
|||||||
@ -6,6 +6,7 @@ require "uri"
|
|||||||
require "vagrant/box_metadata"
|
require "vagrant/box_metadata"
|
||||||
require "vagrant/util/downloader"
|
require "vagrant/util/downloader"
|
||||||
require "vagrant/util/file_checksum"
|
require "vagrant/util/file_checksum"
|
||||||
|
require "vagrant/util/file_mutex"
|
||||||
require "vagrant/util/platform"
|
require "vagrant/util/platform"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
@ -479,12 +480,21 @@ module Vagrant
|
|||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
d.download!
|
mutex_path = d.destination + ".lock"
|
||||||
rescue Errors::DownloaderInterrupted
|
Util::FileMutex.new(mutex_path).with_lock do
|
||||||
# The downloader was interrupted, so just return, because that
|
begin
|
||||||
# means we were interrupted as well.
|
d.download!
|
||||||
@download_interrupted = true
|
rescue Errors::DownloaderInterrupted
|
||||||
env[:ui].info(I18n.t("vagrant.actions.box.download.interrupted"))
|
# 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
|
end
|
||||||
|
|
||||||
Pathname.new(d.destination)
|
Pathname.new(d.destination)
|
||||||
|
|||||||
@ -376,6 +376,10 @@ module Vagrant
|
|||||||
error_key(:dotfile_upgrade_json_error)
|
error_key(:dotfile_upgrade_json_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class DownloadAlreadyInProgress < VagrantError
|
||||||
|
error_key(:download_already_in_progress_error)
|
||||||
|
end
|
||||||
|
|
||||||
class DownloaderError < VagrantError
|
class DownloaderError < VagrantError
|
||||||
error_key(:downloader_error)
|
error_key(:downloader_error)
|
||||||
end
|
end
|
||||||
@ -920,6 +924,10 @@ module Vagrant
|
|||||||
error_key(:uploader_interrupted)
|
error_key(:uploader_interrupted)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class VagrantLocked < VagrantError
|
||||||
|
error_key(:vagrant_locked)
|
||||||
|
end
|
||||||
|
|
||||||
class VagrantInterrupt < VagrantError
|
class VagrantInterrupt < VagrantError
|
||||||
error_key(:interrupted)
|
error_key(:interrupted)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -20,6 +20,7 @@ module Vagrant
|
|||||||
autoload :Experimental, 'vagrant/util/experimental'
|
autoload :Experimental, 'vagrant/util/experimental'
|
||||||
autoload :FileChecksum, 'vagrant/util/file_checksum'
|
autoload :FileChecksum, 'vagrant/util/file_checksum'
|
||||||
autoload :FileMode, 'vagrant/util/file_mode'
|
autoload :FileMode, 'vagrant/util/file_mode'
|
||||||
|
autoload :FileMutex, 'vagrant/util/file_mutex'
|
||||||
autoload :GuestHosts, 'vagrant/util/guest_hosts'
|
autoload :GuestHosts, 'vagrant/util/guest_hosts'
|
||||||
autoload :GuestInspection, 'vagrant/util/guest_inspection'
|
autoload :GuestInspection, 'vagrant/util/guest_inspection'
|
||||||
autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access'
|
autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access'
|
||||||
|
|||||||
31
lib/vagrant/util/file_mutex.rb
Normal file
31
lib/vagrant/util/file_mutex.rb
Normal file
@ -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
|
||||||
@ -139,14 +139,20 @@ module Vagrant
|
|||||||
return @_windows_hyperv_enabled if defined?(@_windows_hyperv_enabled)
|
return @_windows_hyperv_enabled if defined?(@_windows_hyperv_enabled)
|
||||||
|
|
||||||
@_windows_hyperv_enabled = -> {
|
@_windows_hyperv_enabled = -> {
|
||||||
["Get-WindowsOptionalFeature", "Get-WindowsFeature"].each do |cmd_name|
|
check_commands = Array.new.tap do |c|
|
||||||
ps_cmd = "$(#{cmd_name} -FeatureName Microsoft-Hyper-V-Hypervisor).State"
|
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
|
begin
|
||||||
output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
|
output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
|
||||||
return true if output == "Enabled"
|
return true if output == "Enabled"
|
||||||
rescue Errors::PowerShellInvalidVersion
|
rescue Errors::PowerShellInvalidVersion
|
||||||
logger.warn("Invalid PowerShell version detected during Hyper-V enable check")
|
logger.warn("Invalid PowerShell version detected during Hyper-V enable check")
|
||||||
return false
|
return false
|
||||||
|
rescue Errors::PowerShellError
|
||||||
|
logger.warn("Powershell command not found or error on execution of command")
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -404,7 +404,7 @@ module VagrantPlugins
|
|||||||
|
|
||||||
# Set some valid auth methods. We disable the auth methods that
|
# Set some valid auth methods. We disable the auth methods that
|
||||||
# we're not using if we don't have the right auth info.
|
# 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 << "publickey" if ssh_info[:private_key_path]
|
||||||
auth_methods << "password" if ssh_info[:password]
|
auth_methods << "password" if ssh_info[:password]
|
||||||
|
|
||||||
@ -460,6 +460,10 @@ module VagrantPlugins
|
|||||||
connect_opts[:keepalive] = true
|
connect_opts[:keepalive] = true
|
||||||
connect_opts[:keepalive_interval] = 5
|
connect_opts[:keepalive_interval] = 5
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if ssh_info[:password]
|
||||||
|
connect_opts[:non_interactive] = true
|
||||||
|
end
|
||||||
|
|
||||||
@logger.info("Attempting to connect to SSH...")
|
@logger.info("Attempting to connect to SSH...")
|
||||||
@logger.info(" - Host: #{ssh_info[:host]}")
|
@logger.info(" - Host: #{ssh_info[:host]}")
|
||||||
@ -469,7 +473,7 @@ module VagrantPlugins
|
|||||||
@logger.info(" - Key Path: #{ssh_info[:private_key_path]}")
|
@logger.info(" - Key Path: #{ssh_info[:private_key_path]}")
|
||||||
@logger.debug(" - connect_opts: #{connect_opts}")
|
@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
|
ensure
|
||||||
# Make sure we output the connection log
|
# Make sure we output the connection log
|
||||||
@logger.debug("== Net-SSH connection debug-level log START ==")
|
@logger.debug("== Net-SSH connection debug-level log START ==")
|
||||||
|
|||||||
@ -4,7 +4,7 @@ module VagrantPlugins
|
|||||||
module HostArch
|
module HostArch
|
||||||
class Host < Vagrant.plugin("2", :host)
|
class Host < Vagrant.plugin("2", :host)
|
||||||
def detect?(env)
|
def detect?(env)
|
||||||
File.exist?("/etc/arch-release")
|
File.exist?("/etc/arch-release") && !File.exist?("/etc/artix-release")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
require "json"
|
require "json"
|
||||||
|
require "log4r"
|
||||||
|
|
||||||
require "vagrant/util/powershell"
|
require "vagrant/util/powershell"
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ module VagrantPlugins
|
|||||||
|
|
||||||
def initialize(id)
|
def initialize(id)
|
||||||
@vm_id = id
|
@vm_id = id
|
||||||
|
@logger = Log4r::Logger.new("vagrant::hyperv::driver")
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Boolean] Supports VMCX
|
# @return [Boolean] Supports VMCX
|
||||||
@ -294,7 +296,10 @@ module VagrantPlugins
|
|||||||
# @param [String] enhanced session transport type of the VM
|
# @param [String] enhanced session transport type of the VM
|
||||||
# @return [nil]
|
# @return [nil]
|
||||||
def set_enhanced_session_transport_type(transport_type)
|
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
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|||||||
@ -17,8 +17,17 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
} catch {
|
||||||
Write-ErrorMessage "Failed to assign EnhancedSessionTransportType to ${Type}: ${PSItem}"
|
Write-ErrorMessage "Failed to assign EnhancedSessionTransportType to ${Type}:${PSItem}"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,12 +16,6 @@ module VagrantPlugins
|
|||||||
# which will break us out of execution of the middleware sequence.
|
# which will break us out of execution of the middleware sequence.
|
||||||
Driver::Meta.new.verify!
|
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.
|
# Carry on.
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -10,8 +10,8 @@ module VagrantPlugins
|
|||||||
def self.ansible_installed(machine, version)
|
def self.ansible_installed(machine, version)
|
||||||
command = 'test -x "$(command -v ansible)"'
|
command = 'test -x "$(command -v ansible)"'
|
||||||
|
|
||||||
if !version.empty?
|
unless version.empty?
|
||||||
command << "&& ansible --version | grep 'ansible #{version}'"
|
command << "&& [[ $(python3 -c \"import importlib.metadata; print(importlib.metadata.version('ansible'))\") == \"#{version}\" ]]"
|
||||||
end
|
end
|
||||||
|
|
||||||
machine.communicate.test command, sudo: false
|
machine.communicate.test command, sudo: false
|
||||||
|
|||||||
@ -75,7 +75,7 @@ module VagrantPlugins
|
|||||||
raw_output = ""
|
raw_output = ""
|
||||||
|
|
||||||
result = @machine.communicate.execute(
|
result = @machine.communicate.execute(
|
||||||
"ansible --version",
|
"python3 -c \"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))\"",
|
||||||
error_class: Ansible::Errors::AnsibleNotFoundOnGuest,
|
error_class: Ansible::Errors::AnsibleNotFoundOnGuest,
|
||||||
error_key: :ansible_not_found_on_guest) do |type, output|
|
error_key: :ansible_not_found_on_guest) do |type, output|
|
||||||
if type == :stdout && output.lines[0]
|
if type == :stdout && output.lines[0]
|
||||||
|
|||||||
@ -108,8 +108,9 @@ module VagrantPlugins
|
|||||||
end
|
end
|
||||||
|
|
||||||
def gather_ansible_version
|
def gather_ansible_version
|
||||||
raw_output = ""
|
raw_output = ''
|
||||||
command = %w(ansible --version)
|
command = ['python3', '-c',
|
||||||
|
"\"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))\""]
|
||||||
|
|
||||||
command << {
|
command << {
|
||||||
notify: [:stdout, :stderr]
|
notify: [:stdout, :stderr]
|
||||||
|
|||||||
@ -54,6 +54,13 @@ Vagrant.configure("2") do |config|
|
|||||||
# argument is a set of non-required options.
|
# argument is a set of non-required options.
|
||||||
# config.vm.synced_folder "../data", "/vagrant_data"
|
# 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
|
# Provider-specific configuration so you can fine-tune various
|
||||||
# backing providers for Vagrant. These expose provider-specific options.
|
# backing providers for Vagrant. These expose provider-specific options.
|
||||||
# Example for VirtualBox:
|
# Example for VirtualBox:
|
||||||
|
|||||||
@ -895,6 +895,13 @@ en:
|
|||||||
support.
|
support.
|
||||||
|
|
||||||
State file path: %{state_file}
|
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: |-
|
downloader_error: |-
|
||||||
An error occurred while downloading the remote file. The error
|
An error occurred while downloading the remote file. The error
|
||||||
message, if any, is reproduced below. Please fix this error and try
|
message, if any, is reproduced below. Please fix this error and try
|
||||||
@ -1668,6 +1675,11 @@ en:
|
|||||||
uploader_interrupted: |-
|
uploader_interrupted: |-
|
||||||
The upload was interrupted by an external signal. It did not
|
The upload was interrupted by an external signal. It did not
|
||||||
complete.
|
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_exists: |-
|
||||||
`Vagrantfile` already exists in this directory. Remove it before
|
`Vagrantfile` already exists in this directory. Remove it before
|
||||||
running `vagrant init`.
|
running `vagrant init`.
|
||||||
|
|||||||
@ -664,7 +664,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
|||||||
it "includes `none` and `hostbased` auth methods" do
|
it "includes `none` and `hostbased` auth methods" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
nil, nil, hash_including(
|
nil, nil, hash_including(
|
||||||
auth_methods: ["none", "hostbased"]
|
auth_methods: ["none", "hostbased", "keyboard-interactive"]
|
||||||
)
|
)
|
||||||
).and_return(true)
|
).and_return(true)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
@ -780,7 +780,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
|||||||
it "includes `publickey` auth method" do
|
it "includes `publickey` auth method" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
anything, anything, hash_including(
|
anything, anything, hash_including(
|
||||||
auth_methods: ["none", "hostbased", "publickey"]
|
auth_methods: ["none", "hostbased", "keyboard-interactive", "publickey"]
|
||||||
)
|
)
|
||||||
).and_return(true)
|
).and_return(true)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
@ -809,7 +809,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
|||||||
it "has password defined" do
|
it "has password defined" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
anything, anything, hash_including(
|
anything, anything, hash_including(
|
||||||
password: 'vagrant'
|
password: 'vagrant', non_interactive: true
|
||||||
)
|
)
|
||||||
).and_return(true)
|
).and_return(true)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
@ -818,7 +818,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
|||||||
it "includes `password` auth method" do
|
it "includes `password` auth method" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
anything, anything, hash_including(
|
anything, anything, hash_including(
|
||||||
auth_methods: ["none", "hostbased", "password"]
|
auth_methods: ["none", "hostbased", "keyboard-interactive", "password"]
|
||||||
)
|
)
|
||||||
).and_return(true)
|
).and_return(true)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
@ -860,7 +860,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
|||||||
it "includes `publickey` and `password` auth methods" do
|
it "includes `publickey` and `password` auth methods" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
anything, anything, hash_including(
|
anything, anything, hash_including(
|
||||||
auth_methods: ["none", "hostbased", "publickey", "password"]
|
auth_methods: ["none", "hostbased", "keyboard-interactive", "publickey", "password"]
|
||||||
)
|
)
|
||||||
).and_return(true)
|
).and_return(true)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
|
|||||||
@ -328,7 +328,7 @@ describe VagrantPlugins::CommunicatorWinSSH::Communicator do
|
|||||||
it "includes `none` and `hostbased` auth methods" do
|
it "includes `none` and `hostbased` auth methods" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
nil, nil, hash_including(
|
nil, nil, hash_including(
|
||||||
auth_methods: ["none", "hostbased"]
|
auth_methods: ["none", "hostbased", "keyboard-interactive"]
|
||||||
)
|
)
|
||||||
).and_return(connection)
|
).and_return(connection)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
@ -420,7 +420,7 @@ describe VagrantPlugins::CommunicatorWinSSH::Communicator do
|
|||||||
it "includes `publickey` auth method" do
|
it "includes `publickey` auth method" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
anything, anything, hash_including(
|
anything, anything, hash_including(
|
||||||
auth_methods: ["none", "hostbased", "publickey"]
|
auth_methods: ["none", "hostbased", "keyboard-interactive", "publickey"]
|
||||||
)
|
)
|
||||||
).and_return(connection)
|
).and_return(connection)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
@ -458,7 +458,7 @@ describe VagrantPlugins::CommunicatorWinSSH::Communicator do
|
|||||||
it "includes `password` auth method" do
|
it "includes `password` auth method" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
anything, anything, hash_including(
|
anything, anything, hash_including(
|
||||||
auth_methods: ["none", "hostbased", "password"]
|
auth_methods: ["none", "hostbased", "keyboard-interactive", "password"]
|
||||||
)
|
)
|
||||||
).and_return(connection)
|
).and_return(connection)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
@ -500,7 +500,7 @@ describe VagrantPlugins::CommunicatorWinSSH::Communicator do
|
|||||||
it "includes `publickey` and `password` auth methods" do
|
it "includes `publickey` and `password` auth methods" do
|
||||||
expect(Net::SSH).to receive(:start).with(
|
expect(Net::SSH).to receive(:start).with(
|
||||||
anything, anything, hash_including(
|
anything, anything, hash_including(
|
||||||
auth_methods: ["none", "hostbased", "publickey", "password"]
|
auth_methods: ["none", "hostbased", "keyboard-interactive", "publickey", "password"]
|
||||||
)
|
)
|
||||||
).and_return(connection)
|
).and_return(connection)
|
||||||
communicator.send(:connect)
|
communicator.send(:connect)
|
||||||
|
|||||||
@ -71,12 +71,14 @@ VF
|
|||||||
# Class methods for code reuse across examples
|
# Class methods for code reuse across examples
|
||||||
#
|
#
|
||||||
|
|
||||||
def self.it_should_check_ansible_version()
|
def self.it_should_check_ansible_version
|
||||||
it "execute 'ansible --version' before executing 'ansible-playbook'" do
|
it "execute 'Python ansible version check before executing 'ansible-playbook'" do
|
||||||
expect(Vagrant::Util::Subprocess).to receive(:execute).
|
expect(Vagrant::Util::Subprocess).to receive(:execute)
|
||||||
once.with('ansible', '--version', { :notify => [:stdout, :stderr] })
|
.once.with('python3', '-c', "\"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))\"", { notify: %i[
|
||||||
expect(Vagrant::Util::Subprocess).to receive(:execute).
|
stdout stderr
|
||||||
once.with('ansible-playbook', any_args)
|
] })
|
||||||
|
expect(Vagrant::Util::Subprocess).to receive(:execute)
|
||||||
|
.once.with('ansible-playbook', any_args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -326,6 +328,7 @@ VF
|
|||||||
"2.x.y.z": VagrantPlugins::Ansible::COMPATIBILITY_MODE_V2_0,
|
"2.x.y.z": VagrantPlugins::Ansible::COMPATIBILITY_MODE_V2_0,
|
||||||
"4.3.2.1": 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,
|
"[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|
|
valid_versions.each_pair do |ansible_version, mode|
|
||||||
describe "and ansible version #{ansible_version}" do
|
describe "and ansible version #{ansible_version}" do
|
||||||
@ -347,7 +350,7 @@ VF
|
|||||||
"2.9.2.1",
|
"2.9.2.1",
|
||||||
]
|
]
|
||||||
invalid_versions.each do |unknown_ansible_version|
|
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
|
before do
|
||||||
allow(subject).to receive(:gather_ansible_version).and_return(unknown_ansible_version)
|
allow(subject).to receive(:gather_ansible_version).and_return(unknown_ansible_version)
|
||||||
end
|
end
|
||||||
@ -1044,10 +1047,11 @@ VF
|
|||||||
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleCommandFailed)
|
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleCommandFailed)
|
||||||
end
|
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)
|
expect(Vagrant::Util::Subprocess).to receive(:execute)
|
||||||
.once
|
.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)
|
.and_return(default_execute_result)
|
||||||
expect(Vagrant::Util::Subprocess).to receive(:execute)
|
expect(Vagrant::Util::Subprocess).to receive(:execute)
|
||||||
.once
|
.once
|
||||||
|
|||||||
@ -84,6 +84,27 @@ describe Vagrant::Action::Builtin::BoxAdd, :skip_windows, :bsdtar do
|
|||||||
allow(box_collection).to receive(:find).and_return(nil)
|
allow(box_collection).to receive(:find).and_return(nil)
|
||||||
end
|
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
|
context "with box file directly" do
|
||||||
it "adds it" do
|
it "adds it" do
|
||||||
box_path = iso_env.box2_file(:virtualbox)
|
box_path = iso_env.box2_file(:virtualbox)
|
||||||
|
|||||||
81
test/unit/vagrant/util/file_mutex_test.rb
Normal file
81
test/unit/vagrant/util/file_mutex_test.rb
Normal file
@ -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
|
||||||
@ -116,10 +116,11 @@ users, passwords, private keys, etc.).
|
|||||||
By default, Vagrant expects a "vagrant" user to SSH into the machine as.
|
By default, Vagrant expects a "vagrant" user to SSH into the machine as.
|
||||||
This user should be setup with the
|
This user should be setup with the
|
||||||
[insecure keypair](https://github.com/hashicorp/vagrant/tree/main/keys)
|
[insecure keypair](https://github.com/hashicorp/vagrant/tree/main/keys)
|
||||||
that Vagrant uses as a default to attempt to SSH. Also, even though
|
that Vagrant uses as a default to attempt to SSH. It should belong to a
|
||||||
Vagrant uses key-based authentication by default, it is a general convention
|
group named "vagrant". Also, even though Vagrant uses key-based
|
||||||
to set the password for the "vagrant" user to "vagrant". This lets people
|
authentication by default, it is a general convention to set the
|
||||||
login as that user manually if they need to.
|
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
|
To configure SSH access with the insecure keypair, place the public
|
||||||
key into the `~/.ssh/authorized_keys` file for the "vagrant" user. Note
|
key into the `~/.ssh/authorized_keys` file for the "vagrant" user. Note
|
||||||
|
|||||||
@ -20,7 +20,9 @@ and if the provider supports it.
|
|||||||
- `--base NAME` - Instead of packaging a VirtualBox machine that Vagrant
|
- `--base NAME` - Instead of packaging a VirtualBox machine that Vagrant
|
||||||
manages, this will package a VirtualBox machine that VirtualBox manages.
|
manages, this will package a VirtualBox machine that VirtualBox manages.
|
||||||
`NAME` should be the name or UUID of the machine from the VirtualBox GUI.
|
`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,
|
- `--output NAME` - The resulting package will be saved as `NAME`. By default,
|
||||||
it will be saved as `package.box`.
|
it will be saved as `package.box`.
|
||||||
|
|||||||
@ -40,7 +40,7 @@ end
|
|||||||
This will automatically assign an IP address from the reserved address space.
|
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
|
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,
|
machine and using the appropriate command line tool to find the IP,
|
||||||
such as `ifconfig`.
|
such as `ifconfig` or `ip addr show`.
|
||||||
|
|
||||||
## Static IP
|
## Static IP
|
||||||
|
|
||||||
|
|||||||
@ -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.
|
- `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
|
- `linked_clone` (boolean) - Use differencing disk instead of cloning entire VHD. Default: false
|
||||||
- `mac` (string) - MAC address for the guest network interface
|
- `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.
|
- `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.
|
- `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.
|
- `vmname` (string) - Name of virtual machine as shown in Hyper-V manager. Default: Generated name.
|
||||||
|
|||||||
@ -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.
|
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
|
```text
|
||||||
# Generated by Vagrant
|
# 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
|
Note that the generated inventory file is stored as part of your local Vagrant environment in
|
||||||
`.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory`.
|
`.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
|
```text
|
||||||
# Generated by Vagrant
|
# Generated by Vagrant
|
||||||
|
|||||||
@ -27,10 +27,11 @@ end
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you want to upload a folder to your guest system, it can be accomplished by
|
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
|
using a file provisioner seen below. This will copy the your local `folder`
|
||||||
replace `folder` as `newfolder` and place its on the guest machine. Note that if
|
(specified as the `source`) to the the `newfolder` on the guest machine
|
||||||
you'd like the same folder name on your guest machine, make sure that the destination
|
(specified as the `destination`). Note that if you'd like the same folder name
|
||||||
path has the same name as the folder on your host.
|
on your guest machine, make sure that the destination path has the same name as
|
||||||
|
the folder on your host.
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure("2") do |config|
|
||||||
|
|||||||
@ -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
|
to pass to the downloader. For example, a path to a key that the downloader
|
||||||
should use could be specified as `{key: "<path/to/key>"}`. The keys should
|
should use could be specified as `{key: "<path/to/key>"}`. The keys should
|
||||||
be options supported by `curl` using the unshortened form of the flag. For
|
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
|
- `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
|
from the server will not be verified. By default, if the URL is an HTTPS
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
layout: vagrant-cloud
|
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."
|
description: "Organizations are a group of users in Vagrant Cloud that have access and ownership over shared resources."
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user