mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
Remove machine ssh_info and state from using actions
Remove the ReadSSHInfo and ReadState actions and corresponding calls to dispatch queries by vagrant on the provider for current `ssh_info` and `state` to be handled by actions. Change the corresponding methods added to the Driver and Provider classes to avoid modifying `machine.id` directly and allow vagrant to take care of resetting it whenever `state` returns :not_created. This ensures that both `ssh_info` and `state` may be called by other threads, such as the ansible provisioner building the inventory file, on machines without causing exceptions due to machine locks preventing modification (setting `machine.id` to nil) and Batch locking preventing multiple sets of actions being executed on the same machine by different threads/processes. Follows the design of the in-tree docker provider for vagrant.
This commit is contained in:
parent
db440907f7
commit
cee934a482
@ -259,25 +259,6 @@ module VagrantPlugins
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This action is called to read the state of the machine. The resulting
|
|
||||||
# state is expected to be put into the `:machine_state_id` key.
|
|
||||||
def self.action_read_state
|
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
|
||||||
b.use ConfigValidate
|
|
||||||
b.use ReadState
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# This action is called to read the SSH info of the machine. The
|
|
||||||
# resulting state is expected to be put into the `:machine_ssh_info`
|
|
||||||
# key.
|
|
||||||
def self.action_read_ssh_info
|
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
|
||||||
b.use ConfigValidate
|
|
||||||
b.use ReadSSHInfo
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.action_read_mac_addresses
|
def self.action_read_mac_addresses
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
b.use ConfigValidate
|
b.use ConfigValidate
|
||||||
@ -336,9 +317,7 @@ module VagrantPlugins
|
|||||||
autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
|
autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
|
||||||
autoload :PruneNFSExports, action_root.join('prune_nfs_exports')
|
autoload :PruneNFSExports, action_root.join('prune_nfs_exports')
|
||||||
|
|
||||||
autoload :ReadSSHInfo, action_root.join('read_ssh_info')
|
|
||||||
autoload :ReadMacAddresses, action_root.join('read_mac_addresses')
|
autoload :ReadMacAddresses, action_root.join('read_mac_addresses')
|
||||||
autoload :ReadState, action_root.join('read_state')
|
|
||||||
autoload :ResumeDomain, action_root.join('resume_domain')
|
autoload :ResumeDomain, action_root.join('resume_domain')
|
||||||
autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
|
autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
|
||||||
|
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
require "log4r"
|
|
||||||
|
|
||||||
module VagrantPlugins
|
|
||||||
module ProviderLibvirt
|
|
||||||
module Action
|
|
||||||
# This action reads the SSH info for the machine and puts it into the
|
|
||||||
# `:machine_ssh_info` key in the environment.
|
|
||||||
class ReadSSHInfo
|
|
||||||
def initialize(app, env)
|
|
||||||
@app = app
|
|
||||||
@logger = Log4r::Logger.new("vagrant_libvirt::action::read_ssh_info")
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(env)
|
|
||||||
env[:machine_ssh_info] = read_ssh_info(env[:machine].provider.driver.connection,
|
|
||||||
env[:machine])
|
|
||||||
|
|
||||||
@app.call(env)
|
|
||||||
end
|
|
||||||
|
|
||||||
def read_ssh_info(libvirt, machine)
|
|
||||||
return nil if machine.id.nil?
|
|
||||||
return nil if machine.state.id != :running
|
|
||||||
|
|
||||||
# Find the machine
|
|
||||||
domain = libvirt.servers.get(machine.id)
|
|
||||||
if domain.nil?
|
|
||||||
# The machine can't be found
|
|
||||||
@logger.info("Machine couldn't be found, assuming it got destroyed.")
|
|
||||||
machine.id = nil
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get IP address from dnsmasq lease file.
|
|
||||||
ip_address = nil
|
|
||||||
begin
|
|
||||||
domain.wait_for(2) do
|
|
||||||
addresses.each_pair do |type, ip|
|
|
||||||
# Multiple leases are separated with a newline, return only
|
|
||||||
# the most recent address
|
|
||||||
ip_address = ip[0].split("\n").first if ip[0] != nil
|
|
||||||
end
|
|
||||||
ip_address != nil
|
|
||||||
end
|
|
||||||
rescue Fog::Errors::TimeoutError
|
|
||||||
@logger.info("Timeout at waiting for an ip address for machine %s" % machine.name)
|
|
||||||
end
|
|
||||||
|
|
||||||
if not ip_address
|
|
||||||
@logger.info("No lease found for machine %s" % machine.name)
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
ssh_info = {
|
|
||||||
:host => ip_address,
|
|
||||||
:port => machine.config.ssh.guest_port,
|
|
||||||
:forward_agent => machine.config.ssh.forward_agent,
|
|
||||||
:forward_x11 => machine.config.ssh.forward_x11,
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_info[:proxy_command] = "ssh '#{machine.provider_config.host}' -l '#{machine.provider_config.username}' -i '#{machine.provider_config.id_ssh_key_file}' nc %h %p" if machine.provider_config.connect_via_ssh
|
|
||||||
|
|
||||||
ssh_info
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,60 +0,0 @@
|
|||||||
require 'log4r'
|
|
||||||
|
|
||||||
module VagrantPlugins
|
|
||||||
module ProviderLibvirt
|
|
||||||
module Action
|
|
||||||
# This action reads the state of the machine and puts it in the
|
|
||||||
# `:machine_state_id` key in the environment.
|
|
||||||
class ReadState
|
|
||||||
def initialize(app, env)
|
|
||||||
@app = app
|
|
||||||
@logger = Log4r::Logger.new('vagrant_libvirt::action::read_state')
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(env)
|
|
||||||
env[:machine_state_id] = read_state(env[:machine].provider.driver.connection, env[:machine])
|
|
||||||
@app.call(env)
|
|
||||||
end
|
|
||||||
|
|
||||||
def read_state(libvirt, machine)
|
|
||||||
return :not_created if machine.id.nil?
|
|
||||||
|
|
||||||
begin
|
|
||||||
server = libvirt.servers.get(machine.id)
|
|
||||||
rescue Libvirt::RetrieveError => e
|
|
||||||
server = nil
|
|
||||||
@logger.debug('Machine not found #{e}.')
|
|
||||||
end
|
|
||||||
# Find the machine
|
|
||||||
begin
|
|
||||||
# Wait for libvirt to shutdown the domain
|
|
||||||
while libvirt.servers.get(machine.id).state.to_sym == :'shutting-down' do
|
|
||||||
@logger.info('Waiting on the machine to shut down...')
|
|
||||||
sleep 1
|
|
||||||
end
|
|
||||||
|
|
||||||
server = libvirt.servers.get(machine.id)
|
|
||||||
|
|
||||||
if server.nil? || server.state.to_sym == :terminated
|
|
||||||
# The machine can't be found
|
|
||||||
@logger.info('Machine terminated, assuming it got destroyed.')
|
|
||||||
machine.id = nil
|
|
||||||
return :not_created
|
|
||||||
end
|
|
||||||
rescue Libvirt::RetrieveError => e
|
|
||||||
if e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
|
|
||||||
@logger.info("Machine #{machine.id} not found.")
|
|
||||||
machine.id = nil
|
|
||||||
return :not_created
|
|
||||||
else
|
|
||||||
raise e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return the state
|
|
||||||
return server.state.to_sym
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -47,6 +47,88 @@ module VagrantPlugins
|
|||||||
|
|
||||||
@@connection
|
@@connection
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_domain(mid)
|
||||||
|
begin
|
||||||
|
domain = connection.servers.get(mid)
|
||||||
|
rescue Libvirt::RetrieveError => e
|
||||||
|
if e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
|
||||||
|
@logger.debug("machine #{mid} not found #{e}.")
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
raise e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
domain
|
||||||
|
end
|
||||||
|
|
||||||
|
def created?(mid)
|
||||||
|
domain = get_domain(mid)
|
||||||
|
!domain.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_ipaddress(machine)
|
||||||
|
# Find the machine
|
||||||
|
domain = get_domain(machine.id)
|
||||||
|
|
||||||
|
if domain.nil?
|
||||||
|
# The machine can't be found
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get IP address from arp table
|
||||||
|
ip_address = nil
|
||||||
|
begin
|
||||||
|
domain.wait_for(2) do
|
||||||
|
addresses.each_pair do |type, ip|
|
||||||
|
# Multiple leases are separated with a newline, return only
|
||||||
|
# the most recent address
|
||||||
|
ip_address = ip[0].split("\n").first if ip[0] != nil
|
||||||
|
end
|
||||||
|
ip_address != nil
|
||||||
|
end
|
||||||
|
rescue Fog::Errors::TimeoutError
|
||||||
|
@logger.info("Timeout at waiting for an ip address for machine %s" % machine.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not ip_address
|
||||||
|
@logger.info("No arp table entry found for machine %s" % machine.name)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
ip_address
|
||||||
|
end
|
||||||
|
|
||||||
|
def state(machine)
|
||||||
|
# TODO: while this currently matches the previous behaviour in actions
|
||||||
|
# read_state, it shouldn't be necessary to loop and wait for the
|
||||||
|
# machine to reach a state other than shutting-down, before returning
|
||||||
|
|
||||||
|
# may be other error states with initial retreival we can't handle
|
||||||
|
begin
|
||||||
|
domain = get_domain(machine.id)
|
||||||
|
rescue Libvirt::RetrieveError => e
|
||||||
|
@logger.debug("Machine #{machine.id} not found #{e}.")
|
||||||
|
return :not_created
|
||||||
|
end
|
||||||
|
|
||||||
|
# need to wait for the shutting-down state to stablize to a another
|
||||||
|
loop do
|
||||||
|
if domain.nil? || domain.state.to_sym == :terminated
|
||||||
|
return :not_created
|
||||||
|
end
|
||||||
|
|
||||||
|
if domain.state.to_sym != :'shutting-down'
|
||||||
|
# Return the state
|
||||||
|
return domain.state.to_sym
|
||||||
|
end
|
||||||
|
|
||||||
|
@logger.info('Waiting on the machine %s to shut down...' % machine.name)
|
||||||
|
sleep 1
|
||||||
|
domain = get_domain(machine.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -40,9 +40,8 @@ module VagrantPlugins
|
|||||||
# SSH into the machine. If the machine is not at a point where
|
# SSH into the machine. If the machine is not at a point where
|
||||||
# SSH is even possible, then `nil` should be returned.
|
# SSH is even possible, then `nil` should be returned.
|
||||||
def ssh_info
|
def ssh_info
|
||||||
# Run a custom action called "read_ssh_info" which does what it says
|
# Return the ssh_info if already retrieved otherwise call the driver
|
||||||
# and puts the resulting SSH info into the `:machine_ssh_info` key in
|
# and save the result.
|
||||||
# the environment.
|
|
||||||
#
|
#
|
||||||
# Ssh info has following format..
|
# Ssh info has following format..
|
||||||
#
|
#
|
||||||
@ -52,8 +51,32 @@ module VagrantPlugins
|
|||||||
# :username => "mitchellh",
|
# :username => "mitchellh",
|
||||||
# :private_key_path => "/path/to/my/key"
|
# :private_key_path => "/path/to/my/key"
|
||||||
#}
|
#}
|
||||||
env = @machine.action('read_ssh_info', :lock => false)
|
# note that modifing @machine.id or accessing @machine.state is not
|
||||||
env[:machine_ssh_info]
|
# thread safe, so be careful to avoid these here as this method may
|
||||||
|
# be called from other threads of execution.
|
||||||
|
return nil if state.id != :running
|
||||||
|
|
||||||
|
ip = driver.get_ipaddress(@machine)
|
||||||
|
|
||||||
|
# if can't determine the IP, just return nil and let the core
|
||||||
|
# deal with it, similar to the docker provider
|
||||||
|
return nil if !ip
|
||||||
|
|
||||||
|
ssh_info = {
|
||||||
|
:host => ip,
|
||||||
|
:port => @machine.config.ssh.guest_port,
|
||||||
|
:forward_agent => @machine.config.ssh.forward_agent,
|
||||||
|
:forward_x11 => @machine.config.ssh.forward_x11,
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_info[:proxy_command] = (
|
||||||
|
"ssh '#{@machine.provider_config.host}' " +
|
||||||
|
"-l '#{@machine.provider_config.username}' " +
|
||||||
|
"-i '#{@machine.provider_config.id_ssh_key_file}' " +
|
||||||
|
"nc %h %p"
|
||||||
|
) if @machine.provider_config.connect_via_ssh
|
||||||
|
|
||||||
|
ssh_info
|
||||||
end
|
end
|
||||||
|
|
||||||
def mac_addresses
|
def mac_addresses
|
||||||
@ -71,17 +94,29 @@ module VagrantPlugins
|
|||||||
# This should return the state of the machine within this provider.
|
# This should return the state of the machine within this provider.
|
||||||
# The state must be an instance of {MachineState}.
|
# The state must be an instance of {MachineState}.
|
||||||
def state
|
def state
|
||||||
# Run a custom action we define called "read_state" which does
|
|
||||||
# what it says. It puts the state in the `:machine_state_id`
|
|
||||||
# key in the environment.
|
|
||||||
env = @machine.action('read_state', :lock => false)
|
|
||||||
|
|
||||||
state_id = env[:machine_state_id]
|
state_id = nil
|
||||||
|
state_id = :not_created if !@machine.id
|
||||||
|
state_id = :not_created if (
|
||||||
|
!state_id && (!@machine.id || !driver.created?(@machine.id)))
|
||||||
|
# Query the driver for the current state of the machine
|
||||||
|
state_id = driver.state(@machine) if @machine.id && !state_id
|
||||||
|
state_id = :unknown if !state_id
|
||||||
|
|
||||||
|
# This is a special pseudo-state so that we don't set the
|
||||||
|
# NOT_CREATED_ID while we're setting up the machine. This avoids
|
||||||
|
# clearing the data dir.
|
||||||
|
state_id = :preparing if @machine.id == "preparing"
|
||||||
|
|
||||||
# Get the short and long description
|
# Get the short and long description
|
||||||
short = I18n.t("vagrant_libvirt.states.short_#{state_id}")
|
short = I18n.t("vagrant_libvirt.states.short_#{state_id}")
|
||||||
long = I18n.t("vagrant_libvirt.states.long_#{state_id}")
|
long = I18n.t("vagrant_libvirt.states.long_#{state_id}")
|
||||||
|
|
||||||
|
# If we're not created, then specify the special ID flag
|
||||||
|
if state_id == :not_created
|
||||||
|
state_id = Vagrant::MachineState::NOT_CREATED_ID
|
||||||
|
end
|
||||||
|
|
||||||
# Return the MachineState object
|
# Return the MachineState object
|
||||||
Vagrant::MachineState.new(state_id, short, long)
|
Vagrant::MachineState.new(state_id, short, long)
|
||||||
end
|
end
|
||||||
|
@ -155,3 +155,8 @@ en:
|
|||||||
long_running: |-
|
long_running: |-
|
||||||
The Libvirt domain is running. To stop this machine, you can run
|
The Libvirt domain is running. To stop this machine, you can run
|
||||||
`vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
|
`vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
|
||||||
|
short_preparing: |-
|
||||||
|
preparing
|
||||||
|
long_preparing: |-
|
||||||
|
The vagrant machine is being prepared for creation, please wait for
|
||||||
|
it to reach a steady state before issuing commands on it.
|
||||||
|
Loading…
Reference in New Issue
Block a user