Use lxc-info instead of lxc-attach to retrieve container IP

`lxc-info -iH` to retrieve IP address was not available in early LXC
development but was there at LXC 1.0. Because we've bumped our minimum
LXC requirement to v1.0 recently, we can simplify the IP retrieval
process and also get rid of the `dnsmasq` fallback.
This commit is contained in:
Virgil Dupras 2017-12-10 13:11:22 -05:00
parent 7e1eb1d373
commit aa777653f4
8 changed files with 17 additions and 83 deletions

View file

@ -4,8 +4,7 @@ require 'vagrant-lxc/action/create'
require 'vagrant-lxc/action/destroy'
require 'vagrant-lxc/action/destroy_confirm'
require 'vagrant-lxc/action/compress_rootfs'
require 'vagrant-lxc/action/fetch_ip_with_lxc_attach'
require 'vagrant-lxc/action/fetch_ip_from_dnsmasq_leases'
require 'vagrant-lxc/action/fetch_ip_with_lxc_info'
require 'vagrant-lxc/action/forced_halt'
require 'vagrant-lxc/action/forward_ports'
require 'vagrant-lxc/action/gc_private_network_bridges'
@ -182,8 +181,7 @@ module Vagrant
def self.action_ssh_ip
Builder.new.tap do |b|
b.use Builtin::Call, Builtin::ConfigValidate do |env, b2|
b2.use FetchIpWithLxcAttach if env[:machine].provider.driver.supports_attach?
b2.use FetchIpFromDnsmasqLeases
b2.use FetchIpWithLxcInfo
end
end
end

View file

@ -1,49 +0,0 @@
module Vagrant
module LXC
module Action
class FetchIpFromDnsmasqLeases
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::lxc::action::fetch_ip_from_dnsmasq_leases")
end
def call(env)
env[:machine_ip] ||= assigned_ip(env)
@app.call(env)
end
def assigned_ip(env)
mac_address = env[:machine].provider.driver.mac_address
ip = nil
10.times do
dnsmasq_leases = read_dnsmasq_leases
@logger.debug "Attempting to load ip from dnsmasq leases (mac: #{mac_address})"
@logger.debug dnsmasq_leases
if dnsmasq_leases =~ /#{Regexp.escape mac_address.to_s}\s+([0-9.]+)\s+/i
ip = $1.to_s
break
else
@logger.debug 'Ip could not be parsed from dnsmasq leases file'
sleep 2
end
end
ip
end
LEASES_PATHS = %w(
/var/lib/misc/dnsmasq.*.leases
/var/lib/misc/dnsmasq.leases
/var/lib/dnsmasq/dnsmasq.leases
/var/db/dnsmasq.leases
/var/lib/libvirt/dnsmasq/*.leases
)
def read_dnsmasq_leases
Dir["{#{LEASES_PATHS.join(',')}}"].map do |file|
File.read(file)
end.join("\n")
end
end
end
end
end

View file

@ -1,19 +1,17 @@
module Vagrant
module LXC
module Action
class FetchIpWithLxcAttach
class FetchIpWithLxcInfo
# Include this so we can use `Subprocess` more easily.
include Vagrant::Util::Retryable
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::lxc::action::fetch_ip_with_lxc_attach")
@logger = Log4r::Logger.new("vagrant::lxc::action::fetch_ip_with_lxc_info")
end
def call(env)
env[:machine_ip] ||= assigned_ip(env)
rescue LXC::Errors::NamespacesNotSupported
@logger.info 'The `lxc-attach` command available does not support the --namespaces parameter, falling back to dnsmasq leases to fetch container ip'
ensure
@app.call(env)
end
@ -26,7 +24,7 @@ module Vagrant
retryable(:on => LXC::Errors::ExecuteError, :tries => fetch_ip_tries, :sleep => 3) do
unless ip = get_container_ip_from_ip_addr(driver)
# retry
raise LXC::Errors::ExecuteError, :command => "lxc-attach"
raise LXC::Errors::ExecuteError, :command => "lxc-info"
end
end
ip
@ -34,8 +32,8 @@ module Vagrant
# From: https://github.com/lxc/lxc/blob/staging/src/python-lxc/lxc/__init__.py#L371-L385
def get_container_ip_from_ip_addr(driver)
output = driver.attach '/sbin/ip', '-4', 'addr', 'show', 'scope', 'global', 'eth0', namespaces: ['network', 'mount']
if output =~ /^\s+inet ([0-9.]+)\/[0-9]+\s+/
output = driver.info '-iH'
if output =~ /^([0-9.]+)/
return $1.to_s
end
end

View file

@ -127,6 +127,10 @@ module Vagrant
@cli.attach(*command)
end
def info(*command)
@cli.info(*command)
end
def configure_private_network(bridge_name, bridge_ip, container_name, address_type, ip)
@logger.info "Configuring network interface for #{container_name} using #{ip} and bridge #{bridge_name}"
if ip

View file

@ -114,17 +114,17 @@ module Vagrant
end
if namespaces
if supports_attach_with_namespaces?
extra = ['--namespaces', namespaces]
else
raise LXC::Errors::NamespacesNotSupported
end
end
end
run :attach, '--name', @name, *((extra || []) + cmd)
end
def info(*cmd)
run(:info, '--name', @name, *cmd)
end
def transition_to(target_state, tries = 30, timeout = 1, &block)
raise TransitionBlockNotProvided unless block_given?
@ -170,14 +170,6 @@ module Vagrant
def run(command, *args)
@sudo_wrapper.run("lxc-#{command}", *args)
end
def supports_attach_with_namespaces?
unless defined?(@supports_attach_with_namespaces)
@supports_attach_with_namespaces = run(:attach, '-h', :show_stderr => true).values.join.include?('--namespaces')
end
return @supports_attach_with_namespaces
end
end
end
end

View file

@ -25,9 +25,6 @@ module Vagrant
end
class NamespacesNotSupported < Vagrant::Errors::VagrantError
end
class LxcLinuxRequired < Vagrant::Errors::VagrantError
error_key(:lxc_linux_required)
end

View file

@ -232,13 +232,6 @@ describe Vagrant::LXC::Driver::CLI do
subject.attach *(command + [{namespaces: ['network', 'mount']}])
expect(subject).to have_received(:run).with(:attach, '--name', name, '--namespaces', 'NETWORK|MOUNT', '--', *command)
end
it 'raises a NamespacesNotSupported error if not supported' do
allow(subject).to receive(:run).with(:attach, '-h', :show_stderr => true).and_return({:stdout => '', :stderr => 'not supported'})
expect {
subject.attach *(command + [{namespaces: ['network', 'mount']}])
}.to raise_error(Vagrant::LXC::Errors::NamespacesNotSupported)
end
end
describe 'transition block' do

View file

@ -109,6 +109,7 @@ Whitelist.add_regex %r{<%= pipework_regex %>}, '**'
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-version'
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-ls'
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-info', '--name', /.*/
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-info', '--name', /.*/, '-iH'
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-create', '-B', /.*/, '--template', /.*/, '--name', /.*/, '**'
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-create', '--version'
Whitelist.add '<%= cmd_paths['lxc_bin'] %>/lxc-destroy', '--name', /.*/