diff --git a/CHANGELOG.md b/CHANGELOG.md index a4f320aa9..06c06bd6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ FEATURES: - Added a `working_directory` configuration option to the Puppet apply provisioner so you can specify the working directory when `puppet` is called, making it friendly to Hiera data and such. [GH-1670] + - Ability to specify the host IP to bind forwarded ports to. [GH-1785] IMPROVEMENTS: @@ -18,6 +19,14 @@ IMPROVEMENTS: within an LXC container works properly now. - Allow strings in addition to symbols to more places in V1 configuration as well as V2 configuration. + - Add `ARPCHECK=0` to RedHat OS family network configuration. [GH-1815] + - Add SSH agent forwarding sample to initial Vagrantfile. [GH-1808] + - VirtualBox: Only configure networks if there are any to configure. + This allows linux's that don't implement this capability to work with + Vagrant. [GH-1796] + - Default SSH forwarded port now binds to 127.0.0.1 so only local + connections are allowed. [GH-1785] + - Use `netctl` for Arch Linux network configuration. [GH-1760] BUG FIXES: @@ -27,6 +36,12 @@ BUG FIXES: defined. [GH-1665] - Finding V1 boxes now works properly again to avoid "box not found" errors. [GH-1691] + - Setting hostname on SLES 11 works again. [GH-1781] + - `config.vm.guest` properly forces guests again. [GH-1800] + - The `read_ip_address` capability for linux properly reads the IP + of only the first network interface. [GH-1799] + - Validate that an IP is given for a private network. [GH-1788] + - Fix uninitialized constant error for Gentoo plugin. [GH-1698] ## 1.2.2 (April 23, 2013) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..fc5d3c576 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,41 @@ +# How to contribute + +We like to encourage you to contribute to the repository. +This should be as easy as possible for you but there are a few things to consider when contributing. +The following guidelines for contribution should be followed if you want to submit a pull request. + +## How to prepare + +* You need a [GitHub account](https://github.com/signup/free) +* Submit an [issue ticket](https://github.com/mitchellh/vagrant/issues) for your issue if the is no one yet. + * Describe the issue and include steps to reproduce when it's a bug. + * Ensure to mention the earliest version that you know is affected. + * If you plan on submitting a bug report, please submit debug-level logs along + with the report using [gist](https://gist.github.com/) or some other paste + service by prepending `VAGRANT_LOG=debug` to your `vagrant` commands. +* Fork the repository on GitHub + +## Make Changes + +* In your forked repository, create a topic branch for your upcoming patch. + * Usually this is based on the master branch. + * Create a branch based on master; `git branch + fix/master/my_contribution master` then checkout the new branch with `git + checkout fix/master/my_contribution`. Please avoid working directly on the `master` branch. +* Make commits of logical units and describe them properly. +* Check for unnecessary whitespace with `git diff --check` before committing. + +* If possible, submit tests to your patch / new feature so it can be tested easily. +* Assure nothing is broken by running all the tests. + +## Submit Changes + +* Push your changes to a topic branch in your fork of the repository. +* Open a pull request to the original repository and choose the right original branch you want to patch. +* If not done in commit messages (which you really should do) please reference and update your issue with the code changes. +* Even if you have write access to the repository, do not directly push or merge pull-requests. Let another team member review your pull request and approve. + +# Additional Resources + +* [General GitHub documentation](http://help.github.com/) +* [GitHub pull request documentation](http://help.github.com/send-pull-requests/) diff --git a/config/default.rb b/config/default.rb index 099ff55ab..fa88c2cd5 100644 --- a/config/default.rb +++ b/config/default.rb @@ -17,12 +17,12 @@ Vagrant.configure("2") do |config| config.vm.client_cert = nil config.vm.graceful_halt_retry_count = 60 config.vm.graceful_halt_retry_interval = 1 - config.vm.guest = :linux # Share SSH locally by default config.vm.network :forwarded_port, guest: 22, host: 2222, + host_ip: "127.0.0.1", id: "ssh", auto_correct: true diff --git a/contrib/bash/completion.sh b/contrib/bash/completion.sh index 40d12d3fb..fb6fc508a 100644 --- a/contrib/bash/completion.sh +++ b/contrib/bash/completion.sh @@ -1,3 +1,31 @@ # Autocompletion for Vagrant just put this line in your ~/.profile or link this file into it like: # source /path/to/vagrant/contrib/bash/completion.sh -complete -W "$(echo `vagrant --help | awk '/^ /{print $1}'`;)" vagrant +_vagrant() { + + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + preprev="${COMP_WORDS[COMP_CWORD-2]}" + + commands=$(vagrant --help | awk '/^ /{print $1}') + + if [ $COMP_CWORD == 1 ] ; then + COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) ) + return 0 + fi + + if [ $COMP_CWORD == 2 ] ; then + local sub_commands=$(vagrant $prev --help | awk '/^ /{print $1}') + COMPREPLY=( $(compgen -W "${sub_commands}" -- ${cur}) ) + return 0 + fi + + if [[ ${cur} == -* ]] ; then + local command_opts=$(vagrant $preprev $prev --help | grep -E -o "((-\w{1}|--(\w|-)*=?)){1,2}") + COMPREPLY=( $(compgen -W "${command_opts}" -- ${cur}) ) + return 0 + fi +} + +complete -F _vagrant vagrant + +# /* vim: set filetype=sh : */ diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 1377464bb..dc24536d3 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -163,6 +163,14 @@ module Vagrant error_key(:cli_invalid_options) end + class CommandUnavailable < VagrantError + error_key(:command_unavailable) + end + + class CommandUnavailableWindows < VagrantError + error_key(:command_unavailable_windows) + end + class ConfigInvalid < VagrantError error_key(:config_invalid) end diff --git a/lib/vagrant/guest.rb b/lib/vagrant/guest.rb index ad4f06ecb..1c0dab158 100644 --- a/lib/vagrant/guest.rb +++ b/lib/vagrant/guest.rb @@ -69,7 +69,16 @@ module Vagrant guest_info = @guests[name] guest = guest_info[0].new - if guest.detect?(@machine) + # If a specific guest was specified, then attempt to use that + # guest no matter what. Otherwise, only use it if it was detected. + use_this_guest = false + if @machine.config.vm.guest.nil? + use_this_guest = guest.detect?(@machine) + else + use_this_guest = @machine.config.vm.guest.to_sym == name.to_sym + end + + if use_this_guest @logger.info("Detected: #{name}!") @chain << [name, guest] @name = name diff --git a/lib/vagrant/util/subprocess.rb b/lib/vagrant/util/subprocess.rb index 4379304b8..f733ed3ce 100644 --- a/lib/vagrant/util/subprocess.rb +++ b/lib/vagrant/util/subprocess.rb @@ -5,6 +5,7 @@ require 'log4r' require 'vagrant/util/platform' require 'vagrant/util/safe_chdir' +require 'vagrant/util/which' module Vagrant module Util @@ -26,6 +27,12 @@ module Vagrant def initialize(*command) @options = command.last.is_a?(Hash) ? command.pop : {} @command = command + @command[0] = Which.which(@command[0]) if !File.file? @command[0] + if !@command[0] + raise Errors::CommandUnavailableWindows, file: command[0] if Platform.windows? + raise Errors::CommandUnavailable, file: command[0] + end + @logger = Log4r::Logger.new("vagrant::util::subprocess") end diff --git a/plugins/commands/status/command.rb b/plugins/commands/status/command.rb index 6c11ae400..90b7b8584 100644 --- a/plugins/commands/status/command.rb +++ b/plugins/commands/status/command.rb @@ -16,7 +16,7 @@ module VagrantPlugins results = [] with_target_vms(argv) do |machine| state = machine.state if !state - results << "#{machine.name.to_s.ljust(25)}#{machine.state.short_description} (#{machine.provider_name})" + results << "#{machine.name.to_s.ljust(25)} #{machine.state.short_description} (#{machine.provider_name})" end message = nil diff --git a/plugins/guests/arch/cap/configure_networks.rb b/plugins/guests/arch/cap/configure_networks.rb index 11fda5ded..a7cbfd5a3 100644 --- a/plugins/guests/arch/cap/configure_networks.rb +++ b/plugins/guests/arch/cap/configure_networks.rb @@ -13,8 +13,9 @@ module VagrantPlugins temp.close machine.communicate.upload(temp.path, "/tmp/vagrant_network") - machine.communicate.sudo("mv /tmp/vagrant_network /etc/network.d/interfaces/eth#{network[:interface]}") - machine.communicate.sudo("netcfg interfaces/eth#{network[:interface]}") + machine.communicate.sudo("ln -sf /dev/null /etc/udev/rules.d/80-net-name-slot.rules") + machine.communicate.sudo("mv /tmp/vagrant_network /etc/netctl/eth#{network[:interface]}") + machine.communicate.sudo("netctl start eth#{network[:interface]}") end end end diff --git a/plugins/guests/gentoo/cap/change_host_name.rb b/plugins/guests/gentoo/cap/change_host_name.rb index 4c0f50d8f..a8112b7d5 100644 --- a/plugins/guests/gentoo/cap/change_host_name.rb +++ b/plugins/guests/gentoo/cap/change_host_name.rb @@ -1,5 +1,5 @@ module VagrantPlugins - module GuestFreeBSD + module GuestGentoo module Cap class ChangeHostName def self.change_host_name(machine, name) diff --git a/plugins/guests/gentoo/cap/configure_networks.rb b/plugins/guests/gentoo/cap/configure_networks.rb index ce7883f8c..ad534b437 100644 --- a/plugins/guests/gentoo/cap/configure_networks.rb +++ b/plugins/guests/gentoo/cap/configure_networks.rb @@ -3,9 +3,9 @@ require "tempfile" require "vagrant/util/template_renderer" module VagrantPlugins - module GuestFreeBSD + module GuestGentoo module Cap - class ChangeHostName + class ConfigureNetworks include Vagrant::Util def self.configure_networks(machine, networks) diff --git a/plugins/guests/linux/cap/read_ip_address.rb b/plugins/guests/linux/cap/read_ip_address.rb index 0eaffccbf..c6adc9e16 100644 --- a/plugins/guests/linux/cap/read_ip_address.rb +++ b/plugins/guests/linux/cap/read_ip_address.rb @@ -3,13 +3,13 @@ module VagrantPlugins module Cap class ReadIPAddress def self.read_ip_address(machine) - command = "ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}'" + command = "ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1 }'" result = "" machine.communicate.execute(command) do |type, data| result << data if type == :stdout end - result.chomp + result.chomp.split("\n").first end end end diff --git a/plugins/guests/redhat/cap/configure_networks.rb b/plugins/guests/redhat/cap/configure_networks.rb index 227fecfa6..e028fdfc9 100644 --- a/plugins/guests/redhat/cap/configure_networks.rb +++ b/plugins/guests/redhat/cap/configure_networks.rb @@ -48,7 +48,7 @@ module VagrantPlugins retryable(:on => Vagrant::Errors::VagrantError, :tries => 3, :sleep => 2) do machine.communicate.sudo("/sbin/ifdown eth#{interface} 2> /dev/null", :error_check => false) machine.communicate.sudo("cat /tmp/vagrant-network-entry_#{interface} >> #{network_scripts_dir}/ifcfg-eth#{interface}") - machine.communicate.sudo("/sbin/ifup eth#{interface} 2> /dev/null") + machine.communicate.sudo("ARPCHECK=no /sbin/ifup eth#{interface} 2> /dev/null") end machine.communicate.sudo("rm /tmp/vagrant-network-entry_#{interface}") diff --git a/plugins/guests/solaris/guest.rb b/plugins/guests/solaris/guest.rb index e0eab6709..4256c61cd 100644 --- a/plugins/guests/solaris/guest.rb +++ b/plugins/guests/solaris/guest.rb @@ -7,7 +7,7 @@ module VagrantPlugins # Contributed by Blake Irvin class Guest < Vagrant.plugin("2", :guest) def detect?(machine) - machine.communicate.test("uname -o | grep Solaris") + machine.communicate.test("uname -s | grep SunOS") end end end diff --git a/plugins/guests/suse/cap/change_host_name.rb b/plugins/guests/suse/cap/change_host_name.rb index 3616171bf..a8ba242d7 100644 --- a/plugins/guests/suse/cap/change_host_name.rb +++ b/plugins/guests/suse/cap/change_host_name.rb @@ -6,7 +6,7 @@ module VagrantPlugins machine.communicate.tap do |comm| # Only do this if the hostname is not already set if !comm.test("sudo hostname | grep '#{name}'") - comm.sudo("sed -i 's/\\(HOSTNAME=\\).*/\\1#{name}/' /etc/sysconfig/network") + comm.sudo("echo #{name} > /etc/HOSTNAME") comm.sudo("hostname #{name}") comm.sudo("sed -i 's@^\\(127[.]0[.]0[.]1[[:space:]]\\+\\)@\\1#{name} #{name.split('.')[0]} @' /etc/hosts") end diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index 474f1005e..4fc48edab 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -27,6 +27,7 @@ module VagrantPlugins def initialize @graceful_halt_retry_count = UNSET_VALUE @graceful_halt_retry_interval = UNSET_VALUE + @guest = UNSET_VALUE @hostname = UNSET_VALUE @provisioners = [] @@ -226,8 +227,12 @@ module VagrantPlugins def finalize! # Defaults + @guest = nil if @guest == UNSET_VALUE @hostname = nil if @hostname == UNSET_VALUE + # Set the guest properly + @guest = @guest.to_sym if @guest + # If we haven't defined a single VM, then we need to define a # default VM which just inherits the rest of the configuration. define(DEFAULT_VM_NAME) if defined_vm_keys.empty? @@ -381,6 +386,14 @@ module VagrantPlugins fp_host_ports.add(options[:host]) end end + + if type == :private_network + if options[:type] != :dhcp + if !options[:ip] + errors << I18n.t("vagrant.config.vm.network_ip_required") + end + end + end end # We're done with VM level errors so prepare the section diff --git a/plugins/providers/virtualbox/action/forward_ports.rb b/plugins/providers/virtualbox/action/forward_ports.rb index ee64d7988..da4da6eb8 100644 --- a/plugins/providers/virtualbox/action/forward_ports.rb +++ b/plugins/providers/virtualbox/action/forward_ports.rb @@ -70,6 +70,7 @@ module VagrantPlugins ports << { :adapter => fp.adapter, :guestport => fp.guest_port, + :hostip => fp.host_ip, :hostport => fp.host_port, :name => fp.id, :protocol => fp.protocol diff --git a/plugins/providers/virtualbox/action/network.rb b/plugins/providers/virtualbox/action/network.rb index 591583ffc..11409be3c 100644 --- a/plugins/providers/virtualbox/action/network.rb +++ b/plugins/providers/virtualbox/action/network.rb @@ -111,8 +111,10 @@ module VagrantPlugins # Only configure the networks the user requested us to configure networks_to_configure = networks.select { |n| n[:auto_config] } - env[:ui].info I18n.t("vagrant.actions.vm.network.configuring") - env[:machine].guest.capability(:configure_networks, networks_to_configure) + if !networks_to_configure.empty? + env[:ui].info I18n.t("vagrant.actions.vm.network.configuring") + env[:machine].guest.capability(:configure_networks, networks_to_configure) + end end end diff --git a/plugins/providers/virtualbox/driver/version_4_2.rb b/plugins/providers/virtualbox/driver/version_4_2.rb index dded1bc6f..f72ff0b52 100644 --- a/plugins/providers/virtualbox/driver/version_4_2.rb +++ b/plugins/providers/virtualbox/driver/version_4_2.rb @@ -140,9 +140,9 @@ module VagrantPlugins ports.each do |options| pf_builder = [options[:name], options[:protocol] || "tcp", - "", + options[:hostip] || "", options[:hostport], - "", + options[:guestip] || "", options[:guestport]] args.concat(["--natpf#{options[:adapter] || 1}", diff --git a/plugins/providers/virtualbox/model/forwarded_port.rb b/plugins/providers/virtualbox/model/forwarded_port.rb index 88c5c115d..5f8e8ed84 100644 --- a/plugins/providers/virtualbox/model/forwarded_port.rb +++ b/plugins/providers/virtualbox/model/forwarded_port.rb @@ -29,6 +29,11 @@ module VagrantPlugins # @return [Integer] attr_reader :guest_port + # The IP that the forwarded port will bind to on the host machine. + # + # @return [String] + attr_reader :host_ip + # The port on the host used to access the port on the guest. # # @return [Integer] @@ -43,6 +48,7 @@ module VagrantPlugins @auto_correct = true @auto_correct = options[:auto_correct] if options.has_key?(:auto_correct) @adapter = (options[:adapter] || 1).to_i + @host_ip = options[:host_ip] || nil @protocol = options[:protocol] || "tcp" end diff --git a/templates/commands/init/Vagrantfile.erb b/templates/commands/init/Vagrantfile.erb index 205a88164..6f2a3debc 100644 --- a/templates/commands/init/Vagrantfile.erb +++ b/templates/commands/init/Vagrantfile.erb @@ -27,6 +27,10 @@ Vagrant.configure("2") do |config| # your network. # config.vm.network :public_network + # If true, then any SSH connections made will enable agent forwarding. + # Default value: false + # config.ssh.forward_agent = true + # Share an additional folder to the guest VM. The first argument is # the path on the host to the actual folder. The second argument is # the path on the guest to mount the folder. And the optional third diff --git a/templates/guests/arch/network_dhcp.erb b/templates/guests/arch/network_dhcp.erb index f7044f071..cea4e8587 100644 --- a/templates/guests/arch/network_dhcp.erb +++ b/templates/guests/arch/network_dhcp.erb @@ -1,4 +1,4 @@ -CONNECTION='ethernet' -DESCRIPTION='A basic dhcp ethernet connection' -INTERFACE='eth<%= options[:interface] %>' -IP='dhcp' +Description='A basic dhcp ethernet connection' +Interface=eth<%= options[:interface] %> +Connection=ethernet +IP=dhcp diff --git a/templates/guests/arch/network_static.erb b/templates/guests/arch/network_static.erb index 61dfc140b..6cf2b9a62 100644 --- a/templates/guests/arch/network_static.erb +++ b/templates/guests/arch/network_static.erb @@ -1,6 +1,5 @@ -CONNECTION='ethernet' -DESCRIPTION='A basic static ethernet connection' -INTERFACE='eth<%= options[:interface] %>' -IP='static' -ADDR='<%= options[:ip]%>' -NETMASK='<%= options[:netmask] %>' +Connection=ethernet +Description='A basic static ethernet connection' +Interface=eth<%= options[:interface] %> +IP=static +Address=('<%= options[:ip]%>/24') diff --git a/templates/locales/en.yml b/templates/locales/en.yml index b5d423b0b..070e2a05f 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -167,6 +167,14 @@ en: available below. %{help} + command_unavailable: |- + The executable '%(file)' Vagrant is trying to run was not + found in the PATH variable. This is an error. Please verify + this software is installed and on the path. + command_unavailable_windows: |- + The executable '%(file)' Vagrant is trying to run was not + found in the %PATH% variable. This is an error. Please verify + this software is installed and on the path. config_invalid: |- There are errors in the configuration of this machine. Please fix the following errors and try again: @@ -613,6 +621,8 @@ en: nfs_requires_host: |- Using NFS shared folders requires a host to be specified using `config.vagrant.host`. + network_ip_required: |- + An IP is required for a private network. network_fp_host_not_unique: |- Forwarded port '%{host}' (host port) is declared multiple times network_fp_requires_ports: |- diff --git a/test/unit/vagrant/guest_test.rb b/test/unit/vagrant/guest_test.rb index d778ccd05..b66ccc708 100644 --- a/test/unit/vagrant/guest_test.rb +++ b/test/unit/vagrant/guest_test.rb @@ -10,6 +10,9 @@ describe Vagrant::Guest do let(:machine) do double("machine").tap do |m| m.stub(:inspect => "machine") + m.stub(:config => double("config")) + m.config.stub(:vm => double("vm_config")) + m.config.vm.stub(:guest => nil) end end @@ -143,6 +146,16 @@ describe Vagrant::Guest do subject.chain.map { |x| x[1] }.map(&:name).should == [:baz, :bar, :foo] end + it "detects the forced guest setting" do + register_guest(:foo, nil, false) + register_guest(:bar, nil, false) + + machine.config.vm.stub(:guest => :bar) + + subject.detect! + subject.name.should == :bar + end + it "raises an exception if no guest can be detected" do expect { subject.detect! }. to raise_error(Vagrant::Errors::GuestNotDetected) diff --git a/vagrant.gemspec b/vagrant.gemspec index bcf427004..7a900c0b2 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -17,7 +17,6 @@ Gem::Specification.new do |s| s.add_dependency "childprocess", "~> 0.3.7" s.add_dependency "erubis", "~> 2.7.0" s.add_dependency "i18n", "~> 0.6.0" - s.add_dependency "json", ">= 1.5.1", "< 1.8.0" s.add_dependency "log4r", "~> 1.1.9" s.add_dependency "net-ssh", "~> 2.6.6" s.add_dependency "net-scp", "~> 1.1.0"