mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
Merge branch 'qemu-session-support' of git://github.com/qazokm/vagrant-libvirt into qazokm-qemu-session-support
This commit is contained in:
@@ -8,6 +8,7 @@ module VagrantPlugins
|
||||
# image as new domain volume.
|
||||
class CreateDomainVolume
|
||||
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
||||
include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
|
||||
|
||||
def initialize(app, _env)
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::action::create_domain_volume')
|
||||
@@ -48,8 +49,8 @@ module VagrantPlugins
|
||||
xml.target do
|
||||
xml.format(type: 'qcow2')
|
||||
xml.permissions do
|
||||
xml.owner 0
|
||||
xml.group 0
|
||||
xml.owner storage_uid(env)
|
||||
xml.group storage_gid(env)
|
||||
xml.mode '0600'
|
||||
xml.label 'virt_image_t'
|
||||
end
|
||||
@@ -58,8 +59,8 @@ module VagrantPlugins
|
||||
xml.path(@backing_file)
|
||||
xml.format(type: 'qcow2')
|
||||
xml.permissions do
|
||||
xml.owner 0
|
||||
xml.group 0
|
||||
xml.owner storage_uid(env)
|
||||
xml.group storage_gid(env)
|
||||
xml.mode '0600'
|
||||
xml.label 'virt_image_t'
|
||||
end
|
||||
|
||||
@@ -27,6 +27,11 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if env[:machine].provider_config.qemu_use_session
|
||||
@app.call(env)
|
||||
return
|
||||
end
|
||||
|
||||
# only one vm at a time should try to set up networks
|
||||
# otherwise they'll have inconsitent views of current state
|
||||
# and conduct redundant operations that cause errors
|
||||
|
||||
@@ -13,6 +13,11 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if env[:machine].provider_config.qemu_use_session
|
||||
@app.call(env)
|
||||
return
|
||||
end
|
||||
|
||||
# If there were some networks created for this machine, in machines
|
||||
# data directory, created_networks file holds UUIDs of each network.
|
||||
created_networks_file = env[:machine].data_dir + 'created_networks'
|
||||
|
||||
@@ -4,6 +4,10 @@ module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
class HandleBoxImage
|
||||
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
||||
include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
|
||||
|
||||
|
||||
@@lock = Mutex.new
|
||||
|
||||
def initialize(app, _env)
|
||||
@@ -31,11 +35,12 @@ module VagrantPlugins
|
||||
config = env[:machine].provider_config
|
||||
box_image_file = env[:machine].box.directory.join('box.img').to_s
|
||||
env[:box_volume_name] = env[:machine].box.name.to_s.dup.gsub('/', '-VAGRANTSLASH-')
|
||||
env[:box_volume_name] << "_vagrant_box_image_#{begin
|
||||
env[:machine].box.version.to_s
|
||||
rescue
|
||||
''
|
||||
end}.img"
|
||||
env[:box_volume_name] << "_vagrant_box_image_#{
|
||||
begin
|
||||
env[:machine].box.version.to_s
|
||||
rescue
|
||||
''
|
||||
end}.img"
|
||||
|
||||
# Override box_virtual_size
|
||||
if config.machine_virtual_size
|
||||
@@ -44,7 +49,7 @@ module VagrantPlugins
|
||||
# is not supported and will be ignored
|
||||
env[:ui].warn I18n.t(
|
||||
'vagrant_libvirt.warnings.ignoring_virtual_size_too_small',
|
||||
requested: config.machine_virtual_size, minimum: box_virtual_size
|
||||
requested: config.machine_virtual_size, minimum: box_virtual_size
|
||||
)
|
||||
else
|
||||
env[:ui].info I18n.t('vagrant_libvirt.manual_resize_required')
|
||||
@@ -75,17 +80,41 @@ module VagrantPlugins
|
||||
message = "Creating volume #{env[:box_volume_name]}"
|
||||
message << " in storage pool #{config.storage_pool_name}."
|
||||
@logger.info(message)
|
||||
begin
|
||||
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",
|
||||
format_type: box_format,
|
||||
pool_name: config.storage_pool_name
|
||||
)
|
||||
rescue Fog::Errors::Error => e
|
||||
raise Errors::FogCreateVolumeError,
|
||||
error_message: e.message
|
||||
|
||||
if config.qemu_use_session
|
||||
begin
|
||||
@name = env[:box_volume_name]
|
||||
@allocation = "#{box_image_size / 1024 / 1024}M"
|
||||
@capacity = "#{box_virtual_size}G"
|
||||
@format_type = box_format ? box_format : 'raw'
|
||||
|
||||
@storage_volume_uid = storage_uid env
|
||||
@storage_volume_gid = storage_gid env
|
||||
|
||||
libvirt_client = env[:machine].provider.driver.connection.client
|
||||
libvirt_pool = libvirt_client.lookup_storage_pool_by_name(
|
||||
config.storage_pool_name
|
||||
)
|
||||
libvirt_volume = libvirt_pool.create_volume_xml(
|
||||
to_xml('default_storage_volume')
|
||||
)
|
||||
rescue => e
|
||||
raise Errors::CreatingVolumeError,
|
||||
error_message: e.message
|
||||
end
|
||||
else
|
||||
begin
|
||||
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",
|
||||
format_type: box_format,
|
||||
pool_name: config.storage_pool_name
|
||||
)
|
||||
rescue Fog::Errors::Error => e
|
||||
raise Errors::FogCreateVolumeError,
|
||||
error_message: e.message
|
||||
end
|
||||
end
|
||||
|
||||
# Upload box image to storage pool
|
||||
@@ -103,7 +132,11 @@ module VagrantPlugins
|
||||
# storage pool.
|
||||
if env[:interrupted] || !ret
|
||||
begin
|
||||
fog_volume.destroy
|
||||
if config.qemu_use_session
|
||||
libvirt_volume.delete
|
||||
else
|
||||
fog_volume.destroy
|
||||
end
|
||||
rescue
|
||||
nil
|
||||
end
|
||||
@@ -113,6 +146,19 @@ module VagrantPlugins
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
def split_size_unit(text)
|
||||
if text.kind_of? Integer
|
||||
# if text is an integer, match will fail
|
||||
size = text
|
||||
unit = 'G'
|
||||
else
|
||||
matcher = text.match(/(\d+)(.+)/)
|
||||
size = matcher[1]
|
||||
unit = matcher[2]
|
||||
end
|
||||
[size, unit]
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Fog libvirt currently doesn't support uploading images to storage
|
||||
|
||||
@@ -5,6 +5,8 @@ module VagrantPlugins
|
||||
module Action
|
||||
class HandleStoragePool
|
||||
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
||||
include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
|
||||
|
||||
|
||||
@@lock = Mutex.new
|
||||
|
||||
@@ -37,6 +39,9 @@ module VagrantPlugins
|
||||
# Fog libvirt currently doesn't support creating pools. Use
|
||||
# ruby-libvirt client directly.
|
||||
begin
|
||||
@storage_pool_path = storage_pool_path(env)
|
||||
@storage_pool_uid = storage_uid(env)
|
||||
@storage_pool_gid = storage_gid(env)
|
||||
libvirt_pool = env[:machine].provider.driver.connection.client.define_storage_pool_xml(
|
||||
to_xml('default_storage_pool')
|
||||
)
|
||||
|
||||
@@ -31,22 +31,39 @@ module VagrantPlugins
|
||||
# from arp table, either localy or remotely via ssh, if libvirt
|
||||
# connection was done via ssh.
|
||||
env[:ip_address] = nil
|
||||
env[:metrics]['instance_ip_time'] = Util::Timer.time do
|
||||
@logger.debug("Searching for IP for MAC address: #{domain.mac}")
|
||||
env[:ui].info(I18n.t('vagrant_libvirt.waiting_for_ip'))
|
||||
retryable(on: Fog::Errors::TimeoutError, tries: 300) do
|
||||
# If we're interrupted don't worry about waiting
|
||||
return terminate(env) if env[:interrupted]
|
||||
@logger.debug("Searching for IP for MAC address: #{domain.mac}")
|
||||
env[:ui].info(I18n.t('vagrant_libvirt.waiting_for_ip'))
|
||||
|
||||
# Wait for domain to obtain an ip address
|
||||
domain.wait_for(2) do
|
||||
addresses.each_pair do |_type, ip|
|
||||
env[:ip_address] = ip[0] unless ip[0].nil?
|
||||
if env[:machine].provider_config.qemu_use_session
|
||||
env[:metrics]['instance_ip_time'] = Util::Timer.time do
|
||||
retryable(on: Fog::Errors::TimeoutError, tries: 300) do
|
||||
# If we're interrupted don't worry about waiting
|
||||
return terminate(env) if env[:interrupted]
|
||||
|
||||
# Wait for domain to obtain an ip address
|
||||
domain.wait_for(2) do
|
||||
env[:ip_address] = env[:machine].provider.driver.get_ipaddress_system(domain.mac)
|
||||
!env[:ip_address].nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
env[:metrics]['instance_ip_time'] = Util::Timer.time do
|
||||
retryable(on: Fog::Errors::TimeoutError, tries: 300) do
|
||||
# If we're interrupted don't worry about waiting
|
||||
return terminate(env) if env[:interrupted]
|
||||
|
||||
# Wait for domain to obtain an ip address
|
||||
domain.wait_for(2) do
|
||||
addresses.each_pair do |_type, ip|
|
||||
env[:ip_address] = ip[0] unless ip[0].nil?
|
||||
end
|
||||
!env[:ip_address].nil?
|
||||
end
|
||||
!env[:ip_address].nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@logger.info("Got IP address #{env[:ip_address]}")
|
||||
@logger.info("Time for getting IP: #{env[:metrics]['instance_ip_time']}")
|
||||
|
||||
|
||||
@@ -40,11 +40,13 @@ module VagrantPlugins
|
||||
# Libvirt storage pool name, where box image and instance snapshots will
|
||||
# be stored.
|
||||
attr_accessor :storage_pool_name
|
||||
attr_accessor :storage_pool_path
|
||||
|
||||
# Turn on to prevent hostname conflicts
|
||||
attr_accessor :random_hostname
|
||||
|
||||
# Libvirt default network
|
||||
attr_accessor :management_network_device
|
||||
attr_accessor :management_network_name
|
||||
attr_accessor :management_network_address
|
||||
attr_accessor :management_network_mode
|
||||
@@ -54,6 +56,9 @@ module VagrantPlugins
|
||||
attr_accessor :management_network_pci_bus
|
||||
attr_accessor :management_network_pci_slot
|
||||
|
||||
# System connection information
|
||||
attr_accessor :system_uri
|
||||
|
||||
# Default host prefix (alternative to use project folder name)
|
||||
attr_accessor :default_prefix
|
||||
|
||||
@@ -149,6 +154,9 @@ module VagrantPlugins
|
||||
# Additional qemuargs arguments
|
||||
attr_accessor :qemu_args
|
||||
|
||||
# Use qemu session instead of system
|
||||
attr_accessor :qemu_use_session
|
||||
|
||||
def initialize
|
||||
@uri = UNSET_VALUE
|
||||
@driver = UNSET_VALUE
|
||||
@@ -159,6 +167,7 @@ module VagrantPlugins
|
||||
@id_ssh_key_file = UNSET_VALUE
|
||||
@storage_pool_name = UNSET_VALUE
|
||||
@random_hostname = UNSET_VALUE
|
||||
@management_network_device = UNSET_VALUE
|
||||
@management_network_name = UNSET_VALUE
|
||||
@management_network_address = UNSET_VALUE
|
||||
@management_network_mode = UNSET_VALUE
|
||||
@@ -168,6 +177,9 @@ module VagrantPlugins
|
||||
@management_network_pci_slot = UNSET_VALUE
|
||||
@management_network_pci_bus = UNSET_VALUE
|
||||
|
||||
# System connection information
|
||||
@system_uri = UNSET_VALUE
|
||||
|
||||
# Domain specific settings.
|
||||
@uuid = UNSET_VALUE
|
||||
@memory = UNSET_VALUE
|
||||
@@ -253,6 +265,7 @@ module VagrantPlugins
|
||||
@mgmt_attach = UNSET_VALUE
|
||||
|
||||
@qemu_args = []
|
||||
@qemu_use_session = UNSET_VALUE
|
||||
end
|
||||
|
||||
def boot(device)
|
||||
@@ -544,7 +557,9 @@ module VagrantPlugins
|
||||
# Setup connection uri.
|
||||
uri = @driver.dup
|
||||
virt_path = case uri
|
||||
when 'qemu', 'openvz', 'uml', 'phyp', 'parallels', 'kvm'
|
||||
when 'qemu', 'kvm'
|
||||
@qemu_use_session ? '/session' : '/system'
|
||||
when 'openvz', 'uml', 'phyp', 'parallels'
|
||||
'/system'
|
||||
when '@en', 'esx'
|
||||
'/'
|
||||
@@ -594,7 +609,9 @@ module VagrantPlugins
|
||||
@password = nil if @password == UNSET_VALUE
|
||||
@id_ssh_key_file = 'id_rsa' if @id_ssh_key_file == UNSET_VALUE
|
||||
@storage_pool_name = 'default' if @storage_pool_name == UNSET_VALUE
|
||||
@storage_pool_path = nil if @storage_pool_path == UNSET_VALUE
|
||||
@random_hostname = false if @random_hostname == UNSET_VALUE
|
||||
@management_network_device = 'virbr0' if @management_network_device == UNSET_VALUE
|
||||
@management_network_name = 'vagrant-libvirt' if @management_network_name == UNSET_VALUE
|
||||
@management_network_address = '192.168.121.0/24' if @management_network_address == UNSET_VALUE
|
||||
@management_network_mode = 'nat' if @management_network_mode == UNSET_VALUE
|
||||
@@ -603,6 +620,7 @@ module VagrantPlugins
|
||||
@management_network_autostart = false if @management_network_autostart == UNSET_VALUE
|
||||
@management_network_pci_bus = nil if @management_network_pci_bus == UNSET_VALUE
|
||||
@management_network_pci_slot = nil if @management_network_pci_slot == UNSET_VALUE
|
||||
@system_uri = 'qemu:///system' if @system_uri == UNSET_VALUE
|
||||
|
||||
# generate a URI if none is supplied
|
||||
@uri = _generate_uri if @uri == UNSET_VALUE
|
||||
@@ -709,6 +727,7 @@ module VagrantPlugins
|
||||
@mgmt_attach = true if @mgmt_attach == UNSET_VALUE
|
||||
|
||||
@qemu_args = [] if @qemu_args == UNSET_VALUE
|
||||
@qemu_use_session = false if @qemu_use_session == UNSET_VALUE
|
||||
end
|
||||
|
||||
def validate(machine)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'fog/libvirt'
|
||||
require 'libvirt'
|
||||
require 'log4r'
|
||||
|
||||
module VagrantPlugins
|
||||
@@ -10,6 +11,7 @@ module VagrantPlugins
|
||||
# settings as a key to allow per machine connection attributes
|
||||
# to be used.
|
||||
@@connection = nil
|
||||
@@system_connection = nil
|
||||
|
||||
def initialize(machine)
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::driver')
|
||||
@@ -47,6 +49,17 @@ module VagrantPlugins
|
||||
@@connection
|
||||
end
|
||||
|
||||
def system_connection
|
||||
# If already connected to libvirt, just use it and don't connect
|
||||
# again.
|
||||
return @@system_connection if @@system_connection
|
||||
|
||||
config = @machine.provider_config
|
||||
|
||||
@@system_connection = Libvirt::open_read_only(config.system_uri)
|
||||
@@system_connection
|
||||
end
|
||||
|
||||
def get_domain(mid)
|
||||
begin
|
||||
domain = connection.servers.get(mid)
|
||||
@@ -70,6 +83,9 @@ module VagrantPlugins
|
||||
def get_ipaddress(machine)
|
||||
# Find the machine
|
||||
domain = get_domain(machine.id)
|
||||
if @machine.provider_config.qemu_use_session
|
||||
return get_ipaddress_system domain.mac
|
||||
end
|
||||
|
||||
if domain.nil?
|
||||
# The machine can't be found
|
||||
@@ -99,6 +115,19 @@ module VagrantPlugins
|
||||
ip_address
|
||||
end
|
||||
|
||||
def get_ipaddress_system(mac)
|
||||
ip_address = nil
|
||||
|
||||
system_connection.list_all_networks.each do |net|
|
||||
leases = net.dhcp_leases(mac, 0)
|
||||
# Assume the lease expiring last is the current IP address
|
||||
ip_address = leases.sort_by { |lse| lse["expirytime"] }.last["ipaddr"] if !leases.empty?
|
||||
break if ip_address
|
||||
end
|
||||
|
||||
return ip_address
|
||||
end
|
||||
|
||||
def state(machine)
|
||||
# may be other error states with initial retreival we can't handle
|
||||
begin
|
||||
|
||||
@@ -29,6 +29,10 @@ module VagrantPlugins
|
||||
error_key(:creating_storage_pool_error)
|
||||
end
|
||||
|
||||
class CreatingVolumeError < VagrantLibvirtError
|
||||
error_key(:creating_volume_error)
|
||||
end
|
||||
|
||||
class ImageUploadError < VagrantLibvirtError
|
||||
error_key(:image_upload_error)
|
||||
end
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
<path>/var/lib/libvirt/images</path>
|
||||
<path><%= @storage_pool_path %></path>
|
||||
<permissions>
|
||||
<mode>0755</mode>
|
||||
<owner>-1</owner>
|
||||
<group>-1</group>
|
||||
<owner><%= @storage_pool_uid %></owner>
|
||||
<group><%= @storage_pool_gid %></group>
|
||||
</permissions>
|
||||
</target>
|
||||
</pool>
|
||||
|
||||
14
lib/vagrant-libvirt/templates/default_storage_volume.xml.erb
Normal file
14
lib/vagrant-libvirt/templates/default_storage_volume.xml.erb
Normal file
@@ -0,0 +1,14 @@
|
||||
<volume>
|
||||
<name><%= @name %></name>
|
||||
<allocation unit="<%= split_size_unit(@allocation)[1] %>"><%= split_size_unit(@allocation)[0] %></allocation>
|
||||
<capacity unit="<%= split_size_unit(@capacity)[1] %>"><%= split_size_unit(@capacity)[0] %></capacity>
|
||||
<target>
|
||||
<format type="<%= @format_type %>"/>
|
||||
<permissions>
|
||||
<owner><%= @storage_volume_uid %></owner>
|
||||
<group><%= @storage_volume_gid %></group>
|
||||
<mode>0744</mode>
|
||||
<label>virt_image_t</label>
|
||||
</permissions>
|
||||
</target>
|
||||
</volume>
|
||||
@@ -5,6 +5,7 @@ module VagrantPlugins
|
||||
autoload :Collection, 'vagrant-libvirt/util/collection'
|
||||
autoload :Timer, 'vagrant-libvirt/util/timer'
|
||||
autoload :NetworkUtil, 'vagrant-libvirt/util/network_util'
|
||||
autoload :StorageUtil, 'vagrant-libvirt/util/storage_util'
|
||||
autoload :ErrorCodes, 'vagrant-libvirt/util/error_codes'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,8 @@ module VagrantPlugins
|
||||
include Vagrant::Util::NetworkIP
|
||||
|
||||
def configured_networks(env, logger)
|
||||
qemu_use_session = env[:machine].provider_config.qemu_use_session
|
||||
management_network_device = env[:machine].provider_config.management_network_device
|
||||
management_network_name = env[:machine].provider_config.management_network_name
|
||||
management_network_address = env[:machine].provider_config.management_network_address
|
||||
management_network_mode = env[:machine].provider_config.management_network_mode
|
||||
@@ -33,18 +35,31 @@ module VagrantPlugins
|
||||
error_message: "#{management_network_address} does not include both an address and subnet mask"
|
||||
end
|
||||
|
||||
management_network_options = {
|
||||
iface_type: :private_network,
|
||||
network_name: management_network_name,
|
||||
ip: Regexp.last_match(1),
|
||||
netmask: Regexp.last_match(2),
|
||||
dhcp_enabled: true,
|
||||
forward_mode: management_network_mode,
|
||||
guest_ipv6: management_network_guest_ipv6,
|
||||
autostart: management_network_autostart,
|
||||
bus: management_network_pci_bus,
|
||||
slot: management_network_pci_slot
|
||||
}
|
||||
if qemu_use_session
|
||||
management_network_options = {
|
||||
iface_type: :public_network,
|
||||
dev: management_network_device,
|
||||
mode: 'bridge',
|
||||
type: 'bridge',
|
||||
bus: management_network_pci_bus,
|
||||
slot: management_network_pci_slot
|
||||
}
|
||||
else
|
||||
management_network_options = {
|
||||
iface_type: :private_network,
|
||||
network_name: management_network_name,
|
||||
ip: Regexp.last_match(1),
|
||||
netmask: Regexp.last_match(2),
|
||||
dhcp_enabled: true,
|
||||
forward_mode: management_network_mode,
|
||||
guest_ipv6: management_network_guest_ipv6,
|
||||
autostart: management_network_autostart,
|
||||
bus: management_network_pci_bus,
|
||||
slot: management_network_pci_slot
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
unless management_network_mac.nil?
|
||||
management_network_options[:mac] = management_network_mac
|
||||
|
||||
27
lib/vagrant-libvirt/util/storage_util.rb
Normal file
27
lib/vagrant-libvirt/util/storage_util.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Util
|
||||
module StorageUtil
|
||||
def storage_uid(env)
|
||||
env[:machine].provider_config.qemu_use_session ? Process.uid : 0
|
||||
end
|
||||
|
||||
def storage_gid(env)
|
||||
env[:machine].provider_config.qemu_use_session ? Process.gid : 0
|
||||
end
|
||||
|
||||
def storage_pool_path(env)
|
||||
if env[:machine].provider_config.storage_pool_path
|
||||
env[:machine].provider_config.storage_pool_path
|
||||
elsif env[:machine].provider_config.qemu_use_session
|
||||
File.expand_path('~/.local/share/libvirt/images')
|
||||
else
|
||||
'/var/lib/libvirt/images'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user