mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
Merge pull request #436 from electrofelix/parallel-ssh_info
allow query of ssh_info in parallel from other machines or user
This commit is contained in:
commit
0c1c94bf36
@ -7,20 +7,6 @@ module VagrantPlugins
|
||||
autoload :Errors, lib_path.join('errors')
|
||||
autoload :Util, lib_path.join('util')
|
||||
|
||||
# Hold connection handler so there is no need to connect more times than
|
||||
# one. This can be annoying when there are more machines to create, or when
|
||||
# doing state action first and then some other.
|
||||
#
|
||||
# TODO Don't sure if this is the best solution
|
||||
@@libvirt_connection = nil
|
||||
def self.libvirt_connection
|
||||
@@libvirt_connection
|
||||
end
|
||||
|
||||
def self.libvirt_connection=(conn)
|
||||
@@libvirt_connection = conn
|
||||
end
|
||||
|
||||
def self.source_root
|
||||
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
||||
end
|
||||
|
@ -19,7 +19,6 @@ module VagrantPlugins
|
||||
def self.action_up
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use ConnectLibvirt
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
# Create VM if not yet created.
|
||||
if !env[:result]
|
||||
@ -58,7 +57,6 @@ module VagrantPlugins
|
||||
def self.action_start
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use ConnectLibvirt
|
||||
b.use Call, IsRunning do |env, b2|
|
||||
# If the VM is running, then our work here is done, exit
|
||||
next if env[:result]
|
||||
@ -101,7 +99,6 @@ module VagrantPlugins
|
||||
def self.action_halt
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use ConnectLibvirt
|
||||
b.use ClearForwardedPorts
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
if !env[:result]
|
||||
@ -144,7 +141,6 @@ module VagrantPlugins
|
||||
def self.action_package
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use ConnectLibvirt
|
||||
b.use PackageDomain
|
||||
end
|
||||
end
|
||||
@ -157,7 +153,6 @@ module VagrantPlugins
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
if !env[:result]
|
||||
# Try to remove stale volumes anyway
|
||||
b2.use ConnectLibvirt
|
||||
b2.use SetNameOfDomain
|
||||
b2.use RemoveStaleVolume
|
||||
if !env[:result]
|
||||
@ -167,7 +162,6 @@ module VagrantPlugins
|
||||
next
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use ClearForwardedPorts
|
||||
# b2.use PruneNFSExports
|
||||
b2.use DestroyDomain
|
||||
@ -187,7 +181,6 @@ module VagrantPlugins
|
||||
next
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use Call, IsRunning do |env2, b3|
|
||||
if !env2[:result]
|
||||
b3.use MessageNotRunning
|
||||
@ -210,7 +203,6 @@ module VagrantPlugins
|
||||
next
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use Call, IsRunning do |env2, b3|
|
||||
if !env2[:result]
|
||||
b3.use MessageNotRunning
|
||||
@ -235,7 +227,6 @@ module VagrantPlugins
|
||||
next
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use Call, IsRunning do |env2, b3|
|
||||
if !env2[:result]
|
||||
b3.use MessageNotRunning
|
||||
@ -258,7 +249,6 @@ module VagrantPlugins
|
||||
next
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use Call, IsSuspended do |env2, b3|
|
||||
if !env2[:result]
|
||||
b3.use MessageNotSuspended
|
||||
@ -270,31 +260,9 @@ module VagrantPlugins
|
||||
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 ConnectLibvirt
|
||||
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 ConnectLibvirt
|
||||
b.use ReadSSHInfo
|
||||
end
|
||||
end
|
||||
|
||||
def self.action_read_mac_addresses
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use ConnectLibvirt
|
||||
b.use ReadMacAddresses
|
||||
end
|
||||
end
|
||||
@ -309,7 +277,6 @@ module VagrantPlugins
|
||||
next
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use Call, IsRunning do |env2, b3|
|
||||
if !env2[:result]
|
||||
b3.use MessageNotRunning
|
||||
@ -324,7 +291,6 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
action_root = Pathname.new(File.expand_path('../action', __FILE__))
|
||||
autoload :ConnectLibvirt, action_root.join('connect_libvirt')
|
||||
autoload :PackageDomain, action_root.join('package_domain')
|
||||
autoload :CreateDomain, action_root.join('create_domain')
|
||||
autoload :CreateDomainVolume, action_root.join('create_domain_volume')
|
||||
@ -352,9 +318,7 @@ module VagrantPlugins
|
||||
autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
|
||||
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 :ReadState, action_root.join('read_state')
|
||||
autoload :ResumeDomain, action_root.join('resume_domain')
|
||||
autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
require 'fog/libvirt'
|
||||
require 'log4r'
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
class ConnectLibvirt
|
||||
def initialize(app, env)
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::action::connect_libvirt')
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
# If already connected to libvirt, just use it and don't connect
|
||||
# again.
|
||||
if ProviderLibvirt.libvirt_connection
|
||||
env[:libvirt_compute] = ProviderLibvirt.libvirt_connection
|
||||
return @app.call(env)
|
||||
end
|
||||
|
||||
# Get config options for libvirt provider.
|
||||
config = env[:machine].provider_config
|
||||
uri = config.uri
|
||||
|
||||
conn_attr = {}
|
||||
conn_attr[:provider] = 'libvirt'
|
||||
conn_attr[:libvirt_uri] = uri
|
||||
conn_attr[:libvirt_username] = config.username if config.username
|
||||
conn_attr[:libvirt_password] = config.password if config.password
|
||||
|
||||
# Setup command for retrieving IP address for newly created machine
|
||||
# with some MAC address. Get it from dnsmasq leases table
|
||||
ip_command = %q[ awk "/$mac/ {print \$1}" /proc/net/arp ]
|
||||
conn_attr[:libvirt_ip_command] = ip_command
|
||||
|
||||
@logger.info("Connecting to Libvirt (#{uri}) ...")
|
||||
begin
|
||||
env[:libvirt_compute] = Fog::Compute.new(conn_attr)
|
||||
rescue Fog::Errors::Error => e
|
||||
raise Errors::FogLibvirtConnectionError,
|
||||
:error_message => e.message
|
||||
end
|
||||
ProviderLibvirt.libvirt_connection = env[:libvirt_compute]
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -72,7 +72,7 @@ module VagrantPlugins
|
||||
@os_type = 'hvm'
|
||||
|
||||
# Get path to domain image from the storage pool selected.
|
||||
actual_volumes = env[:libvirt_compute].volumes.all.select do |x|
|
||||
actual_volumes = env[:machine].provider.driver.connection.volumes.all.select do |x|
|
||||
x.pool_name == @storage_pool_name
|
||||
end
|
||||
domain_volume = ProviderLibvirt::Util::Collection.find_matching(
|
||||
@ -94,12 +94,12 @@ module VagrantPlugins
|
||||
|
||||
disk[:absolute_path] = storage_prefix + disk[:path]
|
||||
|
||||
if env[:libvirt_compute].volumes.select {
|
||||
if env[:machine].provider.driver.connection.volumes.select {
|
||||
|x| x.name == disk[:name] and x.pool_name == @storage_pool_name}.empty?
|
||||
# make the disk. equivalent to:
|
||||
# qemu-img create -f qcow2 <path> 5g
|
||||
begin
|
||||
env[:libvirt_compute].volumes.create(
|
||||
env[:machine].provider.driver.connection.volumes.create(
|
||||
name: disk[:name],
|
||||
format_type: disk[:type],
|
||||
path: disk[:absolute_path],
|
||||
@ -166,7 +166,7 @@ module VagrantPlugins
|
||||
# Is there a way to tell fog to create new domain with already
|
||||
# existing volume? Use domain creation from template..
|
||||
begin
|
||||
server = env[:libvirt_compute].servers.create(
|
||||
server = env[:machine].provider.driver.connection.servers.create(
|
||||
xml: to_xml('domain'))
|
||||
rescue Fog::Errors::Error => e
|
||||
raise Errors::FogCreateServerError, error_message: e.message
|
||||
|
@ -26,12 +26,12 @@ module VagrantPlugins
|
||||
|
||||
# Verify the volume doesn't exist already.
|
||||
domain_volume = ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].volumes.all, @name)
|
||||
env[:machine].provider.driver.connection.volumes.all, @name)
|
||||
raise Errors::DomainVolumeExists if domain_volume
|
||||
|
||||
# Get path to backing image - box volume.
|
||||
box_volume = ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].volumes.all, env[:box_volume_name])
|
||||
env[:machine].provider.driver.connection.volumes.all, env[:box_volume_name])
|
||||
@backing_file = box_volume.path
|
||||
|
||||
# Virtual size of image. Take value worked out by HandleBoxImage
|
||||
@ -40,7 +40,7 @@ module VagrantPlugins
|
||||
# Create new volume from xml template. Fog currently doesn't support
|
||||
# volume snapshots directly.
|
||||
begin
|
||||
domain_volume = env[:libvirt_compute].volumes.create(
|
||||
domain_volume = env[:machine].provider.driver.connection.volumes.create(
|
||||
:xml => to_xml('volume_snapshot'),
|
||||
:pool_name => config.storage_pool_name)
|
||||
rescue Fog::Errors::Error => e
|
||||
|
@ -27,7 +27,7 @@ module VagrantPlugins
|
||||
def call(env)
|
||||
# Get domain first.
|
||||
begin
|
||||
domain = env[:libvirt_compute].client.lookup_domain_by_uuid(
|
||||
domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
|
||||
env[:machine].id.to_s)
|
||||
rescue => e
|
||||
raise Errors::NoDomainError,
|
||||
@ -61,7 +61,7 @@ module VagrantPlugins
|
||||
# We have slot for interface, fill it with interface configuration.
|
||||
adapters[free_slot] = options
|
||||
adapters[free_slot][:network_name] = interface_network(
|
||||
env[:libvirt_compute].client, adapters[free_slot])
|
||||
env[:machine].provider.driver.connection.client, adapters[free_slot])
|
||||
end
|
||||
|
||||
# Create each interface as new domain device.
|
||||
|
@ -23,7 +23,7 @@ module VagrantPlugins
|
||||
|
||||
@available_networks = []
|
||||
@options = {}
|
||||
@libvirt_client = env[:libvirt_compute].client
|
||||
@libvirt_client = env[:machine].provider.driver.connection.client
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@ -46,7 +46,7 @@ module VagrantPlugins
|
||||
# list is used throughout this class and should be easier to
|
||||
# process than libvirt API calls.
|
||||
@available_networks = libvirt_networks(
|
||||
env[:libvirt_compute].client)
|
||||
env[:machine].provider.driver.connection.client)
|
||||
|
||||
# Prepare a hash describing network for this specific interface.
|
||||
@interface_network = {
|
||||
|
@ -17,7 +17,7 @@ module VagrantPlugins
|
||||
# Fog libvirt currently doesn't support snapshots. Use
|
||||
# ruby-libvirt client directly. Note this is racy, see
|
||||
# http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotListNames
|
||||
libvirt_domain = env[:libvirt_compute].client.lookup_domain_by_uuid(
|
||||
libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
|
||||
env[:machine].id)
|
||||
libvirt_domain.list_snapshots.each do |name|
|
||||
@logger.info("Deleting snapshot '#{name}'")
|
||||
@ -28,7 +28,7 @@ module VagrantPlugins
|
||||
end
|
||||
end
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
|
||||
if env[:machine].provider_config.disks.empty?
|
||||
# if using default configuration of disks
|
||||
|
@ -36,7 +36,7 @@ module VagrantPlugins
|
||||
# lookup_network_by_uuid throws same exception
|
||||
# if there is an error or if the network just doesn't exist
|
||||
begin
|
||||
libvirt_network = env[:libvirt_compute].client.lookup_network_by_uuid(
|
||||
libvirt_network = env[:machine].provider.driver.connection.client.lookup_network_by_uuid(
|
||||
network_uuid)
|
||||
rescue Libvirt::RetrieveError => e
|
||||
# this network is already destroyed, so move on
|
||||
|
@ -13,7 +13,7 @@ module VagrantPlugins
|
||||
def call(env)
|
||||
env[:ui].info(I18n.t("vagrant_libvirt.halt_domain"))
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
raise Errors::NoDomainError if domain == nil
|
||||
|
||||
@logger.info("Trying gracefull shutdown.")
|
||||
|
@ -60,7 +60,7 @@ module VagrantPlugins
|
||||
@@lock.synchronize do
|
||||
# Don't continue if image already exists in storage pool.
|
||||
break if ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].volumes.all, env[:box_volume_name])
|
||||
env[:machine].provider.driver.connection.volumes.all, env[:box_volume_name])
|
||||
|
||||
# Box is not available as a storage pool volume. Create and upload
|
||||
# it as a copy of local box image.
|
||||
@ -73,7 +73,7 @@ module VagrantPlugins
|
||||
message << " in storage pool #{config.storage_pool_name}."
|
||||
@logger.info(message)
|
||||
begin
|
||||
fog_volume = env[:libvirt_compute].volumes.create(
|
||||
fog_volume = env[:machine].provider.driver.connection.volumes.create(
|
||||
name: env[:box_volume_name],
|
||||
allocation: "#{box_image_size/1024/1024}M",
|
||||
capacity: "#{box_virtual_size}G",
|
||||
@ -117,10 +117,10 @@ module VagrantPlugins
|
||||
image_size = File.size(image_file) # B
|
||||
|
||||
begin
|
||||
pool = env[:libvirt_compute].client.lookup_storage_pool_by_name(
|
||||
pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name(
|
||||
pool_name)
|
||||
volume = pool.lookup_volume_by_name(volume_name)
|
||||
stream = env[:libvirt_compute].client.stream
|
||||
stream = env[:machine].provider.driver.connection.client.stream
|
||||
volume.upload(stream, offset=0, length=image_size)
|
||||
|
||||
# Exception ProviderLibvirt::RetrieveError can be raised if buffer is
|
||||
|
@ -23,7 +23,7 @@ module VagrantPlugins
|
||||
@@lock.synchronize do
|
||||
# Check for storage pool, where box image should be created
|
||||
break if ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].pools.all, config.storage_pool_name)
|
||||
env[:machine].provider.driver.connection.pools.all, config.storage_pool_name)
|
||||
|
||||
@logger.info("No storage pool '#{config.storage_pool_name}' is available.")
|
||||
|
||||
@ -36,7 +36,7 @@ module VagrantPlugins
|
||||
# Fog libvirt currently doesn't support creating pools. Use
|
||||
# ruby-libvirt client directly.
|
||||
begin
|
||||
libvirt_pool = env[:libvirt_compute].client.define_storage_pool_xml(
|
||||
libvirt_pool = env[:machine].provider.driver.connection.client.define_storage_pool_xml(
|
||||
to_xml('default_storage_pool'))
|
||||
libvirt_pool.build
|
||||
libvirt_pool.create
|
||||
|
@ -9,7 +9,7 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def call(env)
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
raise Errors::NoDomainError if domain == nil
|
||||
env[:result] = domain.state.to_s == 'running'
|
||||
|
||||
|
@ -9,7 +9,7 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def call(env)
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
raise Errors::NoDomainError if domain == nil
|
||||
env[:result] = domain.state.to_s == 'paused'
|
||||
|
||||
|
@ -14,9 +14,9 @@ module VagrantPlugins
|
||||
|
||||
def call(env)
|
||||
env[:ui].info(I18n.t('vagrant_libvirt.package_domain'))
|
||||
libvirt_domain = env[:libvirt_compute].client.lookup_domain_by_uuid(
|
||||
libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
|
||||
env[:machine].id)
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
root_disk = domain.volumes.select do |x|
|
||||
x.name == libvirt_domain.name + '.img'
|
||||
end.first
|
||||
|
@ -8,7 +8,7 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def call(env)
|
||||
env[:nfs_valid_ids] = env[:libvirt_compute].servers.all.map(&:id)
|
||||
env[:nfs_valid_ids] = env[:machine].provider.driver.connection.servers.all.map(&:id)
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
@ -12,7 +12,7 @@ module VagrantPlugins
|
||||
if env[:host]
|
||||
uuid = env[:machine].id
|
||||
# get all uuids
|
||||
uuids = env[:libvirt_compute].servers.all.map(&:id)
|
||||
uuids = env[:machine].provider.driver.connection.servers.all.map(&:id)
|
||||
# not exiisted in array will removed from nfs
|
||||
uuids.delete(uuid)
|
||||
env[:host].capability(
|
||||
|
@ -10,7 +10,7 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def call(env)
|
||||
env[:machine_mac_addresses] = read_mac_addresses(env[:libvirt_compute], env[:machine])
|
||||
env[:machine_mac_addresses] = read_mac_addresses(env[:machine].provider.driver.connection, env[:machine])
|
||||
end
|
||||
|
||||
def read_mac_addresses(libvirt, machine)
|
||||
|
@ -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[:libvirt_compute],
|
||||
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[:libvirt_compute], 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
|
@ -22,7 +22,7 @@ module VagrantPlugins
|
||||
config = env[:machine].provider_config
|
||||
# Check for storage pool, where box image should be created
|
||||
fog_pool = ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].pools.all, config.storage_pool_name)
|
||||
env[:machine].provider.driver.connection.pools.all, config.storage_pool_name)
|
||||
@logger.debug("**** Pool #{fog_pool.name}")
|
||||
|
||||
# This is name of newly created image for vm.
|
||||
@ -31,7 +31,7 @@ module VagrantPlugins
|
||||
|
||||
# remove root storage
|
||||
box_volume = ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].volumes.all, name)
|
||||
env[:machine].provider.driver.connection.volumes.all, name)
|
||||
if box_volume && box_volume.pool_name == fog_pool.name
|
||||
@logger.info("Deleting volume #{box_volume.key}")
|
||||
box_volume.destroy
|
||||
|
@ -13,7 +13,7 @@ module VagrantPlugins
|
||||
def call(env)
|
||||
env[:ui].info(I18n.t("vagrant_libvirt.resuming_domain"))
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
raise Errors::NoDomainError if domain == nil
|
||||
|
||||
domain.resume
|
||||
|
@ -14,11 +14,12 @@ module VagrantPlugins
|
||||
env[:domain_name] = build_domain_name(env)
|
||||
|
||||
begin
|
||||
@logger.info("Looking for domain #{env[:domain_name]} through list #{env[:libvirt_compute].servers.all}")
|
||||
@logger.info("Looking for domain #{env[:domain_name]} through list " +
|
||||
"#{env[:machine].provider.driver.connection.servers.all}")
|
||||
# Check if the domain name is not already taken
|
||||
|
||||
domain = ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].servers.all, env[:domain_name])
|
||||
env[:machine].provider.driver.connection.servers.all, env[:domain_name])
|
||||
rescue Fog::Errors::Error => e
|
||||
@logger.info("#{e}")
|
||||
domain = nil
|
||||
|
@ -14,7 +14,7 @@ module VagrantPlugins
|
||||
def call(env)
|
||||
env[:ui].info(I18n.t("vagrant_libvirt.starting_domain"))
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
raise Errors::NoDomainError if domain == nil
|
||||
|
||||
begin
|
||||
|
@ -14,7 +14,7 @@ module VagrantPlugins
|
||||
def call(env)
|
||||
env[:ui].info(I18n.t("vagrant_libvirt.suspending_domain"))
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
raise Errors::NoDomainError if domain == nil
|
||||
|
||||
domain.suspend
|
||||
|
@ -21,7 +21,7 @@ module VagrantPlugins
|
||||
env[:metrics] ||= {}
|
||||
|
||||
# Get domain object
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
||||
raise NoDomainError if domain == nil
|
||||
|
||||
# Wait for domain to obtain an ip address. Ip address is searched
|
||||
|
@ -25,13 +25,13 @@ module VagrantPlugins
|
||||
|
||||
# <filesystem/> support in device attach/detach introduced in 1.2.2
|
||||
# version number format is major * 1,000,000 + minor * 1,000 + release
|
||||
libvirt_version = ProviderLibvirt.libvirt_connection.client.libversion
|
||||
libvirt_version = machine.provider.driver.connection.client.libversion
|
||||
libvirt_version >= 1_002_002
|
||||
end
|
||||
|
||||
def prepare(machine, folders, _opts)
|
||||
raise Vagrant::Errors::Error('No libvirt connection') if ProviderLibvirt.libvirt_connection.nil?
|
||||
@conn = ProviderLibvirt.libvirt_connection.client
|
||||
raise Vagrant::Errors::Error('No libvirt connection') if machine.provider.driver.connection.nil?
|
||||
@conn = machine.provider.driver.connection.client
|
||||
|
||||
begin
|
||||
# loop through folders
|
||||
@ -73,10 +73,10 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def cleanup(machine, _opts)
|
||||
if ProviderLibvirt.libvirt_connection.nil?
|
||||
if machine.provider.driver.connection.nil?
|
||||
raise Vagrant::Errors::Error('No libvirt connection')
|
||||
end
|
||||
@conn = ProviderLibvirt.libvirt_connection.client
|
||||
@conn = machine.provider.driver.connection.client
|
||||
begin
|
||||
if machine.id && machine.id != ''
|
||||
dom = @conn.lookup_domain_by_uuid(machine.id)
|
||||
|
121
lib/vagrant-libvirt/driver.rb
Normal file
121
lib/vagrant-libvirt/driver.rb
Normal file
@ -0,0 +1,121 @@
|
||||
require 'fog/libvirt'
|
||||
require 'log4r'
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
class Driver
|
||||
|
||||
# store the connection at the process level
|
||||
#
|
||||
# possibly this should be a connection pool using the connection
|
||||
# settings as a key to allow per machine connection attributes
|
||||
# to be used.
|
||||
@@connection = nil
|
||||
|
||||
def initialize(machine)
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::driver')
|
||||
@machine = machine
|
||||
end
|
||||
|
||||
def connection
|
||||
# If already connected to libvirt, just use it and don't connect
|
||||
# again.
|
||||
return @@connection if @@connection
|
||||
|
||||
# Get config options for libvirt provider.
|
||||
config = @machine.provider_config
|
||||
uri = config.uri
|
||||
|
||||
conn_attr = {}
|
||||
conn_attr[:provider] = 'libvirt'
|
||||
conn_attr[:libvirt_uri] = uri
|
||||
conn_attr[:libvirt_username] = config.username if config.username
|
||||
conn_attr[:libvirt_password] = config.password if config.password
|
||||
|
||||
# Setup command for retrieving IP address for newly created machine
|
||||
# with some MAC address. Get it from dnsmasq leases table
|
||||
ip_command = %q[ awk "/$mac/ {print \$1}" /proc/net/arp ]
|
||||
conn_attr[:libvirt_ip_command] = ip_command
|
||||
|
||||
@logger.info("Connecting to Libvirt (#{uri}) ...")
|
||||
begin
|
||||
@@connection = Fog::Compute.new(conn_attr)
|
||||
rescue Fog::Errors::Error => e
|
||||
raise Errors::FogLibvirtConnectionError,
|
||||
:error_message => e.message
|
||||
end
|
||||
|
||||
@@connection
|
||||
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)
|
||||
# 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
|
||||
|
||||
# TODO: terminated no longer appears to be a valid fog state, remove?
|
||||
if domain.nil? || domain.state.to_sym == :terminated
|
||||
return :not_created
|
||||
end
|
||||
|
||||
return domain.state.gsub("-", "_").to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -2,6 +2,7 @@ require 'vagrant'
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
autoload :Driver, 'vagrant-libvirt/driver'
|
||||
|
||||
# This is the base class for a provider for the V2 API. A provider
|
||||
# is responsible for creating compute resources to match the
|
||||
@ -22,6 +23,12 @@ module VagrantPlugins
|
||||
nil
|
||||
end
|
||||
|
||||
def driver
|
||||
return @driver if @driver
|
||||
|
||||
@driver = Driver.new(@machine)
|
||||
end
|
||||
|
||||
# This method is called if the underying machine ID changes. Providers
|
||||
# can use this method to load in new data for the actual backing
|
||||
# machine or to realize that the machine is now gone (the ID can
|
||||
@ -33,9 +40,8 @@ module VagrantPlugins
|
||||
# SSH into the machine. If the machine is not at a point where
|
||||
# SSH is even possible, then `nil` should be returned.
|
||||
def ssh_info
|
||||
# Run a custom action called "read_ssh_info" which does what it says
|
||||
# and puts the resulting SSH info into the `:machine_ssh_info` key in
|
||||
# the environment.
|
||||
# Return the ssh_info if already retrieved otherwise call the driver
|
||||
# and save the result.
|
||||
#
|
||||
# Ssh info has following format..
|
||||
#
|
||||
@ -45,8 +51,32 @@ module VagrantPlugins
|
||||
# :username => "mitchellh",
|
||||
# :private_key_path => "/path/to/my/key"
|
||||
#}
|
||||
env = @machine.action('read_ssh_info', :lock => false)
|
||||
env[:machine_ssh_info]
|
||||
# note that modifing @machine.id or accessing @machine.state is not
|
||||
# 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
|
||||
|
||||
def mac_addresses
|
||||
@ -64,16 +94,28 @@ module VagrantPlugins
|
||||
# This should return the state of the machine within this provider.
|
||||
# The state must be an instance of {MachineState}.
|
||||
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
|
||||
short = I18n.t("vagrant_libvirt.states.short_#{state_id}")
|
||||
long = I18n.t("vagrant_libvirt.states.long_#{state_id}")
|
||||
short = state_id.to_s.gsub("_", " ")
|
||||
long = I18n.t("vagrant_libvirt.states.#{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
|
||||
Vagrant::MachineState.new(state_id, short, long)
|
||||
|
@ -139,19 +139,18 @@ en:
|
||||
TCP tunnel port not defined.
|
||||
|
||||
states:
|
||||
short_paused: |-
|
||||
pause
|
||||
short_shutoff: |-
|
||||
shutoff
|
||||
long_shutoff: |-
|
||||
paused: |-
|
||||
The Libvirt domain is suspended. Run `vagrant resume` to resume it.
|
||||
shutting_down: |-
|
||||
The Libvirt domain is shutting down. Wait for it to complete and
|
||||
then run `vagrant up` to start it or `vagrant destroy` to remove.
|
||||
shutoff: |-
|
||||
The Libvirt domain is not running. Run `vagrant up` to start it.
|
||||
short_not_created: |-
|
||||
not created
|
||||
long_not_created: |-
|
||||
not_created: |-
|
||||
The Libvirt domain is not created. Run `vagrant up` to create it.
|
||||
|
||||
short_running: |-
|
||||
running
|
||||
long_running: |-
|
||||
running: |-
|
||||
The Libvirt domain is running. To stop this machine, you can run
|
||||
`vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
|
||||
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