diff --git a/README.md b/README.md index 48e9b54..a8d3380 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,6 @@ This provider exposes quite a few provider-specific configuration options: * `password` - Password to access Libvirt. * `id_ssh_key_file` - The id ssh key file name to access Libvirt (eg: id_dsa or id_rsa or ... in the user .ssh directory) * `storage_pool_name` - Libvirt storage pool name, where box image and instance snapshots will be stored. -* `management_network_name` - Name of libvirt network to which all VMs will be connected. If not specified the default is 'vagrant-libvirt'. -* `management_network_address` - Address of network to which all VMs will be connected. Must include the address and subnet mask. If not specified the default is '192.168.121.0/24'. ### Domain Specific Options @@ -236,15 +234,24 @@ starts with 'libvirt__' string. Here is a list of those options: Default mode is 'bridge'. * `:mac` - MAC address for the interface. -## Obtaining Domain IP Address +### Management Network -Libvirt doesn't provide standard way how to find out an IP address of running -domain. But we know, what is MAC address of virtual machine. Libvirt is closely -connected with dnsmasq server, which acts also as a DHCP server. Dnsmasq server -makes lease information public in `/var/lib/libvirt/dnsmasq` directory, or in -`/var/lib/misc/dnsmasq.leases` file on some systems. This is the place, where -information like which MAC address has which IP address resides and it's parsed -by vagrant-libvirt plugin. +Vagrant-libvirt uses a private network to perform some management operations +on VMs. All VMs will have an interface connected to this network and +an IP address dynamically assigned by libvirt. This is in addition to any +networks you configure. The name and address used by this network are +configurable at the provider level. + +* `management_network_name` - Name of libvirt network to which all VMs will be connected. If not specified the default is 'vagrant-libvirt'. +* `management_network_address` - Address of network to which all VMs will be connected. Must include the address and subnet mask. If not specified the default is '192.168.121.0/24'. + +You may wonder how vagrant-libvirt knows the IP address a VM received. +Libvirt doesn't provide a standard way to find out the IP address of a running +domain. But we do know the MAC address of the virtual machine's interface on +the management network. Libvirt is closely connected with dnsmasq, which acts as +a DHCP server. dnsmasq writes lease information in the `/var/lib/libvirt/dnsmasq` +directory. Vagrant-libvirt looks for the MAC address in this file and extracts +the corresponding IP address. ## SSH Access To VM diff --git a/lib/vagrant-libvirt/action.rb b/lib/vagrant-libvirt/action.rb index 1f3547f..164476b 100644 --- a/lib/vagrant-libvirt/action.rb +++ b/lib/vagrant-libvirt/action.rb @@ -57,14 +57,18 @@ module VagrantPlugins next if env[:result] b2.use Call, IsSuspended do |env2, b3| + # if vm is suspended resume it then exit if env2[:result] b3.use ResumeDomain next end - # VM is not running or suspended. Start it.. Machine should gain - # IP address when comming up, so wait for dhcp lease and store IP - # into machines data_dir. + # VM is not running or suspended. + + # Ensure networks are created and active + b3.use CreateNetworks + + # Handle shared folders if Vagrant::VERSION < "1.4.0" b3.use NFS else @@ -74,7 +78,11 @@ module VagrantPlugins b3.use PrepareNFSSettings b3.use ShareFolders + # Start it.. b3.use StartDomain + + # Machine should gain IP address when comming up, + # so wait for dhcp lease and store IP into machines data_dir. b3.use WaitTillUp end end diff --git a/lib/vagrant-libvirt/action/destroy_networks.rb b/lib/vagrant-libvirt/action/destroy_networks.rb index f1af002..6dfcaca 100644 --- a/lib/vagrant-libvirt/action/destroy_networks.rb +++ b/lib/vagrant-libvirt/action/destroy_networks.rb @@ -18,7 +18,7 @@ module VagrantPlugins # data directory, created_networks file holds UUIDs of each network. created_networks_file = env[:machine].data_dir + 'created_networks' - @logger.info 'Attepmt destroy network' + @logger.info 'Checking if any networks were created' # If created_networks file doesn't exist, there are no networks we # need to remove. unless File.exist?(created_networks_file) @@ -26,39 +26,45 @@ module VagrantPlugins return @app.call(env) end - @logger.info 'file with network exists' + @logger.info 'File with created networks exists' # Iterate over each created network UUID and try to remove it. created_networks = [] file = File.open(created_networks_file, 'r') file.readlines.each do |network_uuid| - @logger.info network_uuid + @logger.info "Checking for #{network_uuid}" + # 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( network_uuid) - rescue - raise network_uuid - next + rescue Libvirt::RetrieveError => e + # this network is already destroyed, so move on + if e.message =~ /Network not found/ + @logger.info "It is already undefined" + next + # some other error occured, so raise it again + else + raise e + end end - # Maybe network doesn't exist anymore. - next unless libvirt_network - # Skip removing if network has still active connections. xml = Nokogiri::XML(libvirt_network.xml_desc) connections = xml.xpath('/network/@connections').first - @logger.info connections if connections != nil + @logger.info "Still has connections so will not undefine" created_networks << network_uuid next end - # Shutdown network first. - libvirt_network.destroy + # Shutdown network first. # Undefine network. begin + libvirt_network.destroy libvirt_network.undefine + @logger.info "Undefined it" rescue => e raise Error::DestroyNetworkError, network_name: libvirt_network.name, @@ -68,13 +74,16 @@ module VagrantPlugins file.close # Update status of created networks after removing some/all of them. + # Not sure why we are doing this, something else seems to always delete the file if created_networks.length > 0 File.open(created_networks_file, 'w') do |file| + @logger.info "Writing new created_networks file" created_networks.each do |network_uuid| file.puts network_uuid end end else + @logger.info "Deleting created_networks file" File.delete(created_networks_file) end