mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
IP of VM is searched in dnsmasq lease files only.
This commit is contained in:
35
README.md
35
README.md
@@ -34,7 +34,7 @@ $ vagrant plugin install vagrant-libvirt
|
||||
### Possible problems with plugin installation
|
||||
|
||||
In case of problems with building nokogiri gem, install missing development
|
||||
libraries libxslt and libxml2.
|
||||
libraries for libxslt, libxml2 and libvirt.
|
||||
|
||||
In Ubuntu, Debian, ...
|
||||
```
|
||||
@@ -55,7 +55,6 @@ want. This is just an example of Libvirt CentOS 6.4 box available:
|
||||
|
||||
```
|
||||
$ vagrant box add centos64 http://kwok.cz/centos64.box
|
||||
...
|
||||
```
|
||||
|
||||
And then make a Vagrantfile that looks like the following, filling in
|
||||
@@ -96,7 +95,6 @@ In prepared project directory, run following command:
|
||||
|
||||
```
|
||||
$ vagrant up --provider=libvirt
|
||||
...
|
||||
```
|
||||
|
||||
Vagrant needs to know that we want to use Libvirt and not default VirtualBox.
|
||||
@@ -106,6 +104,8 @@ Vagrant to use Libvirt provider is to setup environment variable
|
||||
|
||||
### How Project Is Created
|
||||
|
||||
Vagrant goes through steps below when creating new project:
|
||||
|
||||
1. Connect to Libvirt localy or remotely via SSH.
|
||||
2. Check if box image is available in Libvirt storage pool. If not, upload it to
|
||||
remote Libvirt storage pool as new volume.
|
||||
@@ -114,7 +114,8 @@ Vagrant to use Libvirt provider is to setup environment variable
|
||||
5. Check for DHCP lease from dnsmasq server. Store IP address into
|
||||
machines *data_dir* for later use, when lease information is not
|
||||
available. Then wait till SSH is available.
|
||||
6. Sync folders via `rsync` and run Vagrant provisioner on new domain.
|
||||
6. Sync folders via `rsync` and run Vagrant provisioner on new domain if
|
||||
setup in Vagrantfile.
|
||||
|
||||
## Networks
|
||||
|
||||
@@ -135,16 +136,13 @@ defined.
|
||||
|
||||
## Obtaining Domain IP Address
|
||||
|
||||
Libvirt doesn't provide a way to find out an IP address of running domain. We
|
||||
can get domains MAC address only. So to get an IP address, Libvirt provider is
|
||||
checking dnsmasq leases files in `/var/lib/libvirt/dnsmasq` directory. After
|
||||
IP address is known, it's stored into machines *data_dir* for later use, because
|
||||
lease information disappears after some time.
|
||||
|
||||
Possible problem raises when machines IP was changed since last write into
|
||||
*data_dir*. Libvirt provider first checks, if IP address matches with domains MAC
|
||||
address. If not, error is writen to user. As possible solution in this
|
||||
situation occurs `fping` or `nmap` command to ping whole 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.
|
||||
|
||||
## Synced Folders
|
||||
|
||||
@@ -185,7 +183,14 @@ $ bundle exec rake
|
||||
If those pass, you're ready to start developing the plugin. You can test
|
||||
the plugin without installing it into your Vagrant environment by just
|
||||
creating a `Vagrantfile` in the top level of this directory (it is gitignored)
|
||||
that uses it, and uses bundler to execute Vagrant:
|
||||
that uses it. Don't forget to add following line at the beginning of your
|
||||
`Vagrantfile` while in development mode:
|
||||
|
||||
```ruby
|
||||
Vagrant.require_plugin "vagrant-libvirt"
|
||||
```
|
||||
|
||||
Now you can use bundler to execute Vagrant:
|
||||
|
||||
```
|
||||
$ bundle exec vagrant up --provider=libvirt
|
||||
|
||||
@@ -48,9 +48,14 @@ module VagrantPlugins
|
||||
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.
|
||||
conn_attr[:libvirt_ip_command] = "cat /var/lib/libvirt/dnsmasq/*.leases"
|
||||
conn_attr[:libvirt_ip_command] << " | grep $mac | awk ' { print $3 }'"
|
||||
# with some MAC address. Get it from dnsmasq leases table - either
|
||||
# /var/lib/libvirt/dnsmasq/*.leases files, or
|
||||
# /var/lib/misc/dnsmasq.leases if available.
|
||||
ip_command = "LEASES='/var/lib/libvirt/dnsmasq/*.leases'; "
|
||||
ip_command << "[ -f /var/lib/misc/dnsmasq.leases ] && "
|
||||
ip_command << "LEASES='/var/lib/misc/dnsmasq.leases'; "
|
||||
ip_command << "cat $LEASES | grep $mac | awk '{ print $3 }'"
|
||||
conn_attr[:libvirt_ip_command] = ip_command
|
||||
|
||||
@logger.info("Connecting to Libvirt (#{uri}) ...")
|
||||
begin
|
||||
|
||||
@@ -18,7 +18,7 @@ module VagrantPlugins
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
def read_ssh_info(libvirt,machine)
|
||||
def read_ssh_info(libvirt, machine)
|
||||
return nil if machine.id.nil?
|
||||
|
||||
# Find the machine
|
||||
@@ -30,53 +30,24 @@ module VagrantPlugins
|
||||
return nil
|
||||
end
|
||||
|
||||
# IP address of machine is stored in $data_dir/ip file. Why? Commands
|
||||
# like ssh or provision need to get IP of VM long time after it was
|
||||
# started and gathered IP. Record in arp table is lost, and this is
|
||||
# the way how to store this info. Not an ideal solution, but libvirt
|
||||
# doesn't provide way how to get IP of some domain.
|
||||
ip_file = machine.data_dir + 'ip'
|
||||
raise Errors::NoIpAddressError if not File.exists?(ip_file)
|
||||
ip_address = File.open(ip_file, 'r') do |file|
|
||||
file.read
|
||||
end
|
||||
|
||||
# Check if stored IP address matches with MAC address of machine.
|
||||
# Command is executed either localy, or on remote libvirt hypervisor,
|
||||
# depends on establised fog libvirt connection.
|
||||
ip_match = false
|
||||
ip_command = "ping -c1 #{ip_address} > /dev/null && "
|
||||
ip_command << "arp -an | grep $mac | sed '"
|
||||
ip_command << 's/.*(\([0-9\.]*\)).*/\1/' + "'"
|
||||
options_hash = { :ip_command => ip_command }
|
||||
3.times do |x|
|
||||
break if ip_match
|
||||
domain.wait_for(1) {
|
||||
begin
|
||||
addresses(service, options_hash).each_pair do |type, ip|
|
||||
if ip[0] != nil
|
||||
ip_match = true
|
||||
break
|
||||
end
|
||||
end
|
||||
rescue Fog::Errors::Error
|
||||
# Sometimes, if pinging happen too quickly after after IP
|
||||
# assignment, machine is not responding yet. Give it a little
|
||||
# time..
|
||||
sleep 1
|
||||
end
|
||||
|
||||
break if ip_match
|
||||
}
|
||||
end
|
||||
raise Errors::IpAddressMismatchError if not ip_match
|
||||
# Get IP address from dnsmasq lease file.
|
||||
ip_address = nil
|
||||
domain.wait_for(2) {
|
||||
addresses.each_pair do |type, ip|
|
||||
ip_address = ip[0] if ip[0] != nil
|
||||
end
|
||||
ip_address != nil
|
||||
}
|
||||
raise Errors::NoIpAddressError if not ip_address
|
||||
|
||||
# Return the info
|
||||
# TODO: Some info should be configurable in Vagrantfile
|
||||
return {
|
||||
:host => ip_address,
|
||||
:port => 22,
|
||||
:username => 'root',
|
||||
:host => ip_address,
|
||||
:port => 22,
|
||||
:username => 'root',
|
||||
:forward_agent => true,
|
||||
:forward_x11 => true,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,7 +37,7 @@ module VagrantPlugins
|
||||
# Wait for domain to obtain an ip address
|
||||
domain.wait_for(2) {
|
||||
addresses.each_pair do |type, ip|
|
||||
env[:ip_address] = ip[0]
|
||||
env[:ip_address] = ip[0] if ip[0] != nil
|
||||
end
|
||||
env[:ip_address] != nil
|
||||
}
|
||||
@@ -46,14 +46,7 @@ module VagrantPlugins
|
||||
terminate(env) if env[:interrupted]
|
||||
@logger.info("Got IP address #{env[:ip_address]}")
|
||||
@logger.info("Time for getting IP: #{env[:metrics]["instance_ip_time"]}")
|
||||
|
||||
# Save newly assigned IP address to machines data_dir
|
||||
ip_file_path = env[:machine].data_dir + 'ip'
|
||||
@logger.info("Saving IP address to #{ip_file_path} file.")
|
||||
File.open(ip_file_path, 'w') do |file|
|
||||
file.write(env[:ip_address])
|
||||
end
|
||||
|
||||
|
||||
# Machine has ip address assigned, now wait till we are able to
|
||||
# connect via ssh.
|
||||
env[:metrics]["instance_ssh_time"] = Util::Timer.time do
|
||||
|
||||
@@ -90,10 +90,6 @@ module VagrantPlugins
|
||||
error_key(:no_ip_address_error)
|
||||
end
|
||||
|
||||
class IpAddressMismatchError < VagrantLibvirtError
|
||||
error_key(:ip_address_mismatch_error)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -101,10 +101,6 @@ en:
|
||||
Error while attaching new device to domain. %{error_message}
|
||||
no_ip_address_error: |-
|
||||
No IP address found.
|
||||
ip_address_mismatch_error: |-
|
||||
IP address mismatch. Possible reason is that domain IP address changed.
|
||||
You can run `vagrant destroy` and then `vagrant up` to rebuild your
|
||||
project.
|
||||
|
||||
states:
|
||||
short_paused: |-
|
||||
|
||||
Reference in New Issue
Block a user