diff --git a/lib/vagrant-libvirt.rb b/lib/vagrant-libvirt.rb index 24322c0..6118d71 100644 --- a/lib/vagrant-libvirt.rb +++ b/lib/vagrant-libvirt.rb @@ -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 diff --git a/lib/vagrant-libvirt/action.rb b/lib/vagrant-libvirt/action.rb index 4fba536..e600ae8 100644 --- a/lib/vagrant-libvirt/action.rb +++ b/lib/vagrant-libvirt/action.rb @@ -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') diff --git a/lib/vagrant-libvirt/action/connect_libvirt.rb b/lib/vagrant-libvirt/action/connect_libvirt.rb deleted file mode 100644 index d34f6c5..0000000 --- a/lib/vagrant-libvirt/action/connect_libvirt.rb +++ /dev/null @@ -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 - diff --git a/lib/vagrant-libvirt/action/create_domain.rb b/lib/vagrant-libvirt/action/create_domain.rb index 80fbbba..c8062a3 100644 --- a/lib/vagrant-libvirt/action/create_domain.rb +++ b/lib/vagrant-libvirt/action/create_domain.rb @@ -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 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 diff --git a/lib/vagrant-libvirt/action/create_domain_volume.rb b/lib/vagrant-libvirt/action/create_domain_volume.rb index 04ff9c8..e5c1acf 100644 --- a/lib/vagrant-libvirt/action/create_domain_volume.rb +++ b/lib/vagrant-libvirt/action/create_domain_volume.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/create_network_interfaces.rb b/lib/vagrant-libvirt/action/create_network_interfaces.rb index 88ab821..6ed1fd8 100644 --- a/lib/vagrant-libvirt/action/create_network_interfaces.rb +++ b/lib/vagrant-libvirt/action/create_network_interfaces.rb @@ -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. diff --git a/lib/vagrant-libvirt/action/create_networks.rb b/lib/vagrant-libvirt/action/create_networks.rb index b8cb08d..728ec33 100644 --- a/lib/vagrant-libvirt/action/create_networks.rb +++ b/lib/vagrant-libvirt/action/create_networks.rb @@ -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 = { diff --git a/lib/vagrant-libvirt/action/destroy_domain.rb b/lib/vagrant-libvirt/action/destroy_domain.rb index e4610be..1312f5e 100644 --- a/lib/vagrant-libvirt/action/destroy_domain.rb +++ b/lib/vagrant-libvirt/action/destroy_domain.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/destroy_networks.rb b/lib/vagrant-libvirt/action/destroy_networks.rb index 6dfcaca..c571c4b 100644 --- a/lib/vagrant-libvirt/action/destroy_networks.rb +++ b/lib/vagrant-libvirt/action/destroy_networks.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/halt_domain.rb b/lib/vagrant-libvirt/action/halt_domain.rb index bf84c95..392f5dd 100644 --- a/lib/vagrant-libvirt/action/halt_domain.rb +++ b/lib/vagrant-libvirt/action/halt_domain.rb @@ -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.") diff --git a/lib/vagrant-libvirt/action/handle_box_image.rb b/lib/vagrant-libvirt/action/handle_box_image.rb index 2cf87ac..2db7718 100644 --- a/lib/vagrant-libvirt/action/handle_box_image.rb +++ b/lib/vagrant-libvirt/action/handle_box_image.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/handle_storage_pool.rb b/lib/vagrant-libvirt/action/handle_storage_pool.rb index f567687..2f2bf8e 100644 --- a/lib/vagrant-libvirt/action/handle_storage_pool.rb +++ b/lib/vagrant-libvirt/action/handle_storage_pool.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/is_running.rb b/lib/vagrant-libvirt/action/is_running.rb index f2d47e5..6512c12 100644 --- a/lib/vagrant-libvirt/action/is_running.rb +++ b/lib/vagrant-libvirt/action/is_running.rb @@ -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' diff --git a/lib/vagrant-libvirt/action/is_suspended.rb b/lib/vagrant-libvirt/action/is_suspended.rb index 6bb3257..b5bf3d0 100644 --- a/lib/vagrant-libvirt/action/is_suspended.rb +++ b/lib/vagrant-libvirt/action/is_suspended.rb @@ -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' diff --git a/lib/vagrant-libvirt/action/package_domain.rb b/lib/vagrant-libvirt/action/package_domain.rb index 8c6c8b0..ab3aec5 100644 --- a/lib/vagrant-libvirt/action/package_domain.rb +++ b/lib/vagrant-libvirt/action/package_domain.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/prepare_nfs_valid_ids.rb b/lib/vagrant-libvirt/action/prepare_nfs_valid_ids.rb index 0eaf69d..2fe086a 100644 --- a/lib/vagrant-libvirt/action/prepare_nfs_valid_ids.rb +++ b/lib/vagrant-libvirt/action/prepare_nfs_valid_ids.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/prune_nfs_exports.rb b/lib/vagrant-libvirt/action/prune_nfs_exports.rb index 3b8eef8..3d2bc8a 100644 --- a/lib/vagrant-libvirt/action/prune_nfs_exports.rb +++ b/lib/vagrant-libvirt/action/prune_nfs_exports.rb @@ -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( diff --git a/lib/vagrant-libvirt/action/read_mac_addresses.rb b/lib/vagrant-libvirt/action/read_mac_addresses.rb index 42db4c0..b4f1063 100644 --- a/lib/vagrant-libvirt/action/read_mac_addresses.rb +++ b/lib/vagrant-libvirt/action/read_mac_addresses.rb @@ -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) diff --git a/lib/vagrant-libvirt/action/read_ssh_info.rb b/lib/vagrant-libvirt/action/read_ssh_info.rb deleted file mode 100644 index 3d7ea9d..0000000 --- a/lib/vagrant-libvirt/action/read_ssh_info.rb +++ /dev/null @@ -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 diff --git a/lib/vagrant-libvirt/action/read_state.rb b/lib/vagrant-libvirt/action/read_state.rb deleted file mode 100644 index 1848de4..0000000 --- a/lib/vagrant-libvirt/action/read_state.rb +++ /dev/null @@ -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 diff --git a/lib/vagrant-libvirt/action/remove_stale_volume.rb b/lib/vagrant-libvirt/action/remove_stale_volume.rb index 5b3c876..88dfcbe 100644 --- a/lib/vagrant-libvirt/action/remove_stale_volume.rb +++ b/lib/vagrant-libvirt/action/remove_stale_volume.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/resume_domain.rb b/lib/vagrant-libvirt/action/resume_domain.rb index 38a9810..1f0dc84 100644 --- a/lib/vagrant-libvirt/action/resume_domain.rb +++ b/lib/vagrant-libvirt/action/resume_domain.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/set_name_of_domain.rb b/lib/vagrant-libvirt/action/set_name_of_domain.rb index 99bc330..e22f710 100644 --- a/lib/vagrant-libvirt/action/set_name_of_domain.rb +++ b/lib/vagrant-libvirt/action/set_name_of_domain.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/start_domain.rb b/lib/vagrant-libvirt/action/start_domain.rb index 0d23d70..f03b13b 100644 --- a/lib/vagrant-libvirt/action/start_domain.rb +++ b/lib/vagrant-libvirt/action/start_domain.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/suspend_domain.rb b/lib/vagrant-libvirt/action/suspend_domain.rb index a350cbc..60027c4 100644 --- a/lib/vagrant-libvirt/action/suspend_domain.rb +++ b/lib/vagrant-libvirt/action/suspend_domain.rb @@ -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 diff --git a/lib/vagrant-libvirt/action/wait_till_up.rb b/lib/vagrant-libvirt/action/wait_till_up.rb index 0081b23..431a35f 100644 --- a/lib/vagrant-libvirt/action/wait_till_up.rb +++ b/lib/vagrant-libvirt/action/wait_till_up.rb @@ -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 diff --git a/lib/vagrant-libvirt/cap/synced_folder.rb b/lib/vagrant-libvirt/cap/synced_folder.rb index 9d3ca8d..6821a44 100644 --- a/lib/vagrant-libvirt/cap/synced_folder.rb +++ b/lib/vagrant-libvirt/cap/synced_folder.rb @@ -25,13 +25,13 @@ module VagrantPlugins # 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) diff --git a/lib/vagrant-libvirt/driver.rb b/lib/vagrant-libvirt/driver.rb new file mode 100644 index 0000000..fe7a03e --- /dev/null +++ b/lib/vagrant-libvirt/driver.rb @@ -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 diff --git a/lib/vagrant-libvirt/provider.rb b/lib/vagrant-libvirt/provider.rb index e1053fa..865edda 100644 --- a/lib/vagrant-libvirt/provider.rb +++ b/lib/vagrant-libvirt/provider.rb @@ -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) diff --git a/locales/en.yml b/locales/en.yml index 1ab8e78..315b6ff 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -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.