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"]
 end
 
diff --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. + +
+ Warning! You cannot use your VMware product license as a + Vagrant VMware plugin license. They are separate commercial products, each + requiring their own license. +
+ +After installing the correct Vagrant VMware product plugin for your system, you +will need to install the license. For VMware Fusion users: + +```text +$ vagrant plugin license vagrant-vmware-fusion ~/license.lic +``` + +For VMware Workstation users: + +```text +$ vagrant plugin license vagrant-vmware-workstation ~/license.lic +``` + +The first parameter is the name of the plugin, and the second parameter is the +path to the license file on disk. Please be sure to replace `~/license.lic` +with the path where you temporarily saved the downloaded license file to disk. +After you have installed the plugin license, you may remove the temporary file. + +To verify the license installation, run: + +```text +$ vagrant plugin list +``` + +If the license is not installed correctly, you will see an error message. + + +## Frequently Asked Questions + +**Q: I purchased a Vagrant VMware plugin license, but I did not receive an email?**
+First, please check your JUNK or SPAM folders. Since the license comes from an +automated system, it might have been flagged as spam by your email provider. If +you do not see the email there, please [contact support](mailto:support@hashicorp.com?subject=License Not Received) +and include the original order number. + +**Q: Do you offer trial periods for the Vagrant VMware plugins?**
+We do not offer a trial mechanism at this time, but we do offer a 30-day, no +questions asked, 100% money-back guarantee. If you are not satisfied with the +product, contact us within 30 days and you will receive a full refund. + +**Q: Do you offer educational discounts on the Vagrant VMware plugins?**
+A select number of educational discounts are available for students, staff, and +faculty. Please [contact support](mailto:support@hashicorp.com?subject=Educational Discounts&body=Hello support! I would like to learn more about educational discounts on the Vagrant VMware plugins. Thanks!) for more +information. You will be asked to verify your status as an employee of active +student. + +**Q: Do I need to keep the Vagrant VMware plugin license file on disk?**
+After you have installed the Vagrant VMware plugin license, it is safe to remove +your copy from disk. Vagrant copies the license into its structure for reference +on boot. + +**Q: I lost my original email, where can I download my Vagrant VMware plugin license again?**
+Please [contact support](mailto:support@hashicorp.com?subject=Lost My License&body=Hello support! I seem to have misplaced my Vagrant VMware license. Could you please send it to me? Thanks!). **Note:** +please contact support using the email address with which you made the +original purchase. If you use an alternate email, you will be asked to verify +that you are the owner of the requested license. + +**Q: Where can I find the EULA for the Vagrant VMware plugins?**
+The [EULA for the Vagrant VMware plugins](http://www.vagrantup.com/vmware/eula) +is available on the Vagrant website. + +**Q: Do you offer bulk/volume discounts for the Vagrant VMware plugins?**
+We certainly do! [Email support](mailto:support@hashicorp.com?subject=Bulk Discounts) +with the number of licenses you need and we can give you bulk pricing +information. Please note that bulk pricing requires the purchase of at least 150 +seats. + +**Q: I upgraded my VMware product and now my license is invalid?**
+The Vagrant VMware plugin licenses are valid for specific VMware product +versions at the time of purchase. When new versions of VMware products are +released, significant changes to the plugin code are often required to support +this new version. For this reason, you may need to upgrade your current license +to work with the new version of the VMware product. Customers can check their +license upgrade eligibility by visiting the [License Upgrade Center](http://license.hashicorp.com/upgrade/vmware2014) +and entering the email address with which they made the original purchase. + +Your existing license will continue to work with all previous versions of the +VMware products. If you do not wish to update at this time, you can rollback +your VMware installation to an older version. + +**Q: Why is the Vagrant VMware plugin not working with my trial version of VMware Fusion/Workstation?**
+The Vagrant VMware Fusion and Vagrant VMware Workstation plugins are not +compatible with trial versions of the VMware products. We apologize for the +inconvenience. + +**Q: I accidentally bought the wrong Vagrant VMware plugin, can I switch?**
+Sure! Even though the Vagrant VMware Fusion plugin and the Vagrant VMware +Workstation plugin are different products, they are the same price and fall +under the same EULA. As such, we can transfer the license for you. Please +[contact support](mailto:support@hashicorp.com?subject=Transfer License). + +**Q: Since each license comes with two "seats", can I use one seat for the Vagrant VMware Fusion plugin and one seat for the Vagrant VMware Workstation plugin?**
+Unfortunately this is not permitted. The Vagrant VMware Fusion plugin and the +Vagrant VMware Workstation plugin are separate products and cannot be shared in +this manner. We apologize for the inconvenience. + +**Q: How do I upgrade my currently installed Vagrant VMware plugin?**
+You can update the Vagrant VMware plugin to the latest version by re-running the +install command. For VMware Fusion: + +```text +$ vagrant plugin install vagrant-vmware-fusion +``` + +For VMWare Workstation: + +```text +$ vagrant plugin install vagrant-vmware-workstation +``` + + +## Support +If you have any issues purchasing, installing, or using the Vagrant VMware +plugins, please [contact support](http://www.vagrantup.com/support.html). To +expedite the support process, please include the +[Vagrant debug output](/v2/other/debugging.html) as a Gist or pastebin if +applicable. This will help us more quickly diagnose your issue.