guests/darwin: Configure network following the MAC addresses matching
Currently `configure_networks` guest cap configures NICs following the device order and fails when the device order is mixed. We should detect the appropriate NIC by its MAC address.
This commit is contained in:
parent
36cfc77167
commit
e426455309
|
@ -6,45 +6,109 @@ module VagrantPlugins
|
||||||
module GuestDarwin
|
module GuestDarwin
|
||||||
module Cap
|
module Cap
|
||||||
class ConfigureNetworks
|
class ConfigureNetworks
|
||||||
|
@@logger = Log4r::Logger.new("vagrant::guest::darwin::configure_networks")
|
||||||
|
|
||||||
include Vagrant::Util
|
include Vagrant::Util
|
||||||
|
|
||||||
def self.configure_networks(machine, networks)
|
def self.configure_networks(machine, networks)
|
||||||
# Slightly different than other plugins, using the template to build commands
|
if !machine.provider.capability?(:nic_mac_addresses)
|
||||||
# rather than templating the files.
|
raise Errors::CantReadMACAddresses,
|
||||||
|
provider: machine.provider_name.to_s
|
||||||
|
end
|
||||||
|
|
||||||
machine.communicate.sudo("networksetup -detectnewhardware")
|
nic_mac_addresses = machine.provider.capability(:nic_mac_addresses)
|
||||||
machine.communicate.sudo("networksetup -listnetworkserviceorder > /tmp/vagrant.interfaces")
|
@@logger.debug("mac addresses: #{nic_mac_addresses.inspect}")
|
||||||
tmpints = File.join(Dir.tmpdir, File.basename("#{machine.id}.interfaces"))
|
|
||||||
machine.communicate.download("/tmp/vagrant.interfaces",tmpints)
|
|
||||||
|
|
||||||
devlist = []
|
mac_service_map = create_mac_service_map(machine)
|
||||||
ints = ::IO.read(tmpints)
|
|
||||||
|
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|
|
ints.split(/\n\n/m).each do |i|
|
||||||
if i.match(/Hardware/) and not i.match(/Ethernet/).nil?
|
if i.match(/Hardware/) && i.match(/Ethernet/)
|
||||||
devmap = {}
|
|
||||||
# Ethernet, should be 2 lines,
|
# Ethernet, should be 2 lines,
|
||||||
# (3) Thunderbolt Ethernet
|
# (3) Thunderbolt Ethernet
|
||||||
# (Hardware Port: Thunderbolt Ethernet, Device: en1)
|
# (Hardware Port: Thunderbolt Ethernet, Device: en1)
|
||||||
|
|
||||||
# multiline, should match "Thunderbolt Ethernet", "en1"
|
# multiline, should match "Thunderbolt Ethernet", "en1"
|
||||||
devicearry = i.match(/\([0-9]+\) (.+)\n.*Device: (.+)\)/m)
|
devicearry = i.match(/\([0-9]+\) (.+)\n.*Device: (.+)\)/m)
|
||||||
devmap[:interface] = devicearry[2]
|
service = devicearry[1]
|
||||||
devmap[:service] = devicearry[1]
|
interface = devicearry[2]
|
||||||
devlist << devmap
|
|
||||||
|
# Should map interface to service { "en1" => "Thunderbolt Ethernet" }
|
||||||
|
interface_map[interface] = service
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
File.delete(tmpints)
|
File.delete(tmp_ints)
|
||||||
|
|
||||||
networks.each do |network|
|
mac_service_map = {}
|
||||||
service_name = devlist[network[:interface]][:service]
|
macs = ::IO.read(tmp_hw)
|
||||||
if network[:type].to_sym == :static
|
macs.split(/\n\n/m).each do |i|
|
||||||
command = "networksetup -setmanual \"#{service_name}\" #{network[:ip]} #{network[:netmask]}"
|
if i.match(/Hardware/) && i.match(/Ethernet/)
|
||||||
elsif network[:type].to_sym == :dhcp
|
# Ethernet, should be 3 lines,
|
||||||
command = "networksetup -setdhcp \"#{service_name}\""
|
# 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
|
||||||
|
|
||||||
|
# Should map MAC to service, { "00C100A1B2C3" => "Thunderbolt Ethernet" }
|
||||||
|
mac_service_map[naked_mac] = interface_map[interface]
|
||||||
end
|
end
|
||||||
|
|
||||||
machine.communicate.sudo(command)
|
|
||||||
end
|
end
|
||||||
|
File.delete(tmp_hw)
|
||||||
|
|
||||||
|
mac_service_map
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue