Simplify container ip detection using lxc-attach + ifconfig
References: #31
This commit is contained in:
parent
e8388743ca
commit
b4161ac8af
5 changed files with 33 additions and 119 deletions
|
@ -103,67 +103,22 @@ module Vagrant
|
|||
end
|
||||
|
||||
def assigned_ip
|
||||
unless File.read(base_path.join('config')) =~ /^lxc\.network\.hwaddr\s*=\s*([a-z0-9:]+)\s*$/
|
||||
raise 'Unknown Container MAC Address'
|
||||
end
|
||||
mac_addr = $1
|
||||
|
||||
ip = ''
|
||||
retryable(:on => LXC::Errors::ExecuteError, :tries => 10, :sleep => 3) do
|
||||
# See: http://programminglinuxblog.blogspot.com.br/2007/11/detecting-ip-address-from-mac-address.html
|
||||
unless ip = get_container_ip_from_arp(mac_addr)
|
||||
# Ping subnet and try to get ip again
|
||||
ping_subnet!
|
||||
unless ip = get_container_ip_from_ifconfig
|
||||
# retry
|
||||
raise LXC::Errors::ExecuteError, :command => ['arp', '-n'].inspect
|
||||
end
|
||||
end
|
||||
ip
|
||||
end
|
||||
|
||||
def get_container_ip_from_arp(mac_addr)
|
||||
r = raw 'arp', '-n'
|
||||
|
||||
# If the command was a failure then raise an exception that is nicely
|
||||
# handled by Vagrant.
|
||||
if r.exit_code != 0
|
||||
if @interrupted
|
||||
@logger.info("Exit code != 0, but interrupted. Ignoring.")
|
||||
else
|
||||
raise LXC::Errors::ExecuteError, :command => ['arp', '-n'].inspect
|
||||
end
|
||||
end
|
||||
|
||||
if r.stdout.gsub("\r\n", "\n").strip =~ /^([0-9.]+).+#{Regexp.escape mac_addr}/
|
||||
def get_container_ip_from_ifconfig
|
||||
output = @cli.attach '/sbin/ifconfig', '-v', 'eth0', namespaces: 'network'
|
||||
if output =~ /\s+inet addr:([0-9.]+)\s+/
|
||||
return $1.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# FIXME: Should output an error friendly message in case fping is not installed
|
||||
def ping_subnet!
|
||||
raise LXC::Errors::UnknownLxcConfigFile unless File.exists?(LXC_DEFAULTS_PATH)
|
||||
|
||||
raise LXC::Errors::UnknownLxcBridgeAddress unless
|
||||
File.read(LXC_DEFAULTS_PATH) =~ /^LXC_ADDR\="?([0-9.]+)"?.*$/
|
||||
|
||||
cmd = ['fping', '-c', '1', '-g', '-q', "#{$1}/24"]
|
||||
raw(*cmd)
|
||||
|
||||
raise LXC::Errors::ExecuteError, :command => cmd.inspect
|
||||
end
|
||||
|
||||
# TODO: Review code below this line, it was pretty much a copy and paste from VirtualBox base driver
|
||||
def raw(*command, &block)
|
||||
int_callback = lambda do
|
||||
@interrupted = true
|
||||
@logger.info("Interrupted.")
|
||||
end
|
||||
|
||||
# Append in the options for subprocess
|
||||
command << { :notify => [:stdout, :stderr] }
|
||||
|
||||
Vagrant::Util::Busy.busy(int_callback) do
|
||||
Vagrant::Util::Subprocess.execute(*command, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
4
spec/fixtures/sample-arp-output
vendored
4
spec/fixtures/sample-arp-output
vendored
|
@ -1,4 +0,0 @@
|
|||
Address HWtype HWaddress Flags Mask Iface
|
||||
120.0.3.30 ether 10:16:3e:c8:f9:b7 C lxcbr0
|
||||
10.0.3.30 ether 00:16:3e:64:d6:74 C lxcbr0
|
||||
192.168.25.1 ether 2c:e4:12:95:90:45 C wlan0
|
47
spec/fixtures/sample-config
vendored
47
spec/fixtures/sample-config
vendored
|
@ -1,47 +0,0 @@
|
|||
lxc.network.type=veth
|
||||
lxc.network.link=lxcbr0
|
||||
lxc.network.flags=up
|
||||
lxc.network.hwaddr = 00:16:3e:64:d6:74
|
||||
lxc.rootfs = /var/lib/lxc/a91df47bfc6e/rootfs
|
||||
lxc.utsname = a91df47bfc6e
|
||||
|
||||
lxc.devttydir = lxc
|
||||
lxc.tty = 4
|
||||
lxc.pts = 1024
|
||||
lxc.mount = /var/lib/lxc/a91df47bfc6e/fstab
|
||||
lxc.arch = amd64
|
||||
lxc.cap.drop = sys_module mac_admin mac_override
|
||||
lxc.pivotdir = lxc_putold
|
||||
|
||||
# uncomment the next line to run the container unconfined:
|
||||
#lxc.aa_profile = unconfined
|
||||
|
||||
lxc.cgroup.devices.deny = a
|
||||
# Allow any mknod (but not using the node)
|
||||
lxc.cgroup.devices.allow = c *:* m
|
||||
lxc.cgroup.devices.allow = b *:* m
|
||||
# /dev/null and zero
|
||||
lxc.cgroup.devices.allow = c 1:3 rwm
|
||||
lxc.cgroup.devices.allow = c 1:5 rwm
|
||||
# consoles
|
||||
lxc.cgroup.devices.allow = c 5:1 rwm
|
||||
lxc.cgroup.devices.allow = c 5:0 rwm
|
||||
#lxc.cgroup.devices.allow = c 4:0 rwm
|
||||
#lxc.cgroup.devices.allow = c 4:1 rwm
|
||||
# /dev/{,u}random
|
||||
lxc.cgroup.devices.allow = c 1:9 rwm
|
||||
lxc.cgroup.devices.allow = c 1:8 rwm
|
||||
lxc.cgroup.devices.allow = c 136:* rwm
|
||||
lxc.cgroup.devices.allow = c 5:2 rwm
|
||||
# rtc
|
||||
lxc.cgroup.devices.allow = c 254:0 rwm
|
||||
#fuse
|
||||
lxc.cgroup.devices.allow = c 10:229 rwm
|
||||
#tun
|
||||
lxc.cgroup.devices.allow = c 10:200 rwm
|
||||
#full
|
||||
lxc.cgroup.devices.allow = c 1:7 rwm
|
||||
#hpet
|
||||
lxc.cgroup.devices.allow = c 10:228 rwm
|
||||
#kvm
|
||||
lxc.cgroup.devices.allow = c 10:232 rwm
|
18
spec/fixtures/sample-ifconfig-output
vendored
Normal file
18
spec/fixtures/sample-ifconfig-output
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
eth0 Link encap:Ethernet HWaddr 00:16:3e:7c:dd:44
|
||||
inet addr:10.0.3.109 Bcast:10.0.3.255 Mask:255.255.255.0
|
||||
inet6 addr: fe80::216:3eff:fe7c:dd44/64 Scope:Link
|
||||
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
||||
RX packets:204 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:203 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:1000
|
||||
RX bytes:29663 (29.6 KB) TX bytes:30168 (30.1 KB)
|
||||
|
||||
lo Link encap:Local Loopback
|
||||
inet addr:127.0.0.1 Mask:255.0.0.0
|
||||
inet6 addr: ::1/128 Scope:Host
|
||||
UP LOOPBACK RUNNING MTU:16436 Metric:1
|
||||
RX packets:73 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:73 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:0
|
||||
RX bytes:34173 (34.1 KB) TX bytes:34173 (34.1 KB)
|
||||
|
|
@ -125,27 +125,19 @@ describe Vagrant::LXC::Container do
|
|||
end
|
||||
|
||||
describe 'assigned ip' do
|
||||
# This ip is set on the sample-arp-output fixture based on mac address from
|
||||
# sample-config fixture
|
||||
let(:ip) { "10.0.3.30" }
|
||||
let(:conf_file_contents) { File.read('spec/fixtures/sample-config') }
|
||||
# This ip is set on the sample-ifconfig-output fixture
|
||||
let(:ip) { "10.0.3.109" }
|
||||
let(:ifconfig_output) { File.read('spec/fixtures/sample-ifconfig-output') }
|
||||
let(:name) { 'random-container-name' }
|
||||
let(:cli) { fire_double('Vagrant::LXC::Container::CLI', :attach => ifconfig_output) }
|
||||
|
||||
context 'when container mac address gets returned from the first `arp` call' do
|
||||
before do
|
||||
@arp_output = File.read('spec/fixtures/sample-arp-output')
|
||||
subject.stub(:raw) {
|
||||
mock(stdout: "#{@arp_output}\n", exit_code: 0)
|
||||
}
|
||||
File.stub(read: conf_file_contents)
|
||||
end
|
||||
subject { described_class.new(name, cli) }
|
||||
|
||||
it 'gets parsed from `arp` based on lxc mac address' do
|
||||
context 'when ip for eth0 gets returned from lxc-attach call' do
|
||||
it 'gets parsed from ifconfig output' do
|
||||
subject.assigned_ip.should == ip
|
||||
subject.should have_received(:raw).with('arp', '-n')
|
||||
cli.should have_received(:attach).with('/sbin/ifconfig', '-v', 'eth0', namespaces: 'network')
|
||||
end
|
||||
end
|
||||
|
||||
pending 'when mac address is not returned from an `arp` call'
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue