fix(coreos-base/oem-vagrant): Rework network configuration code.

- Only write configs for static networks, DHCP will work by default.
 - Match interfaces by MAC address if possible.
 - Use the configured netmask instead of always using a /24
 - Define default addresses in /etc/environment based on the type of
   network. Now using both a private and a public network works!
This commit is contained in:
Michael Marineau 2014-04-27 19:37:11 -04:00
parent b1294b062d
commit 8b1ff15435

View File

@ -7,11 +7,17 @@
require 'tempfile'
require 'ipaddr'
require 'log4r'
require Vagrant.source_root.join("plugins/guests/coreos/cap/configure_networks.rb")
BASE_CLOUD_CONFIG = <<EOF
#cloud-config
write_files:
- path: /etc/environment
content: |
COREOS_PUBLIC_IPV4=%s
COREOS_PRIVATE_IPV4=%s
coreos:
units:
EOF
@ -21,7 +27,7 @@ NETWORK_UNIT = <<EOF
runtime: no
content: |
[Match]
Name=%s
%s
[Network]
Address=%s
@ -38,31 +44,43 @@ module VagrantPlugins
module GuestCoreOS
module Cap
class ConfigureNetworks
include Vagrant::Util
@@logger = Log4r::Logger.new("vagrant::guest::coreos::configure_networks")
def self.configure_networks(machine, networks)
cfg = BASE_CLOUD_CONFIG
machine.communicate.tap do |comm|
public_ipv4, private_ipv4 = get_environment_ips(machine, "127.0.0.1")
cfg = BASE_CLOUD_CONFIG % [public_ipv4, private_ipv4]
# Read network interface names
interfaces = []
comm.sudo("ifconfig | grep enp0 | cut -f1 -d:") do |_, result|
interfaces = result.split("\n")
# Define network units by mac address if possible.
match_rules = {}
if false
#if machine.provider.capability?(:nic_mac_addresses)
# untested, required feature hasn't made it into a release yet
match_rules = match_by_mac(machine)
else
match_rules = match_by_name(machine)
end
# Configure interfaces
# FIXME: fix matching of interfaces with IP adresses
@@logger.debug("Networks: #{networks.inspect}")
@@logger.debug("Interfaces: #{match_rules.inspect}")
# Generate any static networks, let DHCP handle the rest
networks.each do |network|
iface_num = network[:interface].to_i
iface_name = interfaces[iface_num]
cidr = IPAddr.new('255.255.255.0').to_cidr
address = "%s/%s" % [network[:ip], cidr]
unit_name = "50-%s.network" % [iface_name]
unit = NETWORK_UNIT % [unit_name, iface_name, address]
next if network[:type].to_sym != :static
interface = network[:interface].to_i
unit_name = "50-vagrant%d.network" % [interface]
cfg = "#{cfg}#{unit}"
match = match_rules[interface]
if match.nil?
@@logger.warn("Could not find match rule for network #{network.inspect}")
next
end
cidr = IPAddr.new(network[:netmask]).to_cidr
address = "%s/%s" % [network[:ip], cidr]
cfg << NETWORK_UNIT % [unit_name, match, address]
end
machine.communicate.tap do |comm|
temp = Tempfile.new("coreos-vagrant")
temp.binmode
temp.write(cfg)
@ -74,6 +92,51 @@ module VagrantPlugins
comm.sudo("systemctl start system-cloudinit@#{path_esc}.service")
end
end
# Find IP addresses to export in /etc/environment. This step
# must be performed here because that file must be written even
# if there are no additional networks configured.
def self.get_environment_ips(machine, default)
public_ipv4 = nil
private_ipv4 = nil
machine.config.vm.networks.each do |type, options|
next if !options[:ip]
if type == :public_network
public_ipv4 = options[:ip]
elsif type == :private_network
private_ipv4 = options[:ip]
end
end
# Fall back to localhost if no networks are configured.
private_ipv4 ||= default
public_ipv4 ||= private_ipv4
return [public_ipv4, private_ipv4]
end
def self.match_by_name(machine)
match = {}
machine.communicate.tap do |comm|
comm.sudo("ifconfig -a | grep ^en | cut -f1 -d:") do |_, result|
result.split("\n").each_with_index do |name, interface|
match[interface] = "Name=#{name}"
end
end
end
match
end
def self.match_by_mac(machine)
match = {}
macs = machine.provider.capability(:nic_mac_addresses)
macs.each do |adapter, address|
# The adapter list from VirtualBox is 1 indexed instead of 0
interface = adapter.to_i - 1
match[interface] = "MACAddress=#{address}"
end
match
end
end
end
end