mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-01-07 14:33:08 -06:00
- Changed way how to get IP address of new VM - checks
/var/lib/libvirt/dnsmasq/*.leases files. - IP address is saved in $data_dir/ip file for future. This IP is then checked if it match with VMs MAC address. - Added ssh, provision and resume subcommand
This commit is contained in:
parent
1069816a75
commit
99d649a2c3
6
Rakefile
6
Rakefile
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env rake
|
||||
|
||||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
#require 'bundler/gem_tasks'
|
||||
#require 'rubygems'
|
||||
#require 'bundler/setup'
|
||||
require 'bundler/gem_tasks'
|
||||
Bundler::GemHelper.install_tasks
|
||||
|
||||
|
@ -29,12 +29,12 @@ module VagrantPlugins
|
||||
b2.use CreateDomainVolume
|
||||
b2.use CreateDomain
|
||||
b2.use CreateNetworkInterfaces
|
||||
end
|
||||
|
||||
b.use TimedProvision
|
||||
b.use StartDomain
|
||||
b.use WaitTillUp
|
||||
b.use SyncFolders
|
||||
b2.use TimedProvision
|
||||
b2.use StartDomain
|
||||
b2.use WaitTillUp
|
||||
b2.use SyncFolders
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -55,6 +55,71 @@ module VagrantPlugins
|
||||
end
|
||||
end
|
||||
|
||||
# This action is called to SSH into the machine.
|
||||
def self.action_ssh
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
if !env[:result]
|
||||
b2.use MessageNotCreated
|
||||
next
|
||||
end
|
||||
|
||||
b2.use SSHExec
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This action is called when `vagrant provision` is called.
|
||||
def self.action_provision
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
if !env[:result]
|
||||
b2.use MessageNotCreated
|
||||
next
|
||||
end
|
||||
|
||||
b2.use Provision
|
||||
b2.use SyncFolders
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This is the action that is primarily responsible for suspending
|
||||
# the virtual machine.
|
||||
def self.action_suspend
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
if !env[:result]
|
||||
b2.use MessageNotCreated
|
||||
next
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use SuspendDomain
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This is the action that is primarily responsible for resuming
|
||||
# suspended machines.
|
||||
def self.action_resume
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
if !env[:result]
|
||||
b2.use MessageNotCreated
|
||||
next
|
||||
end
|
||||
|
||||
b2.use ConnectLibvirt
|
||||
b2.use ResumeDomain
|
||||
end
|
||||
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
|
||||
@ -76,18 +141,7 @@ module VagrantPlugins
|
||||
end
|
||||
end
|
||||
|
||||
# suspend
|
||||
# save vm to file
|
||||
def self.action_suspend
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use ConnectLibvirt
|
||||
b.use Suspend
|
||||
end
|
||||
end
|
||||
|
||||
action_root = Pathname.new(File.expand_path("../action", __FILE__))
|
||||
autoload :Suspend, action_root.join("suspend")
|
||||
autoload :ConnectLibvirt, action_root.join("connect_libvirt")
|
||||
autoload :IsCreated, action_root.join("is_created")
|
||||
autoload :MessageAlreadyCreated, action_root.join("message_already_created")
|
||||
@ -100,6 +154,8 @@ module VagrantPlugins
|
||||
autoload :CreateNetworkInterfaces, action_root.join("create_network_interfaces")
|
||||
autoload :DestroyDomain, action_root.join("destroy_domain")
|
||||
autoload :StartDomain, action_root.join("start_domain")
|
||||
autoload :SuspendDomain, action_root.join("suspend_domain")
|
||||
autoload :ResumeDomain, action_root.join("resume_domain")
|
||||
autoload :ReadState, action_root.join("read_state")
|
||||
autoload :ReadSSHInfo, action_root.join("read_ssh_info")
|
||||
autoload :TimedProvision, action_root.join("timed_provision")
|
||||
|
@ -48,11 +48,9 @@ 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 via arp table. This solution doesn't
|
||||
# require arpwatch to be installed.
|
||||
conn_attr[:libvirt_ip_command] = "arp -an | grep $mac | sed '"
|
||||
conn_attr[:libvirt_ip_command] << 's/.*(\([0-9\.]*\)).*/\1/'
|
||||
conn_attr[:libvirt_ip_command] << "'"
|
||||
# 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 }'"
|
||||
|
||||
@logger.info("Connecting to Libvirt (#{uri}) ...")
|
||||
begin
|
||||
|
@ -37,6 +37,7 @@ module VagrantPlugins
|
||||
env[:ui].info(" -- Cpus: #{@cpus}")
|
||||
env[:ui].info(" -- Memory: #{@memory_size/1024}M")
|
||||
env[:ui].info(" -- Base box: #{env[:machine].box.name}")
|
||||
env[:ui].info(" -- Storage pool: #{env[:machine].provider_config.storage_pool_name}")
|
||||
env[:ui].info(" -- Image: #{@domain_volume_path}")
|
||||
|
||||
# Create libvirt domain.
|
||||
|
@ -4,24 +4,26 @@ module VagrantPlugins
|
||||
module Libvirt
|
||||
module Action
|
||||
class DestroyDomain
|
||||
|
||||
def initialize(app, env)
|
||||
@logger = Log4r::Logger.new("vagrant_libvirt::action::destroy_domain")
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
|
||||
# Destroy the server and remove the tracking ID
|
||||
# Destroy the server, remove the tracking ID and file holding IP
|
||||
# address.
|
||||
env[:ui].info(I18n.t("vagrant_libvirt.destroy_domain"))
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain.destroy(:destroy_volumes => true)
|
||||
env[:machine].id = nil
|
||||
|
||||
# Remove file holding IP address
|
||||
ip_file_path = env[:machine].data_dir + 'ip'
|
||||
File.delete(ip_file_path) if File.exists?(ip_file_path)
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -18,23 +18,58 @@ 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
|
||||
server = libvirt.servers.get(machine.id)
|
||||
if server.nil?
|
||||
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 of machine
|
||||
ip_address = server.public_ip_address
|
||||
ip_address = server.private_ip_address if ip_address == nil
|
||||
return nil if ip_address == nil
|
||||
# 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
|
||||
|
||||
# Return the info
|
||||
# TODO: Some info should be configurable in Vagrantfile
|
||||
@ -43,8 +78,7 @@ module VagrantPlugins
|
||||
:port => 22,
|
||||
:username => 'root',
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
27
lib/vagrant-libvirt/action/resume_domain.rb
Normal file
27
lib/vagrant-libvirt/action/resume_domain.rb
Normal file
@ -0,0 +1,27 @@
|
||||
require 'log4r'
|
||||
|
||||
module VagrantPlugins
|
||||
module Libvirt
|
||||
module Action
|
||||
# Resume suspended domain.
|
||||
class ResumeDomain
|
||||
def initialize(app, env)
|
||||
@logger = Log4r::Logger.new("vagrant_libvirt::action::resume_domain")
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
env[:ui].info(I18n.t("vagrant_libvirt.resuming_domain"))
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
raise Errors::NoDomainError if domain == nil
|
||||
|
||||
domain.resume
|
||||
@logger.info("Machine #{env[:machine].id} is resumed.")
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -3,23 +3,26 @@ require 'log4r'
|
||||
module VagrantPlugins
|
||||
module Libvirt
|
||||
module Action
|
||||
|
||||
class Suspend
|
||||
# Suspend domain.
|
||||
class SuspendDomain
|
||||
def initialize(app, env)
|
||||
@logger = Log4r::Logger.new("vagrant_libvirt::action::create_domain")
|
||||
@logger = Log4r::Logger.new("vagrant_libvirt::action::suspend_domain")
|
||||
@app = app
|
||||
end
|
||||
|
||||
# make pause
|
||||
def call(env)
|
||||
vmid = env[:machine].id.to_s.chomp
|
||||
domain = env[:libvirt_compute].servers.get(vmid)
|
||||
env[:ui].info(I18n.t("vagrant_libvirt.suspending_domain"))
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
raise Errors::NoDomainError if domain == nil
|
||||
|
||||
domain.suspend
|
||||
@logger.info("Machine #{vmid} is suspended ")
|
||||
@logger.info("Machine #{env[:machine].id} is suspended ")
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
@ -47,6 +47,13 @@ module VagrantPlugins
|
||||
@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
|
||||
|
@ -85,6 +85,15 @@ module VagrantPlugins
|
||||
class AttachDeviceError < VagrantLibvirtError
|
||||
error_key(:attach_device_error)
|
||||
end
|
||||
|
||||
class NoIpAddressError < VagrantLibvirtError
|
||||
error_key(:no_ip_address_error)
|
||||
end
|
||||
|
||||
class IpAddressMismatchError < VagrantLibvirtError
|
||||
error_key(:ip_address_mismatch_error)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,13 +1,13 @@
|
||||
en:
|
||||
vagrant_libvirt:
|
||||
already_created: |-
|
||||
The machine is already created.
|
||||
The domain is already created.
|
||||
not_created: |-
|
||||
Machine is not created. Please run `vagrant up` first.
|
||||
Domain is not created. Please run `vagrant up` first.
|
||||
finding_volume: |-
|
||||
Checking if volume is available.
|
||||
creating_domain: |-
|
||||
Creating machine with the following settings...
|
||||
Creating domain with the following settings...
|
||||
uploading_volume: |-
|
||||
Uploading base box image as volume into libvirt storage...
|
||||
creating_domain_volume: |-
|
||||
@ -15,17 +15,21 @@ en:
|
||||
removing_domain_volume: |-
|
||||
Removing image (snapshot of base box volume).
|
||||
starting_domain: |-
|
||||
Starting machine.
|
||||
Starting domain.
|
||||
terminating: |-
|
||||
Removing machine...
|
||||
Removing domain...
|
||||
poweroff_domain: |-
|
||||
Poweroff machine.
|
||||
Poweroff domain.
|
||||
destroy_domain: |-
|
||||
Removing machine...
|
||||
Removing domain...
|
||||
resuming_domain: |-
|
||||
Resuming domain...
|
||||
suspending_domain: |-
|
||||
Suspending domain...
|
||||
waiting_for_ready: |-
|
||||
Waiting for machine to become "ready"...
|
||||
Waiting for domain to become "ready"...
|
||||
waiting_for_ip: |-
|
||||
Waiting for machine to get an IP address...
|
||||
Waiting for domain to get an IP address...
|
||||
waiting_for_ssh: |-
|
||||
Waiting for SSH to become available...
|
||||
booted: |-
|
||||
@ -89,6 +93,12 @@ en:
|
||||
No domain found. %{error_message}
|
||||
attach_device_error: |-
|
||||
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: |-
|
||||
|
Loading…
Reference in New Issue
Block a user