Merge pull request #6386 from legal90/fix-osx-nic-order
Fix network configuration in OS X (Darwin) guests
This commit is contained in:
commit
d69d7047b2
|
@ -240,6 +240,10 @@ module Vagrant
|
|||
error_key(:bundler_error)
|
||||
end
|
||||
|
||||
class CantReadMACAddresses < VagrantError
|
||||
error_key(:cant_read_mac_addresses)
|
||||
end
|
||||
|
||||
class CapabilityHostExplicitNotDetected < VagrantError
|
||||
error_key(:capability_host_explicit_not_detected)
|
||||
end
|
||||
|
|
|
@ -6,46 +6,110 @@ module VagrantPlugins
|
|||
module GuestDarwin
|
||||
module Cap
|
||||
class ConfigureNetworks
|
||||
@@logger = Log4r::Logger.new("vagrant::guest::darwin::configure_networks")
|
||||
|
||||
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.
|
||||
if !machine.provider.capability?(:nic_mac_addresses)
|
||||
raise Vagrant::Errors::CantReadMACAddresses,
|
||||
provider: machine.provider_name.to_s
|
||||
end
|
||||
|
||||
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)
|
||||
nic_mac_addresses = machine.provider.capability(:nic_mac_addresses)
|
||||
@@logger.debug("mac addresses: #{nic_mac_addresses.inspect}")
|
||||
|
||||
devlist = []
|
||||
ints = ::IO.read(tmpints)
|
||||
mac_service_map = create_mac_service_map(machine)
|
||||
|
||||
networks.each do |network|
|
||||
mac_address = nic_mac_addresses[network[:interface]+1]
|
||||
if mac_address.nil?
|
||||
@@logger.warn("Could not find mac address for network #{network.inspect}")
|
||||
next
|
||||
end
|
||||
|
||||
service_name = mac_service_map[mac_address]
|
||||
if service_name.nil?
|
||||
@@logger.warn("Could not find network service for mac address #{mac_address}")
|
||||
next
|
||||
end
|
||||
|
||||
network_type = network[:type].to_sym
|
||||
if network_type == :static
|
||||
command = "networksetup -setmanual \"#{service_name}\" #{network[:ip]} #{network[:netmask]}"
|
||||
elsif network_type == :dhcp
|
||||
command = "networksetup -setdhcp \"#{service_name}\""
|
||||
else
|
||||
raise "#{network_type} network type is not supported, try static or dhcp"
|
||||
end
|
||||
|
||||
machine.communicate.sudo(command)
|
||||
end
|
||||
end
|
||||
|
||||
# Creates a hash mapping MAC addresses to network service name
|
||||
# Example: { "00C100A1B2C3" => "Thunderbolt Ethernet" }
|
||||
def self.create_mac_service_map(machine)
|
||||
tmp_ints = File.join(Dir.tmpdir, File.basename("#{machine.id}.interfaces"))
|
||||
tmp_hw = File.join(Dir.tmpdir, File.basename("#{machine.id}.hardware"))
|
||||
|
||||
machine.communicate.tap do |comm|
|
||||
comm.sudo("networksetup -detectnewhardware")
|
||||
comm.sudo("networksetup -listnetworkserviceorder > /tmp/vagrant.interfaces")
|
||||
comm.sudo("networksetup -listallhardwareports > /tmp/vagrant.hardware")
|
||||
comm.download("/tmp/vagrant.interfaces", tmp_ints)
|
||||
comm.download("/tmp/vagrant.hardware", tmp_hw)
|
||||
end
|
||||
|
||||
interface_map = {}
|
||||
ints = ::IO.read(tmp_ints)
|
||||
ints.split(/\n\n/m).each do |i|
|
||||
if i.match(/Hardware/) and not i.match(/Ethernet/).nil?
|
||||
devmap = {}
|
||||
if i.match(/Hardware/) && i.match(/Ethernet/)
|
||||
# Ethernet, should be 2 lines,
|
||||
# (3) Thunderbolt Ethernet
|
||||
# (Hardware Port: Thunderbolt Ethernet, Device: en1)
|
||||
|
||||
# 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
|
||||
File.delete(tmpints)
|
||||
service = devicearry[1]
|
||||
interface = devicearry[2]
|
||||
|
||||
networks.each do |network|
|
||||
service_name = devlist[network[:interface]][:service]
|
||||
if network[:type].to_sym == :static
|
||||
command = "networksetup -setmanual \"#{service_name}\" #{network[:ip]} #{network[:netmask]}"
|
||||
elsif network[:type].to_sym == :dhcp
|
||||
command = "networksetup -setdhcp \"#{service_name}\""
|
||||
# Should map interface to service { "en1" => "Thunderbolt Ethernet" }
|
||||
interface_map[interface] = service
|
||||
end
|
||||
end
|
||||
File.delete(tmp_ints)
|
||||
|
||||
mac_service_map = {}
|
||||
macs = ::IO.read(tmp_hw)
|
||||
macs.split(/\n\n/m).each do |i|
|
||||
if i.match(/Hardware/) && i.match(/Ethernet/)
|
||||
# Ethernet, should be 3 lines,
|
||||
# Hardware Port: Thunderbolt 1
|
||||
# Device: en1
|
||||
# Ethernet Address: a1:b2:c3:d4:e5:f6
|
||||
|
||||
# multiline, should match "en1", "00:c1:00:a1:b2:c3"
|
||||
devicearry = i.match(/Device: (.+)\nEthernet Address: (.+)/m)
|
||||
interface = devicearry[1]
|
||||
naked_mac = devicearry[2].gsub(':','').upcase
|
||||
|
||||
# Skip hardware ports without MAC (bridges, bluetooth, etc.)
|
||||
next if naked_mac == "N/A"
|
||||
|
||||
if !interface_map[interface]
|
||||
@@logger.warn("Could not find network service for interface #{interface}")
|
||||
next
|
||||
end
|
||||
|
||||
machine.communicate.sudo(command)
|
||||
# Should map MAC to service, { "00C100A1B2C3" => "Thunderbolt Ethernet" }
|
||||
mac_service_map[naked_mac] = interface_map[interface]
|
||||
end
|
||||
end
|
||||
File.delete(tmp_hw)
|
||||
|
||||
mac_service_map
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -53,7 +53,7 @@ module VagrantPlugins
|
|||
|
||||
def self.create_vm_interface_map(machine, guest_network)
|
||||
if !machine.provider.capability?(:nic_mac_addresses)
|
||||
raise Errors::CantReadMACAddresses,
|
||||
raise Vagrant::Errors::CantReadMACAddresses,
|
||||
provider: machine.provider_name.to_s
|
||||
end
|
||||
|
||||
|
|
|
@ -6,10 +6,6 @@ module VagrantPlugins
|
|||
error_namespace("vagrant_windows.errors")
|
||||
end
|
||||
|
||||
class CantReadMACAddresses < WindowsError
|
||||
error_key(:cant_read_mac_addresses)
|
||||
end
|
||||
|
||||
class NetworkWinRMRequired < WindowsError
|
||||
error_key(:network_winrm_required)
|
||||
end
|
||||
|
|
|
@ -603,6 +603,14 @@ en:
|
|||
issues. The error from Bundler is:
|
||||
|
||||
%{message}
|
||||
cant_read_mac_addresses: |-
|
||||
The provider you are using ('%{provider}') doesn't support the
|
||||
"nic_mac_addresses" provider capability which is required
|
||||
for advanced networking to work with this guest OS. Please inform
|
||||
the author of the provider to add this feature.
|
||||
|
||||
Until then, you must remove any networking configurations other
|
||||
than forwarded ports from your Vagrantfile for Vagrant to continue.
|
||||
capability_host_explicit_not_detected: |-
|
||||
The explicit capability host specified of '%{value}' could not be
|
||||
found.
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
en:
|
||||
vagrant_windows:
|
||||
errors:
|
||||
cant_read_mac_addresses: |-
|
||||
The provider being used to start Windows ('%{provider}')
|
||||
doesn't support the "nic_mac_addresses" capability which is required
|
||||
for advanced networking to work with Windows guests. Please inform
|
||||
the author of the provider to add this feature.
|
||||
|
||||
Until then, you must remove any networking configurations other
|
||||
than forwarded ports from your Vagrantfile for Vagrant to continue.
|
||||
network_winrm_required: |-
|
||||
Configuring networks on Windows requires the communicator to be
|
||||
set to WinRM. To do this, add the following to your Vagrantfile:
|
||||
|
|
Loading…
Reference in New Issue