From db440907f7ea55bca16eb66802885ccd21df758d Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Tue, 28 Jul 2015 09:57:48 +0100 Subject: [PATCH 1/4] Move libvirt connection setup to driver Handle libvirt connection through a driver located within the provider so it can be reached via the machine settings. Adopt the format followed by the docker/virtualbox providers as this is likely to remain well supported. Will allow queries to be made without needing to setup a specific action which is important when dealing with parallel machine provisioning. Calling actions from other threads to retrieve information on the state of the other running machines currently will cause vagrant to complain about the machine being locked. --- lib/vagrant-libvirt.rb | 14 ----- lib/vagrant-libvirt/action.rb | 15 ------ lib/vagrant-libvirt/action/connect_libvirt.rb | 51 ------------------ lib/vagrant-libvirt/action/create_domain.rb | 8 +-- .../action/create_domain_volume.rb | 6 +-- .../action/create_network_interfaces.rb | 4 +- lib/vagrant-libvirt/action/create_networks.rb | 4 +- lib/vagrant-libvirt/action/destroy_domain.rb | 4 +- .../action/destroy_networks.rb | 2 +- lib/vagrant-libvirt/action/halt_domain.rb | 2 +- .../action/handle_box_image.rb | 8 +-- .../action/handle_storage_pool.rb | 4 +- lib/vagrant-libvirt/action/is_running.rb | 2 +- lib/vagrant-libvirt/action/is_suspended.rb | 2 +- lib/vagrant-libvirt/action/package_domain.rb | 4 +- .../action/prepare_nfs_valid_ids.rb | 2 +- .../action/prune_nfs_exports.rb | 2 +- .../action/read_mac_addresses.rb | 2 +- lib/vagrant-libvirt/action/read_ssh_info.rb | 2 +- lib/vagrant-libvirt/action/read_state.rb | 2 +- .../action/remove_stale_volume.rb | 4 +- lib/vagrant-libvirt/action/resume_domain.rb | 2 +- .../action/set_name_of_domain.rb | 5 +- lib/vagrant-libvirt/action/start_domain.rb | 2 +- lib/vagrant-libvirt/action/suspend_domain.rb | 2 +- lib/vagrant-libvirt/action/wait_till_up.rb | 2 +- lib/vagrant-libvirt/cap/synced_folder.rb | 10 ++-- lib/vagrant-libvirt/driver.rb | 52 +++++++++++++++++++ lib/vagrant-libvirt/provider.rb | 7 +++ 29 files changed, 103 insertions(+), 123 deletions(-) delete mode 100644 lib/vagrant-libvirt/action/connect_libvirt.rb create mode 100644 lib/vagrant-libvirt/driver.rb diff --git a/lib/vagrant-libvirt.rb b/lib/vagrant-libvirt.rb index 825e5fa..a579f93 100644 --- a/lib/vagrant-libvirt.rb +++ b/lib/vagrant-libvirt.rb @@ -8,20 +8,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 48f1605..042a679 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 @@ -186,7 +180,6 @@ module VagrantPlugins next end - b2.use ConnectLibvirt b2.use Call, IsRunning do |env2, b3| if !env2[:result] b3.use MessageNotRunning @@ -209,7 +202,6 @@ module VagrantPlugins next end - b2.use ConnectLibvirt b2.use Call, IsRunning do |env2, b3| if !env2[:result] b3.use MessageNotRunning @@ -234,7 +226,6 @@ module VagrantPlugins next end - b2.use ConnectLibvirt b2.use Call, IsRunning do |env2, b3| if !env2[:result] b3.use MessageNotRunning @@ -257,7 +248,6 @@ module VagrantPlugins next end - b2.use ConnectLibvirt b2.use Call, IsSuspended do |env2, b3| if !env2[:result] b3.use MessageNotSuspended @@ -274,7 +264,6 @@ module VagrantPlugins def self.action_read_state Vagrant::Action::Builder.new.tap do |b| b.use ConfigValidate - b.use ConnectLibvirt b.use ReadState end end @@ -285,7 +274,6 @@ module VagrantPlugins def self.action_read_ssh_info Vagrant::Action::Builder.new.tap do |b| b.use ConfigValidate - b.use ConnectLibvirt b.use ReadSSHInfo end end @@ -293,7 +281,6 @@ module VagrantPlugins def self.action_read_mac_addresses Vagrant::Action::Builder.new.tap do |b| b.use ConfigValidate - b.use ConnectLibvirt b.use ReadMacAddresses end end @@ -308,7 +295,6 @@ module VagrantPlugins next end - b2.use ConnectLibvirt b2.use Call, IsRunning do |env2, b3| if !env2[:result] b3.use MessageNotRunning @@ -323,7 +309,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') 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 92f2041..23b6994 100644 --- a/lib/vagrant-libvirt/action/create_domain.rb +++ b/lib/vagrant-libvirt/action/create_domain.rb @@ -69,7 +69,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( @@ -91,12 +91,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], @@ -161,7 +161,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 index 3d7ea9d..4de7308 100644 --- a/lib/vagrant-libvirt/action/read_ssh_info.rb +++ b/lib/vagrant-libvirt/action/read_ssh_info.rb @@ -12,7 +12,7 @@ module VagrantPlugins end def call(env) - env[:machine_ssh_info] = read_ssh_info(env[:libvirt_compute], + env[:machine_ssh_info] = read_ssh_info(env[:machine].provider.driver.connection, env[:machine]) @app.call(env) diff --git a/lib/vagrant-libvirt/action/read_state.rb b/lib/vagrant-libvirt/action/read_state.rb index 1848de4..20e313a 100644 --- a/lib/vagrant-libvirt/action/read_state.rb +++ b/lib/vagrant-libvirt/action/read_state.rb @@ -12,7 +12,7 @@ module VagrantPlugins end def call(env) - env[:machine_state_id] = read_state(env[:libvirt_compute], env[:machine]) + env[:machine_state_id] = read_state(env[:machine].provider.driver.connection, env[:machine]) @app.call(env) 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..25376b8 --- /dev/null +++ b/lib/vagrant-libvirt/driver.rb @@ -0,0 +1,52 @@ +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 + end + end +end diff --git a/lib/vagrant-libvirt/provider.rb b/lib/vagrant-libvirt/provider.rb index e1053fa..8d41827 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 From cee934a4821c09a20b240fa3ec017078914a23f2 Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Tue, 28 Jul 2015 14:27:49 +0100 Subject: [PATCH 2/4] 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. --- lib/vagrant-libvirt/action.rb | 21 ------ lib/vagrant-libvirt/action/read_ssh_info.rb | 68 ----------------- lib/vagrant-libvirt/action/read_state.rb | 60 --------------- lib/vagrant-libvirt/driver.rb | 82 +++++++++++++++++++++ lib/vagrant-libvirt/provider.rb | 55 +++++++++++--- locales/en.yml | 5 ++ 6 files changed, 132 insertions(+), 159 deletions(-) delete mode 100644 lib/vagrant-libvirt/action/read_ssh_info.rb delete mode 100644 lib/vagrant-libvirt/action/read_state.rb diff --git a/lib/vagrant-libvirt/action.rb b/lib/vagrant-libvirt/action.rb index 042a679..1ed3576 100644 --- a/lib/vagrant-libvirt/action.rb +++ b/lib/vagrant-libvirt/action.rb @@ -259,25 +259,6 @@ 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 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 Vagrant::Action::Builder.new.tap do |b| b.use ConfigValidate @@ -336,9 +317,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/read_ssh_info.rb b/lib/vagrant-libvirt/action/read_ssh_info.rb deleted file mode 100644 index 4de7308..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[: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 diff --git a/lib/vagrant-libvirt/action/read_state.rb b/lib/vagrant-libvirt/action/read_state.rb deleted file mode 100644 index 20e313a..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[: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 diff --git a/lib/vagrant-libvirt/driver.rb b/lib/vagrant-libvirt/driver.rb index 25376b8..8e7fea0 100644 --- a/lib/vagrant-libvirt/driver.rb +++ b/lib/vagrant-libvirt/driver.rb @@ -47,6 +47,88 @@ module VagrantPlugins @@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) + # 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 diff --git a/lib/vagrant-libvirt/provider.rb b/lib/vagrant-libvirt/provider.rb index 8d41827..05873ac 100644 --- a/lib/vagrant-libvirt/provider.rb +++ b/lib/vagrant-libvirt/provider.rb @@ -40,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.. # @@ -52,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 @@ -71,17 +94,29 @@ 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}") + # 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) end diff --git a/locales/en.yml b/locales/en.yml index 1ab8e78..52617a0 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -155,3 +155,8 @@ en: long_running: |- The Libvirt domain is running. To stop this machine, you can run `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. From e7dec9acc38a3450409dbddaa1037c8592284c20 Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Tue, 28 Jul 2015 14:55:06 +0100 Subject: [PATCH 3/4] Condense state description retrieval Reduce state description retrieval to keying off the state id and use a simple substitution for the short name of the same. --- lib/vagrant-libvirt/provider.rb | 4 ++-- locales/en.yml | 21 ++++++--------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/lib/vagrant-libvirt/provider.rb b/lib/vagrant-libvirt/provider.rb index 05873ac..865edda 100644 --- a/lib/vagrant-libvirt/provider.rb +++ b/lib/vagrant-libvirt/provider.rb @@ -109,8 +109,8 @@ module VagrantPlugins 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 diff --git a/locales/en.yml b/locales/en.yml index 52617a0..3de6566 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -139,24 +139,15 @@ 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. + 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`. - short_preparing: |- - preparing - long_preparing: |- + preparing: |- The vagrant machine is being prepared for creation, please wait for it to reach a steady state before issuing commands on it. From efeb6c6b8a7061c5738a7255c7902ef22b468f12 Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Tue, 28 Jul 2015 15:41:13 +0100 Subject: [PATCH 4/4] Allow shutting-down state to be returned If the machine is in a shutting-down state, simply return this instead of waiting until the machine has reached a steady state. --- lib/vagrant-libvirt/driver.rb | 23 +++++------------------ locales/en.yml | 3 +++ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/lib/vagrant-libvirt/driver.rb b/lib/vagrant-libvirt/driver.rb index 8e7fea0..fe7a03e 100644 --- a/lib/vagrant-libvirt/driver.rb +++ b/lib/vagrant-libvirt/driver.rb @@ -101,10 +101,6 @@ module VagrantPlugins 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) @@ -113,21 +109,12 @@ module VagrantPlugins 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) + # 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 diff --git a/locales/en.yml b/locales/en.yml index 3de6566..315b6ff 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -141,6 +141,9 @@ en: states: 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. not_created: |-