diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 7f1ce463c..a2c34aa35 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -183,6 +183,10 @@ module Vagrant error_key(:copy_private_key_failed) end + class DarwinNFSMountFailed < VagrantError + error_key(:darwin_nfs_mount_failed) + end + class DestroyRequiresForce < VagrantError error_key(:destroy_requires_force) end diff --git a/plugins/guests/darwin/cap/configure_networks.rb b/plugins/guests/darwin/cap/configure_networks.rb index 5b37dc1b9..9836893d0 100644 --- a/plugins/guests/darwin/cap/configure_networks.rb +++ b/plugins/guests/darwin/cap/configure_networks.rb @@ -3,48 +3,55 @@ require "tempfile" require "vagrant/util/template_renderer" module VagrantPlugins - module GuestDarwin - module Cap - class ConfigureNetworks - include Vagrant::Util + module GuestDarwin + module Cap + class ConfigureNetworks + include Vagrant::Util - def self.configure_networks(machine, networks) - # Slightly different than other plugins, using the template to build commands - # rather than templating the files. + def self.configure_networks(machine, networks) + # Slightly different than other plugins, using the template to build commands + # rather than templating the files. - machine.communicate.sudo("networksetup -detectnewhardware") - devmap = {} - machine.communicate.sudo("networksetup -listnetworkserviceorder > /tmp/vagrant.interfaces") - tmpints = File.join(Dir.tmpdir, "#{machine.id}.interfaces") - machine.communicate.download("/tmp/vagrant.interfaces",tmpints) - ints = IO.read(tmpints) - ints.split(/\n\n/m).each do |i| - if i.match(/Hardware/) and not i.match(/Ethernet/).nil? - # Ethernet, should be 2 lines, - # (3) Thunderbolt Ethernet - # (Hardware Port: Thunderbolt Ethernet, Device: en1) - devicearry = i.match(/Hardware Port: (.+), Device: en(.+)\)/) - devmap[devicearry[2]] = devicearry[1] - end - end - networks.each do |network| + machine.communicate.sudo("networksetup -detectnewhardware") + machine.communicate.sudo("networksetup -listnetworkserviceorder > /tmp/vagrant.interfaces") + tmpints = File.join(Dir.tmpdir, File.basename("#{machine.id}.interfaces")) + machine.communicate.download("/tmp/vagrant.interfaces",tmpints) + devlist = [] + ints = IO.read(tmpints) + ints.split(/\n\n/m).each do |i| + if i.match(/Hardware/) and not i.match(/Ethernet/).nil? + devmap = {} + # Ethernet, should be 2 lines, + # (3) Thunderbolt Ethernet + # (Hardware Port: Thunderbolt Ethernet, Device: en1) - if network[:type].to_sym == :static - # network seems 1 indexed - skip NAT interface (en0) also en1 because it seems to not *really* exist on virtualbox? - intnum = network[:interface] + 1 - puts "Network - #{intnum}" - command = "networksetup -setmanual \"#{devmap[intnum.to_s]}\" #{network[:ip]} #{network[:netmask]} #{network[:gateway]}" + # multiline, should match "Thunderbolt Ethernet", "en1" + devicearry = i.match(/\([0-9]+\) (.+)\n.*Device: (.+)\)/m) + devmap[:interface] = devicearry[2] + devmap[:service] = devicearry[1] + devlist << devmap + end + end + puts devlist - elsif network[:type].to_sym == :dhcp - command = "networksetup -setdhcp \"#{devmap[options[:interface]]}\"" + networks.each do |network| + intnum = network[:interface] + puts network[:interface] + puts network[:type] + if network[:type].to_sym == :static + # network seems 1 indexed - skip NAT interface (en0) also en1 because it seems to not *really* exist on virtualbox? + command = "networksetup -setmanual \"#{devlist[intnum+1][:service]}\" #{network[:ip]} #{network[:netmask]}" - end + elsif network[:type].to_sym == :dhcp + command = "networksetup -setdhcp \"#{devlist[intnum+1][:service]}\"" - machine.communicate.sudo("#{command}") - end - end - end - end - end + end + + machine.communicate.sudo(command) + end + end + end + end + end end diff --git a/plugins/guests/darwin/cap/mount_nfs_folder.rb b/plugins/guests/darwin/cap/mount_nfs_folder.rb index c4be11a05..52030a2ae 100644 --- a/plugins/guests/darwin/cap/mount_nfs_folder.rb +++ b/plugins/guests/darwin/cap/mount_nfs_folder.rb @@ -1,16 +1,25 @@ +require "vagrant/util/retryable" + module VagrantPlugins - module GuestDarwin - module Cap - class MountNFSFolder - def self.mount_nfs_folder(machine, ip, folders) - puts "30 second nap...." - sleep(30) - folders.each do |name, opts| - machine.communicate.sudo("if [ ! -d #{opts[:guestpath]} ]; then mkdir -p #{opts[:guestpath]};fi") - machine.communicate.sudo("mount -t nfs '#{ip}:#{opts[:hostpath]}' '#{opts[:guestpath]}'") - end - end - end - end - end + module GuestDarwin + module Cap + class MountNFSFolder + extend Vagrant::Util::Retryable + def self.mount_nfs_folder(machine, ip, folders) + folders.each do |name, opts| + # Expand the guest path so we can handle things like "~/vagrant" + expanded_guest_path = machine.guest.capability( + :shell_expand_guest_path, opts[:guestpath]) + + machine.communicate.sudo("if [ ! -d #{expanded_guest_path} ]; then mkdir -p #{expanded_guest_path};fi") + + mount_command = "mount -t nfs '#{ip}:#{opts[:hostpath]}' '#{expanded_guest_path}'" + retryable(:on => Vagrant::Errors::DarwinNFSMountFailed, :tries => 10, :sleep => 5) do + machine.communicate.sudo(mount_command, :error_class => Vagrant::Errors::DarwinNFSMountFailed) + end + end + end + end + end + end end diff --git a/plugins/guests/darwin/cap/shell_expand_guest_path.rb b/plugins/guests/darwin/cap/shell_expand_guest_path.rb new file mode 100644 index 000000000..13a82979b --- /dev/null +++ b/plugins/guests/darwin/cap/shell_expand_guest_path.rb @@ -0,0 +1,26 @@ +module VagrantPlugins + module GuestDarwin + module Cap + class ShellExpandGuestPath + def self.shell_expand_guest_path(machine, path) + real_path = nil + machine.communicate.execute("printf #{path}") do |type, data| + if type == :stdout + real_path ||= "" + real_path += data + end + end + + if !real_path + # If no real guest path was detected, this is really strange + # and we raise an exception because this is a bug. + raise DarwinShellExpandFailed + end + + # Chomp the string so that any trailing newlines are killed + return real_path.chomp + end + end + end + end +end diff --git a/plugins/guests/darwin/plugin.rb b/plugins/guests/darwin/plugin.rb index 5d104ed78..a7b481b24 100644 --- a/plugins/guests/darwin/plugin.rb +++ b/plugins/guests/darwin/plugin.rb @@ -1,35 +1,40 @@ require "vagrant" module VagrantPlugins - module GuestDarwin - class Plugin < Vagrant.plugin("2") - name "Darwin guest" - description "Darwin guest support." + module GuestDarwin + class Plugin < Vagrant.plugin("2") + name "Darwin guest" + description "Darwin guest support." - guest("darwin") do - require File.expand_path("../guest", __FILE__) - Guest - end + guest("darwin") do + require File.expand_path("../guest", __FILE__) + Guest + end - guest_capability("darwin", "change_host_name") do - require_relative "cap/change_host_name" - Cap::ChangeHostName - end + guest_capability("darwin", "change_host_name") do + require_relative "cap/change_host_name" + Cap::ChangeHostName + end - guest_capability("darwin", "configure_networks") do - require_relative "cap/configure_networks" - Cap::ConfigureNetworks - end + guest_capability("darwin", "configure_networks") do + require_relative "cap/configure_networks" + Cap::ConfigureNetworks + end - guest_capability("darwin", "halt") do - require_relative "cap/halt" - Cap::Halt - end + guest_capability("darwin", "halt") do + require_relative "cap/halt" + Cap::Halt + end - guest_capability("darwin", "mount_nfs_folder") do - require_relative "cap/mount_nfs_folder" - Cap::MountNFSFolder - end - end - end + guest_capability("darwin", "mount_nfs_folder") do + require_relative "cap/mount_nfs_folder" + Cap::MountNFSFolder + end + + guest_capability("darwin", "shell_expand_guest_path") do + require_relative "cap/shell_expand_guest_path" + Cap::ShellExpandGuestPath + end + end + end end