diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec50bf6d..0a830aa41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ BUG FIXES: - core: push configurations are validated with global configs [GH-5130] - guests/funtoo: fix incorrect path in configure networks [GH-4812] - plugins/login: allow users to login with a token [GH-5145] + - providers/hyperv: allow users to configure memory, cpu count, and vmname [GH-5183] + - provisioners/ansible: fix SSH settings to support more than 5 ssh keys [GH-5017] + - provisioners/ansible: increase ansible connection timeout to 30 seconds [GH-5018] ## 1.7.2 (January 6, 2015) diff --git a/lib/vagrant/util/is_port_open.rb b/lib/vagrant/util/is_port_open.rb index e98dd4c24..63652ee28 100644 --- a/lib/vagrant/util/is_port_open.rb +++ b/lib/vagrant/util/is_port_open.rb @@ -29,7 +29,8 @@ module Vagrant # to connect. return true end - rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH + rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, \ + Errno::ENETUNREACH, Errno::EACCES # Any of the above exceptions signal that the port is closed. return false end diff --git a/plugins/providers/hyperv/action/import.rb b/plugins/providers/hyperv/action/import.rb index 0687503af..468a55c57 100644 --- a/plugins/providers/hyperv/action/import.rb +++ b/plugins/providers/hyperv/action/import.rb @@ -14,6 +14,15 @@ module VagrantPlugins def call(env) vm_dir = env[:machine].box.directory.join("Virtual Machines") hd_dir = env[:machine].box.directory.join("Virtual Hard Disks") + memory = env[:machine].provider_config.memory + maxmemory = env[:machine].provider_config.maxmemory + cpus = env[:machine].provider_config.cpus + vmname = env[:machine].provider_config.vmname + + env[:ui].output("Configured Dynamical memory allocation, maxmemory is #{maxmemory}") if maxmemory + env[:ui].output("Configured startup memory is #{memory}") if memory + env[:ui].output("Configured cpus number is #{cpus}") if cpus + env[:ui].output("Configured vmname is #{vmname}") if vmname if !vm_dir.directory? || !hd_dir.directory? raise Errors::BoxInvalid @@ -78,6 +87,10 @@ module VagrantPlugins image_path: image_path.to_s.gsub("/", "\\") } options[:switchname] = switch if switch + options[:memory] = memory if memory + options[:maxmemory] = maxmemory if maxmemory + options[:cpus] = cpus if cpus + options[:vmname] = vmname if vmname env[:ui].detail("Creating and registering the VM...") server = env[:machine].provider.driver.import(options) diff --git a/plugins/providers/hyperv/config.rb b/plugins/providers/hyperv/config.rb index ad69e3059..89b51c0a6 100644 --- a/plugins/providers/hyperv/config.rb +++ b/plugins/providers/hyperv/config.rb @@ -8,15 +8,27 @@ module VagrantPlugins # # @return [Integer] attr_accessor :ip_address_timeout + attr_accessor :memory + attr_accessor :maxmemory + attr_accessor :cpus + attr_accessor :vmname def initialize @ip_address_timeout = UNSET_VALUE + @memory = UNSET_VALUE + @maxmemory = UNSET_VALUE + @cpus = UNSET_VALUE + @vmname = UNSET_VALUE end def finalize! if @ip_address_timeout == UNSET_VALUE @ip_address_timeout = 120 end + @memory = nil if @memory == UNSET_VALUE + @maxmemory = nil if @maxmemory == UNSET_VALUE + @cpus = nil if @cpus == UNSET_VALUE + @vmname = nil if @vmname == UNSET_VALUE end def validate(machine) diff --git a/plugins/providers/hyperv/scripts/import_vm.ps1 b/plugins/providers/hyperv/scripts/import_vm.ps1 index 0b1d74a7e..5aea63875 100644 --- a/plugins/providers/hyperv/scripts/import_vm.ps1 +++ b/plugins/providers/hyperv/scripts/import_vm.ps1 @@ -4,7 +4,11 @@ Param( [Parameter(Mandatory=$true)] [string]$image_path, - [string]$switchname=$null + [string]$switchname=$null, + [string]$memory=$null, + [string]$maxmemory=$null, + [string]$cpus=$null, + [string]$vmname=$null ) # Include the following modules @@ -13,10 +17,22 @@ $Dir = Split-Path $script:MyInvocation.MyCommand.Path [xml]$vmconfig = Get-Content -Path $vm_xml_config -$vm_name = $vmconfig.configuration.properties.name.'#text' -$processors = $vmconfig.configuration.settings.processors.count.'#text' $generation = [int]($vmconfig.configuration.properties.subtype.'#text')+1 +if (!$vmname) { + # Get the name of the vm + $vm_name = $vmconfig.configuration.properties.name.'#text' +}else { + $vm_name = $vmname +} + +if (!$cpus) { + # Get the name of the vm + $processors = $vmconfig.configuration.settings.processors.count.'#text' +}else { + $processors = $cpus +} + function GetUniqueName($name) { Get-VM | ForEach-Object -Process { if ($name -eq $_.Name) { @@ -31,18 +47,34 @@ do { $vm_name = GetUniqueName $name } while ($vm_name -ne $name) -$memory = (Select-Xml -xml $vmconfig -XPath "//memory").node.Bank -if ($memory.dynamic_memory_enabled."#text" -eq "True") { - $dynamicmemory = $True +if (!$memory) { + $xmlmemory = (Select-Xml -xml $vmconfig -XPath "//memory").node.Bank + if ($xmlmemory.dynamic_memory_enabled."#text" -eq "True") { + $dynamicmemory = $True + } + else { + $dynamicmemory = $False + } + # Memory values need to be in bytes + $MemoryMaximumBytes = ($xmlmemory.limit."#text" -as [int]) * 1MB + $MemoryStartupBytes = ($xmlmemory.size."#text" -as [int]) * 1MB + $MemoryMinimumBytes = ($xmlmemory.reservation."#text" -as [int]) * 1MB } else { - $dynamicmemory = $False + if (!$maxmemory){ + $dynamicmemory = $False + $MemoryMaximumBytes = ($memory -as [int]) * 1MB + $MemoryStartupBytes = ($memory -as [int]) * 1MB + $MemoryMinimumBytes = ($memory -as [int]) * 1MB + } + else { + $dynamicmemory = $True + $MemoryMaximumBytes = ($maxmemory -as [int]) * 1MB + $MemoryStartupBytes = ($memory -as [int]) * 1MB + $MemoryMinimumBytes = ($memory -as [int]) * 1MB + } } -# Memory values need to be in bytes -$MemoryMaximumBytes = ($memory.limit."#text" -as [int]) * 1MB -$MemoryStartupBytes = ($memory.size."#text" -as [int]) * 1MB -$MemoryMinimumBytes = ($memory.reservation."#text" -as [int]) * 1MB if (!$switchname) { # Get the name of the virtual switch diff --git a/plugins/provisioners/ansible/provisioner.rb b/plugins/provisioners/ansible/provisioner.rb index eea544abe..9e2cb155b 100644 --- a/plugins/provisioners/ansible/provisioner.rb +++ b/plugins/provisioners/ansible/provisioner.rb @@ -1,3 +1,5 @@ +require "vagrant/util/platform" + module VagrantPlugins module Ansible class Provisioner < Vagrant.plugin("2", :provisioner) @@ -23,6 +25,12 @@ module VagrantPlugins # but can be enabled via raw_arguments option. options << "--connection=ssh" + # Increase the SSH connection timeout, as the Ansible default value (10 seconds) + # is a bit demanding for some overloaded developer boxes. This is particularly + # helpful when additional virtual networks are configured, as their availability + # is not controlled during vagrant boot process. + options << "--timeout=30" + # By default we limit by the current machine, but # this can be overridden by the `limit` option. if config.limit @@ -209,6 +217,12 @@ module VagrantPlugins # Don't access user's known_hosts file, except when host_key_checking is enabled. ssh_options << "-o UserKnownHostsFile=/dev/null" unless config.host_key_checking + # Set IdentitiesOnly=yes to avoid authentication errors when the host has more than 5 ssh keys. + # Notes: + # - Solaris/OpenSolaris/Illumos uses SunSSH which doesn't support the IdentitiesOnly option. + # - this could be improved by sharing logic with lib/vagrant/util/ssh.rb + ssh_options << "-o IdentitiesOnly=yes" unless Vagrant::Util::Platform.solaris? + # Multiple Private Keys @ssh_info[:private_key_path].drop(1).each do |key| ssh_options << "-o IdentityFile=#{key}" diff --git a/plugins/provisioners/chef/cap/omnios/chef_install.rb b/plugins/provisioners/chef/cap/omnios/chef_install.rb new file mode 100644 index 000000000..b20332638 --- /dev/null +++ b/plugins/provisioners/chef/cap/omnios/chef_install.rb @@ -0,0 +1,20 @@ +require_relative "../../omnibus" + +module VagrantPlugins + module Chef + module Cap + module OmniOS + module ChefInstall + def self.chef_install(machine, version, prerelease, download_path) + su_cmd = machine.config.solaris.suexec_cmd + + machine.communicate.execute("#{su_cmd} pkg list --no-refresh web/curl > /dev/null 2>&1 || pkg install -q --accept web/curl") + + command = VagrantPlugins::Chef::Omnibus.build_command(version, prerelease, download_path) + machine.communicate.execute(su_cmd + ' ' + command) + end + end + end + end + end +end diff --git a/plugins/provisioners/chef/cap/omnios/chef_installed.rb b/plugins/provisioners/chef/cap/omnios/chef_installed.rb new file mode 100644 index 000000000..2345d3b6a --- /dev/null +++ b/plugins/provisioners/chef/cap/omnios/chef_installed.rb @@ -0,0 +1,23 @@ +module VagrantPlugins + module Chef + module Cap + module OmniOS + module ChefInstalled + # TODO: this is the same code as cap/linux/chef_installed, consider merging + # Check if Chef is installed at the given version. + # @return [true, false] + def self.chef_installed(machine, version) + knife = "/opt/chef/bin/knife" + command = "test -x #{knife}" + + if version != :latest + command << "&& #{knife} --version | grep 'Chef: #{version}'" + end + + machine.communicate.test(command, sudo: true) + end + end + end + end + end +end diff --git a/plugins/provisioners/chef/plugin.rb b/plugins/provisioners/chef/plugin.rb index 793eb397b..5a1b2876f 100644 --- a/plugins/provisioners/chef/plugin.rb +++ b/plugins/provisioners/chef/plugin.rb @@ -67,6 +67,17 @@ module VagrantPlugins require_relative "cap/redhat/chef_install" Cap::Redhat::ChefInstall end + + guest_capability(:omnios, :chef_installed) do + require_relative "cap/omnios/chef_installed" + Cap::OmniOS::ChefInstalled + end + + guest_capability(:omnios, :chef_install) do + require_relative "cap/omnios/chef_install" + Cap::OmniOS::ChefInstall + end + end end end diff --git a/test/unit/plugins/providers/hyperv/config_test.rb b/test/unit/plugins/providers/hyperv/config_test.rb index 5177dca59..a3c46c619 100644 --- a/test/unit/plugins/providers/hyperv/config_test.rb +++ b/test/unit/plugins/providers/hyperv/config_test.rb @@ -9,10 +9,37 @@ describe VagrantPlugins::HyperV::Config do subject.finalize! expect(subject.ip_address_timeout).to eq(180) end - it "defaults to a number" do subject.finalize! expect(subject.ip_address_timeout).to eq(120) end end + describe "#vmname" do + it "can be set" do + subject.vmname = "test" + subject.finalize! + expect(subject.vmname).to eq("test") + end + end + describe "#memory" do + it "can be set" do + subject.memory = 512 + subject.finalize! + expect(subject.memory).to eq(512) + end + end + describe "#maxmemory" do + it "can be set" do + subject.maxmemory = 1024 + subject.finalize! + expect(subject.maxmemory).to eq(1024) + end + end + describe "#cpus" do + it "can be set" do + subject.cpus = 2 + subject.finalize! + expect(subject.cpus).to eq(2) + end + end end diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index 756f95769..05fa8fae3 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -50,6 +50,7 @@ VF let(:generated_inventory_file) { File.join(generated_inventory_dir, 'vagrant_ansible_inventory') } before do + Vagrant::Util::Platform.stub(solaris?: false) subject.instance_variable_get(:@logger).stub(:debug?).and_return(false) machine.stub(ssh_info: ssh_info) @@ -63,7 +64,7 @@ VF # def self.it_should_set_arguments_and_environment_variables( - expected_args_count = 6, expected_vars_count = 4, expected_host_key_checking = false, expected_transport_mode = "ssh") + expected_args_count = 7, expected_vars_count = 4, expected_host_key_checking = false, expected_transport_mode = "ssh") it "sets implicit arguments in a specific order" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| @@ -72,6 +73,7 @@ VF expect(args[1]).to eq("--private-key=#{machine.ssh_info[:private_key_path][0]}") expect(args[2]).to eq("--user=#{machine.ssh_info[:username]}") expect(args[3]).to eq("--connection=ssh") + expect(args[4]).to eq("--timeout=30") inventory_count = args.count { |x| x =~ /^--inventory-file=.+$/ } expect(inventory_count).to be > 0 @@ -103,10 +105,11 @@ VF cmd_opts = args.last if expected_host_key_checking - expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to be_nil unless config.raw_arguments + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to_not include("-o UserKnownHostsFile=/dev/null") else expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o UserKnownHostsFile=/dev/null") end + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentitiesOnly=yes") expect(cmd_opts[:env]['ANSIBLE_FORCE_COLOR']).to eql("true") expect(cmd_opts[:env]['ANSIBLE_HOST_KEY_CHECKING']).to eql(expected_host_key_checking.to_s) expect(cmd_opts[:env]['PYTHONUNBUFFERED']).to eql(1) @@ -270,7 +273,7 @@ VF config.host_key_checking = true end - it_should_set_arguments_and_environment_variables 6, 3, true + it_should_set_arguments_and_environment_variables 7, 4, true end describe "with boolean (flag) options disabled" do @@ -282,7 +285,7 @@ VF config.sudo_user = 'root' end - it_should_set_arguments_and_environment_variables 7 + it_should_set_arguments_and_environment_variables 8 it_should_set_optional_arguments({ "sudo_user" => "--sudo-user=root" }) it "it does not set boolean flag when corresponding option is set to false" do @@ -311,7 +314,7 @@ VF "--new-arg=yeah"] end - it_should_set_arguments_and_environment_variables 17, 4, false, "paramiko" + it_should_set_arguments_and_environment_variables 18, 4, false, "paramiko" it "sets all raw arguments" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| @@ -367,7 +370,7 @@ VF config.ask_vault_pass = true end - it_should_set_arguments_and_environment_variables 7 + it_should_set_arguments_and_environment_variables 8 it "should ask the vault password" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| @@ -381,7 +384,7 @@ VF config.vault_password_file = existing_file end - it_should_set_arguments_and_environment_variables 7 + it_should_set_arguments_and_environment_variables 8 it "uses the given vault password file" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| @@ -395,7 +398,7 @@ VF config.raw_ssh_args = ['-o ControlMaster=no', '-o ForwardAgent=no'] end - it_should_set_arguments_and_environment_variables 6, 4 + it_should_set_arguments_and_environment_variables 7, 4 it_should_explicitly_enable_ansible_ssh_control_persist_defaults it "passes custom SSH options via ANSIBLE_SSH_ARGS with the highest priority" do @@ -429,7 +432,7 @@ VF ssh_info[:private_key_path] = ['/path/to/my/key', '/an/other/identity', '/yet/an/other/key'] end - it_should_set_arguments_and_environment_variables 6, 4 + it_should_set_arguments_and_environment_variables 7, 4 it_should_explicitly_enable_ansible_ssh_control_persist_defaults it "passes additional Identity Files via ANSIBLE_SSH_ARGS" do @@ -446,7 +449,7 @@ VF ssh_info[:forward_agent] = true end - it_should_set_arguments_and_environment_variables 6, 4 + it_should_set_arguments_and_environment_variables 7, 4 it_should_explicitly_enable_ansible_ssh_control_persist_defaults it "enables SSH-Forwarding via ANSIBLE_SSH_ARGS" do @@ -465,7 +468,7 @@ VF it "shows the ansible-playbook command" do expect(machine.env.ui).to receive(:detail).with { |full_command| - expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml") + expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --timeout=30 --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml") } end end @@ -475,12 +478,12 @@ VF config.verbose = 'v' end - it_should_set_arguments_and_environment_variables 7 + it_should_set_arguments_and_environment_variables 8 it_should_set_optional_arguments({ "verbose" => "-v" }) it "shows the ansible-playbook command" do expect(machine.env.ui).to receive(:detail).with { |full_command| - expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml") + expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --timeout=30 --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml") } end end @@ -513,7 +516,7 @@ VF config.raw_ssh_args = ['-o ControlMaster=no'] end - it_should_set_arguments_and_environment_variables 20, 4, true + it_should_set_arguments_and_environment_variables 21, 4, true it_should_explicitly_enable_ansible_ssh_control_persist_defaults it_should_set_optional_arguments({ "extra_vars" => "--extra-vars=@#{File.expand_path(__FILE__)}", "sudo" => "--sudo", @@ -538,10 +541,84 @@ VF it "shows the ansible-playbook command, with additional quotes when required" do expect(machine.env.ui).to receive(:detail).with { |full_command| - expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentityFile=/my/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/my/key1 --user=testuser --connection=ssh --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --ask-sudo-pass --ask-vault-pass --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task='an awesome task' --why-not --su-user=foot --ask-su-pass --limit='all' playbook.yml") + expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentitiesOnly=yes -o IdentityFile=/my/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/my/key1 --user=testuser --connection=ssh --timeout=30 --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --ask-sudo-pass --ask-vault-pass --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task='an awesome task' --why-not --su-user=foot --ask-su-pass --limit='all' playbook.yml") } end end + # + # Special cases related to the VM provider context + # + + context "with Docker provider on a non-Linux host" do + + let(:fake_host_ssh_info) {{ + private_key_path: ['/path/to/docker/host/key'], + username: 'boot9docker', + host: '127.0.0.1', + port: 2299 + }} + let(:fake_host_vm) { + double("host_vm").tap do |h| + h.stub(ssh_info: fake_host_ssh_info) + end + } + + before do + machine.stub(provider_name: :docker) + machine.provider.stub(host_vm?: true) + machine.provider.stub(host_vm: fake_host_vm) + end + + it "uses an SSH ProxyCommand to reach the VM" do + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + cmd_opts = args.last + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o ProxyCommand='ssh boot9docker@127.0.0.1 -p 2299 -i /path/to/docker/host/key -o Compression=yes -o ConnectTimeout=5 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no exec nc %h %p 2>/dev/null'") + } + end + end + + # + # Special cases related to the Vagrant Host operating system in use + # + + context "with a Solaris-like host" do + before do + Vagrant::Util::Platform.stub(solaris?: true) + end + + it "does not set IdentitiesOnly=yes in ANSIBLE_SSH_ARGS" do + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + cmd_opts = args.last + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to_not include("-o IdentitiesOnly=yes") + + # Note: + # The expectation below is a workaround to a possible misuse (or bug) in RSpec/Ruby stack. + # If 'args' variable is not required by in this block, the "Vagrant::Util::Subprocess).to receive" + # surprisingly expects to receive "no args". + # This problem can be "solved" by using args the "unnecessary" (but harmless) expectation below: + expect(true).to be_true + } + end + + describe "and with host_key_checking option enabled" do + it "does not set ANSIBLE_SSH_ARGS environment variable" do + config.host_key_checking = true + + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + cmd_opts = args.last + expect(cmd_opts[:env]).to_not include('ANSIBLE_SSH_ARGS') + + # Note: + # The expectation below is a workaround to a possible misuse (or bug) in RSpec/Ruby stack. + # If 'args' variable is not required by in this block, the "Vagrant::Util::Subprocess).to receive" + # surprisingly expects to receive "no args". + # This problem can be "solved" by using args the "unnecessary" (but harmless) expectation below: + expect(true).to be_true + } + end + end + + end end end diff --git a/website/docs/source/v2/hyperv/configuration.html.md b/website/docs/source/v2/hyperv/configuration.html.md index 2459c7c0d..18ed9e89c 100644 --- a/website/docs/source/v2/hyperv/configuration.html.md +++ b/website/docs/source/v2/hyperv/configuration.html.md @@ -8,6 +8,15 @@ sidebar_current: "hyperv-configuration" The Hyper-V provider has some provider-specific configuration options you may set. A complete reference is shown below: + * `vmname` (string) - Name of virtual mashine as shown in Hyper-V manager. + Defaults is taken from box image XML. + * `cpus` (integer) - Number of virtual CPU given to mashine. + Defaults is taken from box image XML. + * `memory` (integer) - Number of MegaBytes allocated to VM at startup. + Defaults is taken from box image XML. + * `maxmemory` (integer) - Number of MegaBytes maximal allowed to allocate for VM + This parameter is switch on Dynamic Allocation of memory. + Defaults is taken from box image XML. * `ip_address_timeout` (integer) - The time in seconds to wait for the virtual machine to report an IP address. This defaults to 120 seconds. This may have to be increased if your VM takes longer to boot. diff --git a/website/docs/source/v2/provisioning/ansible.html.md b/website/docs/source/v2/provisioning/ansible.html.md index 9301e0fb8..10fd1fc6d 100644 --- a/website/docs/source/v2/provisioning/ansible.html.md +++ b/website/docs/source/v2/provisioning/ansible.html.md @@ -33,30 +33,30 @@ a single page of documentation. ## Inventory File When using Ansible, it needs to know on which machines a given playbook should run. It does -this by way of an [inventory](http://docs.ansible.com/intro_inventory.html) file which lists those machines. In the context of Vagrant, -there are two ways to approach working with inventory files. +this by way of an [inventory](http://docs.ansible.com/intro_inventory.html) file which lists those machines. +In the context of Vagrant, there are two ways to approach working with inventory files. + +### Auto-Generated Inventory 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 generated inventory file is stored as part of your local Vagrant environment in `.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory`. -The `ansible.groups` option can be used to pass a hash of group -names and group members to be included in the generated inventory file. Group variables -are intentionally not supported, as this practice is not recommended. -For example: +**Groups of Hosts** + +The `ansible.groups` option can be used to pass a hash of group names and group members to be included in the generated inventory file. + +With this configuration example: ``` ansible.groups = { "group1" => ["machine1"], - "group2" => ["machine2", "machine3"], - "all_groups:children" => ["group1", "group2", "group3"] + "group2" => ["machine2"], + "all_groups:children" => ["group1", "group2"] } ``` -Note that unmanaged machines and undefined groups are not added to the inventory. -For example, `group3` in the above example would not be added to the inventory file. - -A generated inventory might look like: +Vagrant would generate an inventory file that might look like: ``` # Generated by Vagrant @@ -75,6 +75,24 @@ group1 group2 ``` +**Notes** + + * The generation of group variables blocks (e.g. `[group1:vars]`) are intentionally not supported, as it is [not recommended to store group variables in the main inventory file](http://docs.ansible.com/intro_inventory.html#splitting-out-host-and-group-specific-data). A good practice is to store these group (or host) variables in `YAML` files stored in `group_vars/` or `host_vars/` directories in the playbook (or inventory) directory. + * Unmanaged machines and undefined groups are not added to the inventory, to avoid useless Ansible errors (e.g. *unreachable host* or *undefined child group*) + +For example, `machine3`, `group3` and `group1:vars` in the example below would not be added to the generated inventory file: + +``` +ansible.groups = { + "group1" => ["machine1"], + "group2" => ["machine2", "machine3"], + "all_groups:children" => ["group1", "group2", "group3"], + "group1:vars" => { "variable1" => 9, "variable2" => "example" } +} +``` + +### Static Inventory + The second option is for situations where you'd like to have more control over the inventory management. With the `ansible.inventory_path` option, you can reference a specific inventory resource (e.g. a static inventory file, a [dynamic inventory script](http://docs.ansible.com/intro_dynamic_inventory.html) or even [multiple inventories stored in the same directory](http://docs.ansible.com/intro_dynamic_inventory.html#using-multiple-inventory-sources)). Vagrant will then use this inventory information instead of generating it. @@ -90,8 +108,10 @@ Where the above IP address is one set in your Vagrantfile: config.vm.network :private_network, ip: "192.168.111.222" ``` -Note that machine names in `Vagrantfile` and `ansible.inventory_path` file should correspond, -unless you use `ansible.limit` option to reference the correct machines. +**Notes:** + + * The machine names in `Vagrantfile` and `ansible.inventory_path` files should correspond, unless you use `ansible.limit` option to reference the correct machines. + * The SSH host addresses (and ports) must obviously be specified twice, in `Vagrantfile` and `ansible.inventory_path` files. ## Playbook @@ -207,6 +227,12 @@ by the sudo command. Vagrant is designed to provision [multi-machine environments](/v2/multi-machine) in sequence, but the following configuration pattern can be used to take advantage of Ansible parallelism: ``` + # By default, Vagrant 1.7+ automatically inserts a different + # insecure keypair for each new VM created. The easiest way + # to use the same keypair for all the machines is to disable + # this feature and rely on the legacy insecure key. + config.ssh.insert_key = false + config.vm.define 'machine2' do |machine| machine.vm.hostname = 'machine2' machine.vm.network "private_network", ip: "192.168.77.22" diff --git a/website/docs/source/v2/synced-folders/rsync.html.md b/website/docs/source/v2/synced-folders/rsync.html.md index bfa322850..0d242676e 100644 --- a/website/docs/source/v2/synced-folders/rsync.html.md +++ b/website/docs/source/v2/synced-folders/rsync.html.md @@ -81,7 +81,7 @@ permissions, use `"--rsync-path='sudo rsync'"` to run rsync with sudo on the gue
Vagrant.configure("2") do |config| config.vm.synced_folder "bin", "/usr/local/bin", type: "rsync", - rsync__exclude: ".git/" + rsync__exclude: ".git/", rsync__args: ["--verbose", "--rsync-path='sudo rsync'", "--archive", "--delete", "-z"] enddiff --git a/website/docs/source/v2/vmware/installation.html.md b/website/docs/source/v2/vmware/installation.html.md index c9a7ca561..972e2266e 100644 --- a/website/docs/source/v2/vmware/installation.html.md +++ b/website/docs/source/v2/vmware/installation.html.md @@ -5,36 +5,149 @@ sidebar_current: "vmware-installation" # Installation -The VMware provider is installed using -[standard plugin installation procedures](/v2/plugins/usage.html). -In addition to installing the plugin, a license must be provided so that -it can be loaded properly. +The Vagrant VMware provider can be installed using the standard plugin +installation procedure. VMware Fusion users should run: -To purchase a license, visit the [Vagrant VMware provider](http://www.vagrantup.com/vmware) -page. After purchasing a license, a link to download it will be emailed -to you. Download this file. - -Installing the plugin and license is easy using the `vagrant plugin` -interface. Both steps are shown below. Note that the plugin name is different -depending on the provider you're using. If you're using the Fusion provider, -it is `vagrant-vmware-fusion`. If you're using the Workstation provider, -it is `vagrant-vmware-workstation`. - -``` +```text $ vagrant plugin install vagrant-vmware-fusion -... -$ vagrant plugin license vagrant-vmware-fusion license.lic -... ``` -For licensing, the first parameter is the name of the plugin, which is -`vagrant-vmware-fusion` for the VMware Fusion provider, or `vagrant-vmware-workstation` -for the VMware Workstation provider. The second parameter is the path to the license itself. +VMware Workstation users should run: -You can verify the license is properly installed by running any -Vagrant command, such as `vagrant plugin list`. The VMware -provider will show an error message if you are missing a license or using an -invalid license. +```text +$ vagrant plugin install vagrant-vmware-workstation +``` -If there are problems installing the plugin, please contact -[support](http://www.vagrantup.com/support.html). +For more information on plugin installation, please see the +[Vagrant plugin usage documentation](/v2/plugins/usage.html). + +The Vagrant VMware plugins are commercial products provided by +[HashiCorp](https://www.hashicorp.com) and **require the purchase of a license** +to operate. To purchase a license, please visit the +[Vagrant VMware provider](http://www.vagrantup.com/vmware#buy-now) page. Upon +purchasing a license, you will receive a license file in your inbox. Download +this file and save it to a temporary location on your computer. + +