Make network creation thread-safe, closes #104

This commit is contained in:
Brian Pitts 2014-01-17 18:16:18 -06:00
parent 46306503f4
commit 1aabe66b23

View File

@ -2,6 +2,7 @@ require 'log4r'
require 'vagrant/util/network_ip' require 'vagrant/util/network_ip'
require 'vagrant/util/scoped_hash_override' require 'vagrant/util/scoped_hash_override'
require 'ipaddr' require 'ipaddr'
require 'thread'
module VagrantPlugins module VagrantPlugins
module ProviderLibvirt module ProviderLibvirt
@ -13,6 +14,8 @@ module VagrantPlugins
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
include VagrantPlugins::ProviderLibvirt::Util::LibvirtUtil include VagrantPlugins::ProviderLibvirt::Util::LibvirtUtil
@@lock = Mutex.new
def initialize(app, env) def initialize(app, env)
mess = 'vagrant_libvirt::action::create_networks' mess = 'vagrant_libvirt::action::create_networks'
@logger = Log4r::Logger.new(mess) @logger = Log4r::Logger.new(mess)
@ -74,44 +77,49 @@ module VagrantPlugins
networks.push(options) networks.push(options)
end end
# Iterate over networks If some network is not # only one vm at a time should try to set up networks
# available, create it if possible. Otherwise raise an error. # otherwise they'll have inconsitent views of current state
networks.each do |options| # and conduct redundant operations that cause errors
@logger.debug "Searching for network with options #{options}" @@lock.synchronize do
# Iterate over networks If some network is not
# available, create it if possible. Otherwise raise an error.
networks.each do |options|
@logger.debug "Searching for network with options #{options}"
# should fix other methods so this doesn't have to be instance var # should fix other methods so this doesn't have to be instance var
@options = options @options = options
# Get a list of all (active and inactive) libvirt networks. This # Get a list of all (active and inactive) libvirt networks. This
# list is used throughout this class and should be easier to # list is used throughout this class and should be easier to
# process than libvirt API calls. # process than libvirt API calls.
@available_networks = libvirt_networks(env[:libvirt_compute].client) @available_networks = libvirt_networks(env[:libvirt_compute].client)
# Prepare a hash describing network for this specific interface. # Prepare a hash describing network for this specific interface.
@interface_network = { @interface_network = {
name: nil, name: nil,
ip_address: nil, ip_address: nil,
netmask: @options[:netmask], netmask: @options[:netmask],
network_address: nil, network_address: nil,
bridge_name: nil, bridge_name: nil,
created: false, created: false,
active: false, active: false,
autostart: false, autostart: false,
libvirt_network: nil, libvirt_network: nil,
} }
if @options[:ip] if @options[:ip]
handle_ip_option(env) handle_ip_option(env)
# in vagrant 1.2.3 and later it is not possible to take this branch # in vagrant 1.2.3 and later it is not possible to take this branch
# because cannot have name without ip # because cannot have name without ip
# https://github.com/mitchellh/vagrant/commit/cf2f6da4dbcb4f57c9cdb3b94dcd0bba62c5f5fd # https://github.com/mitchellh/vagrant/commit/cf2f6da4dbcb4f57c9cdb3b94dcd0bba62c5f5fd
elsif @options[:network_name] elsif @options[:network_name]
handle_network_name_option handle_network_name_option
end end
autostart_network if !@interface_network[:autostart] autostart_network if !@interface_network[:autostart]
activate_network if !@interface_network[:active] activate_network if !@interface_network[:active]
end end
end
@app.call(env) @app.call(env)
end end