vagrant-libvirt 0.3.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +421 -50
- data/lib/vagrant-libvirt/action.rb +7 -1
- data/lib/vagrant-libvirt/action/clean_machine_folder.rb +30 -0
- data/lib/vagrant-libvirt/action/create_domain.rb +56 -18
- data/lib/vagrant-libvirt/action/create_domain_volume.rb +57 -55
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +0 -3
- data/lib/vagrant-libvirt/action/create_networks.rb +11 -4
- data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
- data/lib/vagrant-libvirt/action/forward_ports.rb +37 -38
- data/lib/vagrant-libvirt/action/halt_domain.rb +25 -9
- data/lib/vagrant-libvirt/action/handle_box_image.rb +163 -74
- data/lib/vagrant-libvirt/action/is_running.rb +1 -3
- data/lib/vagrant-libvirt/action/is_suspended.rb +4 -4
- data/lib/vagrant-libvirt/action/package_domain.rb +2 -1
- data/lib/vagrant-libvirt/action/set_boot_order.rb +6 -2
- data/lib/vagrant-libvirt/action/start_domain.rb +86 -29
- data/lib/vagrant-libvirt/action/wait_till_up.rb +8 -52
- data/lib/vagrant-libvirt/cap/{mount_p9.rb → mount_9p.rb} +2 -2
- data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +37 -0
- data/lib/vagrant-libvirt/cap/{synced_folder.rb → synced_folder_9p.rb} +4 -5
- data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +109 -0
- data/lib/vagrant-libvirt/config.rb +236 -43
- data/lib/vagrant-libvirt/driver.rb +49 -32
- data/lib/vagrant-libvirt/errors.rb +24 -1
- data/lib/vagrant-libvirt/plugin.rb +14 -5
- data/lib/vagrant-libvirt/provider.rb +2 -9
- data/lib/vagrant-libvirt/templates/domain.xml.erb +35 -10
- data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
- data/lib/vagrant-libvirt/util/network_util.rb +21 -3
- data/lib/vagrant-libvirt/version +1 -1
- data/lib/vagrant-libvirt/version.rb +57 -9
- data/locales/en.yml +12 -0
- data/spec/spec_helper.rb +37 -3
- data/spec/support/binding_proc.rb +24 -0
- data/spec/support/libvirt_context.rb +2 -0
- data/spec/support/matchers/have_file_content.rb +63 -0
- data/spec/support/sharedcontext.rb +4 -0
- data/spec/unit/action/clean_machine_folder_spec.rb +58 -0
- data/spec/unit/action/create_domain_spec.rb +121 -36
- data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +54 -0
- data/spec/unit/action/create_domain_spec/default_domain.xml +49 -0
- data/spec/unit/action/create_domain_spec/{default_storage_pool.xml → default_system_storage_pool.xml} +0 -0
- data/spec/unit/action/create_domain_spec/default_user_storage_pool.xml +17 -0
- data/spec/unit/action/create_domain_volume_spec.rb +102 -0
- data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +21 -0
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +21 -0
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +21 -0
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +21 -0
- data/spec/unit/action/destroy_domain_spec.rb +1 -1
- data/spec/unit/action/forward_ports_spec.rb +202 -0
- data/spec/unit/action/halt_domain_spec.rb +90 -0
- data/spec/unit/action/handle_box_image_spec.rb +363 -0
- data/spec/unit/action/start_domain_spec.rb +183 -1
- data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +50 -0
- data/spec/unit/action/start_domain_spec/default.xml +2 -2
- data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +48 -0
- data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +48 -0
- data/spec/unit/action/wait_till_up_spec.rb +22 -21
- data/spec/unit/config_spec.rb +395 -127
- data/spec/unit/templates/domain_all_settings.xml +14 -3
- data/spec/unit/templates/domain_custom_cpu_model.xml +2 -1
- data/spec/unit/templates/domain_defaults.xml +2 -1
- data/spec/unit/templates/domain_spec.rb +100 -3
- data/spec/unit/templates/tpm/version_1.2.xml +54 -0
- data/spec/unit/templates/tpm/version_2.0.xml +53 -0
- metadata +105 -19
@@ -21,7 +21,7 @@ module VagrantPlugins
|
|
21
21
|
env[:metrics] ||= {}
|
22
22
|
|
23
23
|
# Get domain object
|
24
|
-
domain = env[:machine].provider.driver.get_domain(env[:machine]
|
24
|
+
domain = env[:machine].provider.driver.get_domain(env[:machine])
|
25
25
|
if domain.nil?
|
26
26
|
raise Errors::NoDomainError,
|
27
27
|
error_message: "Domain #{env[:machine].id} not found"
|
@@ -34,63 +34,19 @@ module VagrantPlugins
|
|
34
34
|
@logger.debug("Searching for IP for MAC address: #{domain.mac}")
|
35
35
|
env[:ui].info(I18n.t('vagrant_libvirt.waiting_for_ip'))
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
return if env[:interrupted]
|
37
|
+
env[:metrics]['instance_ip_time'] = Util::Timer.time do
|
38
|
+
retryable(on: Fog::Errors::TimeoutError, tries: 300) do
|
39
|
+
# just return if interrupted and let the warden call recover
|
40
|
+
return if env[:interrupted]
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
env[:ip_address] = env[:machine].provider.driver.get_ipaddress_system(domain.mac)
|
46
|
-
!env[:ip_address].nil?
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
else
|
51
|
-
env[:metrics]['instance_ip_time'] = Util::Timer.time do
|
52
|
-
retryable(on: Fog::Errors::TimeoutError, tries: 300) do
|
53
|
-
# just return if interrupted and let the warden call recover
|
54
|
-
return if env[:interrupted]
|
55
|
-
|
56
|
-
# Wait for domain to obtain an ip address
|
57
|
-
domain.wait_for(2) do
|
58
|
-
addresses.each_pair do |_type, ip|
|
59
|
-
env[:ip_address] = ip[0] unless ip[0].nil?
|
60
|
-
end
|
61
|
-
!env[:ip_address].nil?
|
62
|
-
end
|
63
|
-
end
|
42
|
+
# Wait for domain to obtain an ip address
|
43
|
+
env[:ip_address] = env[:machine].provider.driver.get_domain_ipaddress(env[:machine], domain)
|
64
44
|
end
|
65
45
|
end
|
66
46
|
|
67
47
|
@logger.info("Got IP address #{env[:ip_address]}")
|
68
48
|
@logger.info("Time for getting IP: #{env[:metrics]['instance_ip_time']}")
|
69
49
|
|
70
|
-
# Machine has ip address assigned, now wait till we are able to
|
71
|
-
# connect via ssh.
|
72
|
-
env[:metrics]['instance_ssh_time'] = Util::Timer.time do
|
73
|
-
env[:ui].info(I18n.t('vagrant_libvirt.waiting_for_ssh'))
|
74
|
-
retryable(on: Fog::Errors::TimeoutError, tries: 60) do
|
75
|
-
# If we're interrupted don't worry about waiting
|
76
|
-
next if env[:interrupted]
|
77
|
-
|
78
|
-
# Wait till we are able to connect via ssh.
|
79
|
-
loop do
|
80
|
-
# If we're interrupted then just back out
|
81
|
-
break if env[:interrupted]
|
82
|
-
break if env[:machine].communicate.ready?
|
83
|
-
sleep 2
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
# just return if interrupted and let the warden call recover
|
88
|
-
return if env[:interrupted]
|
89
|
-
@logger.info("Time for SSH ready: #{env[:metrics]['instance_ssh_time']}")
|
90
|
-
|
91
|
-
# Booted and ready for use.
|
92
|
-
# env[:ui].info(I18n.t("vagrant_libvirt.ready"))
|
93
|
-
|
94
50
|
@app.call(env)
|
95
51
|
end
|
96
52
|
|
@@ -100,7 +56,7 @@ module VagrantPlugins
|
|
100
56
|
end
|
101
57
|
|
102
58
|
def terminate(env)
|
103
|
-
if env[:machine].
|
59
|
+
if env[:machine].state.id != :not_created
|
104
60
|
# If we're not supposed to destroy on error then just return
|
105
61
|
return unless env[:destroy_on_error]
|
106
62
|
|
@@ -4,10 +4,10 @@ require 'vagrant/util/retryable'
|
|
4
4
|
module VagrantPlugins
|
5
5
|
module ProviderLibvirt
|
6
6
|
module Cap
|
7
|
-
class
|
7
|
+
class Mount9P
|
8
8
|
extend Vagrant::Util::Retryable
|
9
9
|
|
10
|
-
def self.
|
10
|
+
def self.mount_9p_shared_folder(machine, folders)
|
11
11
|
folders.each do |_name, opts|
|
12
12
|
# Expand the guest path so we can handle things like "~/vagrant"
|
13
13
|
expanded_guest_path = machine.guest.capability(
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'vagrant/util/retryable'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ProviderLibvirt
|
6
|
+
module Cap
|
7
|
+
class MountVirtioFS
|
8
|
+
extend Vagrant::Util::Retryable
|
9
|
+
|
10
|
+
def self.mount_virtiofs_shared_folder(machine, folders)
|
11
|
+
folders.each do |_name, opts|
|
12
|
+
# Expand the guest path so we can handle things like "~/vagrant"
|
13
|
+
expanded_guest_path = machine.guest.capability(
|
14
|
+
:shell_expand_guest_path, opts[:guestpath]
|
15
|
+
)
|
16
|
+
|
17
|
+
# Do the actual creating and mounting
|
18
|
+
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
|
19
|
+
|
20
|
+
# Mount
|
21
|
+
mount_tag = Digest::MD5.new.update(opts[:hostpath]).to_s[0, 31]
|
22
|
+
|
23
|
+
mount_opts = "-o #{opts[:mount_opts]}" if opts[:mount_opts]
|
24
|
+
|
25
|
+
mount_command = "mount -t virtiofs #{mount_opts} '#{mount_tag}' #{expanded_guest_path}"
|
26
|
+
retryable(on: Vagrant::Errors::LinuxMountFailed,
|
27
|
+
tries: 5,
|
28
|
+
sleep: 3) do
|
29
|
+
machine.communicate.sudo(mount_command,
|
30
|
+
error_class: Vagrant::Errors::LinuxMountFailed)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -6,10 +6,9 @@ require 'digest/md5'
|
|
6
6
|
require 'vagrant/util/subprocess'
|
7
7
|
require 'vagrant/errors'
|
8
8
|
require 'vagrant-libvirt/errors'
|
9
|
-
# require_relative "helper"
|
10
9
|
|
11
10
|
module VagrantPlugins
|
12
|
-
module
|
11
|
+
module SyncedFolder9P
|
13
12
|
class SyncedFolder < Vagrant.plugin('2', :synced_folder)
|
14
13
|
include Vagrant::Util
|
15
14
|
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
@@ -69,10 +68,10 @@ module VagrantPlugins
|
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
72
|
-
#
|
71
|
+
# once up, mount folders
|
73
72
|
def enable(machine, folders, _opts)
|
74
73
|
# Go through each folder and mount
|
75
|
-
machine.ui.info('mounting
|
74
|
+
machine.ui.info('mounting 9p share in guest')
|
76
75
|
# Only mount folders that have a guest path specified.
|
77
76
|
mount_folders = {}
|
78
77
|
folders.each do |id, opts|
|
@@ -83,7 +82,7 @@ module VagrantPlugins
|
|
83
82
|
end
|
84
83
|
# Mount the actual folder
|
85
84
|
machine.guest.capability(
|
86
|
-
:
|
85
|
+
:mount_9p_shared_folder, mount_folders
|
87
86
|
)
|
88
87
|
end
|
89
88
|
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'digest/md5'
|
5
|
+
|
6
|
+
require 'vagrant/util/subprocess'
|
7
|
+
require 'vagrant/errors'
|
8
|
+
require 'vagrant-libvirt/errors'
|
9
|
+
|
10
|
+
module VagrantPlugins
|
11
|
+
module SyncedFolderVirtioFS
|
12
|
+
class SyncedFolder < Vagrant.plugin('2', :synced_folder)
|
13
|
+
include Vagrant::Util
|
14
|
+
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
super
|
18
|
+
@logger = Log4r::Logger.new('vagrant_libvirt::synced_folders::virtiofs')
|
19
|
+
end
|
20
|
+
|
21
|
+
def usable?(machine, _raise_error = false)
|
22
|
+
# bail now if not using Libvirt since checking version would throw error
|
23
|
+
return false unless machine.provider_name == :libvirt
|
24
|
+
|
25
|
+
# virtiofs support introduced since 6.2.0
|
26
|
+
# version number format is major * 1,000,000 + minor * 1,000 + release
|
27
|
+
libvirt_version = machine.provider.driver.connection.client.libversion
|
28
|
+
libvirt_version >= 6_002_000
|
29
|
+
end
|
30
|
+
|
31
|
+
def prepare(machine, folders, _opts)
|
32
|
+
raise Vagrant::Errors::Error('No Libvirt connection') if machine.provider.driver.connection.nil?
|
33
|
+
@conn = machine.provider.driver.connection.client
|
34
|
+
|
35
|
+
begin
|
36
|
+
# loop through folders
|
37
|
+
folders.each do |id, folder_opts|
|
38
|
+
folder_opts.merge!(target: id,
|
39
|
+
mount: true,
|
40
|
+
readonly: nil) { |_k, ov, _nv| ov }
|
41
|
+
|
42
|
+
mount_tag = Digest::MD5.new.update(folder_opts[:hostpath]).to_s[0, 31]
|
43
|
+
folder_opts[:mount_tag] = mount_tag
|
44
|
+
|
45
|
+
machine.ui.info "================\nMachine id: #{machine.id}\nShould be mounting folders\n #{id}, opts: #{folder_opts}"
|
46
|
+
|
47
|
+
#xml = to_xml('filesystem', folder_opts)
|
48
|
+
xml = Nokogiri::XML::Builder.new do |xml|
|
49
|
+
xml.filesystem(type: 'mount', accessmode: 'passthrough') do
|
50
|
+
xml.driver(type: 'virtiofs')
|
51
|
+
xml.source(dir: folder_opts[:hostpath])
|
52
|
+
xml.target(dir: mount_tag)
|
53
|
+
xml.readonly unless folder_opts[:readonly].nil?
|
54
|
+
end
|
55
|
+
end.to_xml(
|
56
|
+
save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION |
|
57
|
+
Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
|
58
|
+
Nokogiri::XML::Node::SaveOptions::FORMAT
|
59
|
+
)
|
60
|
+
# puts "<<<<< XML:\n #{xml}\n >>>>>"
|
61
|
+
@conn.lookup_domain_by_uuid(machine.id).attach_device(xml, 0)
|
62
|
+
end
|
63
|
+
rescue => e
|
64
|
+
machine.ui.error("could not attach device because: #{e}")
|
65
|
+
raise VagrantPlugins::ProviderLibvirt::Errors::AttachDeviceError,
|
66
|
+
error_message: e.message
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# once up, mount folders
|
71
|
+
def enable(machine, folders, _opts)
|
72
|
+
# Go through each folder and mount
|
73
|
+
machine.ui.info('mounting virtiofs share in guest')
|
74
|
+
# Only mount folders that have a guest path specified.
|
75
|
+
mount_folders = {}
|
76
|
+
folders.each do |id, opts|
|
77
|
+
next unless opts[:mount] && opts[:guestpath] && !opts[:guestpath].empty?
|
78
|
+
mount_folders[id] = opts.dup
|
79
|
+
end
|
80
|
+
# Mount the actual folder
|
81
|
+
machine.guest.capability(
|
82
|
+
:mount_virtiofs_shared_folder, mount_folders
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def cleanup(machine, _opts)
|
87
|
+
if machine.provider.driver.connection.nil?
|
88
|
+
raise Vagrant::Errors::Error('No Libvirt connection')
|
89
|
+
end
|
90
|
+
@conn = machine.provider.driver.connection.client
|
91
|
+
begin
|
92
|
+
if machine.id && machine.id != ''
|
93
|
+
dom = @conn.lookup_domain_by_uuid(machine.id)
|
94
|
+
Nokogiri::XML(dom.xml_desc).xpath(
|
95
|
+
'/domain/devices/filesystem'
|
96
|
+
).each do |xml|
|
97
|
+
dom.detach_device(xml.to_s)
|
98
|
+
machine.ui.info 'Cleaned up shared folders'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
rescue => e
|
102
|
+
machine.ui.error("could not detach device because: #{e}")
|
103
|
+
raise VagrantPlugins::ProviderLibvirt::Errors::DetachDeviceError,
|
104
|
+
error_message: e.message
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
1
3
|
require 'vagrant'
|
2
4
|
|
3
5
|
class Numeric
|
@@ -37,6 +39,11 @@ module VagrantPlugins
|
|
37
39
|
# ID SSH key file
|
38
40
|
attr_accessor :id_ssh_key_file
|
39
41
|
|
42
|
+
attr_accessor :proxy_command
|
43
|
+
|
44
|
+
# Forward port with id 'ssh'
|
45
|
+
attr_accessor :forward_ssh_port
|
46
|
+
|
40
47
|
# Libvirt storage pool name, where box image and instance snapshots will
|
41
48
|
# be stored.
|
42
49
|
attr_accessor :storage_pool_name
|
@@ -59,6 +66,7 @@ module VagrantPlugins
|
|
59
66
|
attr_accessor :management_network_pci_bus
|
60
67
|
attr_accessor :management_network_pci_slot
|
61
68
|
attr_accessor :management_network_domain
|
69
|
+
attr_accessor :management_network_mtu
|
62
70
|
|
63
71
|
# System connection information
|
64
72
|
attr_accessor :system_uri
|
@@ -84,6 +92,8 @@ module VagrantPlugins
|
|
84
92
|
attr_accessor :shares
|
85
93
|
attr_accessor :features
|
86
94
|
attr_accessor :features_hyperv
|
95
|
+
attr_accessor :clock_offset
|
96
|
+
attr_accessor :clock_timers
|
87
97
|
attr_accessor :numa_nodes
|
88
98
|
attr_accessor :loader
|
89
99
|
attr_accessor :nvram
|
@@ -93,9 +103,10 @@ module VagrantPlugins
|
|
93
103
|
attr_accessor :machine_virtual_size
|
94
104
|
attr_accessor :disk_bus
|
95
105
|
attr_accessor :disk_device
|
106
|
+
attr_accessor :disk_driver_opts
|
96
107
|
attr_accessor :nic_model_type
|
97
108
|
attr_accessor :nested
|
98
|
-
attr_accessor :volume_cache
|
109
|
+
attr_accessor :volume_cache # deprecated, kept for backwards compatibility; use disk_driver
|
99
110
|
attr_accessor :kernel
|
100
111
|
attr_accessor :cmd_line
|
101
112
|
attr_accessor :initrd
|
@@ -117,6 +128,13 @@ module VagrantPlugins
|
|
117
128
|
attr_accessor :tpm_model
|
118
129
|
attr_accessor :tpm_type
|
119
130
|
attr_accessor :tpm_path
|
131
|
+
attr_accessor :tpm_version
|
132
|
+
|
133
|
+
# Configure the memballoon
|
134
|
+
attr_accessor :memballoon_enabled
|
135
|
+
attr_accessor :memballoon_model
|
136
|
+
attr_accessor :memballoon_pci_bus
|
137
|
+
attr_accessor :memballoon_pci_slot
|
120
138
|
|
121
139
|
# Sets the max number of NICs that can be created
|
122
140
|
# Default set to 8. Don't change the default unless you know
|
@@ -177,10 +195,14 @@ module VagrantPlugins
|
|
177
195
|
@uri = UNSET_VALUE
|
178
196
|
@driver = UNSET_VALUE
|
179
197
|
@host = UNSET_VALUE
|
198
|
+
@port = UNSET_VALUE
|
180
199
|
@connect_via_ssh = UNSET_VALUE
|
181
200
|
@username = UNSET_VALUE
|
182
201
|
@password = UNSET_VALUE
|
183
202
|
@id_ssh_key_file = UNSET_VALUE
|
203
|
+
@socket = UNSET_VALUE
|
204
|
+
@proxy_command = UNSET_VALUE
|
205
|
+
@forward_ssh_port = UNSET_VALUE # forward port with id 'ssh'
|
184
206
|
@storage_pool_name = UNSET_VALUE
|
185
207
|
@snapshot_pool_name = UNSET_VALUE
|
186
208
|
@random_hostname = UNSET_VALUE
|
@@ -194,6 +216,7 @@ module VagrantPlugins
|
|
194
216
|
@management_network_pci_slot = UNSET_VALUE
|
195
217
|
@management_network_pci_bus = UNSET_VALUE
|
196
218
|
@management_network_domain = UNSET_VALUE
|
219
|
+
@management_network_mtu = UNSET_VALUE
|
197
220
|
|
198
221
|
# System connection information
|
199
222
|
@system_uri = UNSET_VALUE
|
@@ -215,6 +238,8 @@ module VagrantPlugins
|
|
215
238
|
@shares = UNSET_VALUE
|
216
239
|
@features = UNSET_VALUE
|
217
240
|
@features_hyperv = UNSET_VALUE
|
241
|
+
@clock_offset = UNSET_VALUE
|
242
|
+
@clock_timers = []
|
218
243
|
@numa_nodes = UNSET_VALUE
|
219
244
|
@loader = UNSET_VALUE
|
220
245
|
@nvram = UNSET_VALUE
|
@@ -223,6 +248,7 @@ module VagrantPlugins
|
|
223
248
|
@machine_virtual_size = UNSET_VALUE
|
224
249
|
@disk_bus = UNSET_VALUE
|
225
250
|
@disk_device = UNSET_VALUE
|
251
|
+
@disk_driver_opts = {}
|
226
252
|
@nic_model_type = UNSET_VALUE
|
227
253
|
@nested = UNSET_VALUE
|
228
254
|
@volume_cache = UNSET_VALUE
|
@@ -245,6 +271,12 @@ module VagrantPlugins
|
|
245
271
|
@tpm_model = UNSET_VALUE
|
246
272
|
@tpm_type = UNSET_VALUE
|
247
273
|
@tpm_path = UNSET_VALUE
|
274
|
+
@tpm_version = UNSET_VALUE
|
275
|
+
|
276
|
+
@memballoon_enabled = UNSET_VALUE
|
277
|
+
@memballoon_model = UNSET_VALUE
|
278
|
+
@memballoon_pci_bus = UNSET_VALUE
|
279
|
+
@memballoon_pci_slot = UNSET_VALUE
|
248
280
|
|
249
281
|
@nic_adapter_count = UNSET_VALUE
|
250
282
|
|
@@ -373,10 +405,39 @@ module VagrantPlugins
|
|
373
405
|
raise 'Feature name AND state must be specified'
|
374
406
|
end
|
375
407
|
|
408
|
+
if options[:name] == 'spinlocks' && options[:retries].nil?
|
409
|
+
raise 'Feature spinlocks requires retries parameter'
|
410
|
+
end
|
411
|
+
|
376
412
|
@features_hyperv = [] if @features_hyperv == UNSET_VALUE
|
377
413
|
|
378
|
-
|
379
|
-
|
414
|
+
if options[:name] == 'spinlocks'
|
415
|
+
@features_hyperv.push(name: options[:name],
|
416
|
+
state: options[:state],
|
417
|
+
retries: options[:retries])
|
418
|
+
else
|
419
|
+
@features_hyperv.push(name: options[:name],
|
420
|
+
state: options[:state])
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
def clock_timer(options = {})
|
425
|
+
if options[:name].nil?
|
426
|
+
raise 'Clock timer name must be specified'
|
427
|
+
end
|
428
|
+
|
429
|
+
options.each do |key, value|
|
430
|
+
case key
|
431
|
+
when :name, :track, :tickpolicy, :frequency, :mode, :present
|
432
|
+
if value.nil?
|
433
|
+
raise "Value of timer option #{key} is nil"
|
434
|
+
end
|
435
|
+
else
|
436
|
+
raise "Unknown clock timer option: #{key}"
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
@clock_timers.push(options.dup)
|
380
441
|
end
|
381
442
|
|
382
443
|
def cputopology(options = {})
|
@@ -551,6 +612,12 @@ module VagrantPlugins
|
|
551
612
|
@smartcard_dev[:source_service] = options[:source_service] if @smartcard_dev[:type] == 'tcp'
|
552
613
|
end
|
553
614
|
|
615
|
+
# Disk driver options for primary disk
|
616
|
+
def disk_driver(options = {})
|
617
|
+
supported_opts = [:cache, :io, :copy_on_read, :discard, :detect_zeroes]
|
618
|
+
@disk_driver_opts = options.select { |k,_| supported_opts.include? k }
|
619
|
+
end
|
620
|
+
|
554
621
|
# NOTE: this will run twice for each time it's needed- keep it idempotent
|
555
622
|
def storage(storage_type, options = {})
|
556
623
|
if storage_type == :file
|
@@ -574,11 +641,13 @@ module VagrantPlugins
|
|
574
641
|
# as will the address unit number (unit=0, unit=1, etc)
|
575
642
|
|
576
643
|
options = {
|
644
|
+
type: 'raw',
|
577
645
|
bus: 'ide',
|
578
646
|
path: nil
|
579
647
|
}.merge(options)
|
580
648
|
|
581
649
|
cdrom = {
|
650
|
+
type: options[:type],
|
582
651
|
dev: options[:dev],
|
583
652
|
bus: options[:bus],
|
584
653
|
path: options[:path]
|
@@ -605,6 +674,10 @@ module VagrantPlugins
|
|
605
674
|
allow_existing: options[:allow_existing],
|
606
675
|
shareable: options[:shareable],
|
607
676
|
serial: options[:serial],
|
677
|
+
io: options[:io],
|
678
|
+
copy_on_read: options[:copy_on_read],
|
679
|
+
discard: options[:discard],
|
680
|
+
detect_zeroes: options[:detect_zeroes],
|
608
681
|
pool: options[:pool], # overrides storage_pool setting for additional disks
|
609
682
|
wwn: options[:wwn],
|
610
683
|
}
|
@@ -624,15 +697,25 @@ module VagrantPlugins
|
|
624
697
|
@qemu_env.merge!(options)
|
625
698
|
end
|
626
699
|
|
700
|
+
def _default_uri
|
701
|
+
# Determine if any settings except driver provided explicitly, if not
|
702
|
+
# and the LIBVIRT_DEFAULT_URI var is set, use that.
|
703
|
+
#
|
704
|
+
# Skipping driver because that may be set on individual boxes rather
|
705
|
+
# than by the user.
|
706
|
+
if [
|
707
|
+
@connect_via_ssh, @host, @username, @password,
|
708
|
+
@id_ssh_key_file, @qemu_use_session, @socket,
|
709
|
+
].none?{ |v| v != UNSET_VALUE }
|
710
|
+
if ENV.fetch('LIBVIRT_DEFAULT_URI', '') != ""
|
711
|
+
@uri = ENV['LIBVIRT_DEFAULT_URI']
|
712
|
+
end
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
627
716
|
# code to generate URI from from either the LIBVIRT_URI environment
|
628
717
|
# variable or a config moved out of the connect action
|
629
718
|
def _generate_uri(qemu_use_session)
|
630
|
-
|
631
|
-
# If the LIBVIRT_DEFAULT_URI var is set, we'll use that
|
632
|
-
if ENV.fetch('LIBVIRT_DEFAULT_URI', '') != ""
|
633
|
-
return ENV['LIBVIRT_DEFAULT_URI']
|
634
|
-
end
|
635
|
-
|
636
719
|
# builds the Libvirt connection URI from the given driver config
|
637
720
|
# Setup connection uri.
|
638
721
|
uri = @driver.dup
|
@@ -652,30 +735,34 @@ module VagrantPlugins
|
|
652
735
|
uri = 'qemu' # use QEMU uri for KVM domain type
|
653
736
|
end
|
654
737
|
|
655
|
-
if
|
738
|
+
# turn on ssh if an ssh key file is explicitly provided
|
739
|
+
if @connect_via_ssh == UNSET_VALUE && @id_ssh_key_file && @id_ssh_key_file != UNSET_VALUE
|
740
|
+
@connect_via_ssh = true
|
741
|
+
end
|
742
|
+
|
743
|
+
params = {}
|
744
|
+
|
745
|
+
if @connect_via_ssh == true
|
746
|
+
finalize_id_ssh_key_file
|
747
|
+
|
656
748
|
uri << '+ssh://'
|
657
|
-
uri << @username + '@' if @username
|
749
|
+
uri << @username + '@' if @username && @username != UNSET_VALUE
|
658
750
|
|
659
|
-
uri << ( @host ? @host : 'localhost' )
|
751
|
+
uri << ( @host && @host != UNSET_VALUE ? @host : 'localhost' )
|
752
|
+
|
753
|
+
params['no_verify'] = '1'
|
754
|
+
params['keyfile'] = @id_ssh_key_file if @id_ssh_key_file
|
660
755
|
else
|
661
756
|
uri << '://'
|
662
|
-
uri << @host if @host
|
757
|
+
uri << @host if @host && @host != UNSET_VALUE
|
663
758
|
end
|
664
759
|
|
665
760
|
uri << virt_path
|
666
761
|
|
667
|
-
params = {'no_verify' => '1'}
|
668
|
-
|
669
|
-
if @id_ssh_key_file
|
670
|
-
# set ssh key for access to Libvirt host
|
671
|
-
# if no slash, prepend $HOME/.ssh/
|
672
|
-
@id_ssh_key_file.prepend("#{ENV['HOME']}/.ssh/") if @id_ssh_key_file !~ /\A\//
|
673
|
-
params['keyfile'] = @id_ssh_key_file
|
674
|
-
end
|
675
762
|
# set path to Libvirt socket
|
676
763
|
params['socket'] = @socket if @socket
|
677
764
|
|
678
|
-
uri << "?" + params.map{|pair| pair.join('=')}.join('&')
|
765
|
+
uri << "?" + params.map{|pair| pair.join('=')}.join('&') if !params.empty?
|
679
766
|
uri
|
680
767
|
end
|
681
768
|
|
@@ -688,12 +775,25 @@ module VagrantPlugins
|
|
688
775
|
end
|
689
776
|
|
690
777
|
def finalize!
|
778
|
+
_default_uri if @uri == UNSET_VALUE
|
779
|
+
|
780
|
+
# settings which _generate_uri
|
691
781
|
@driver = 'kvm' if @driver == UNSET_VALUE
|
692
|
-
@host = nil if @host == UNSET_VALUE
|
693
|
-
@connect_via_ssh = false if @connect_via_ssh == UNSET_VALUE
|
694
|
-
@username = nil if @username == UNSET_VALUE
|
695
782
|
@password = nil if @password == UNSET_VALUE
|
696
|
-
@
|
783
|
+
@socket = nil if @socket == UNSET_VALUE
|
784
|
+
|
785
|
+
# If uri isn't set then let's build one from various sources.
|
786
|
+
# Default to passing false for qemu_use_session if it's not set.
|
787
|
+
if @uri == UNSET_VALUE
|
788
|
+
@uri = _generate_uri(@qemu_use_session == UNSET_VALUE ? false : @qemu_use_session)
|
789
|
+
end
|
790
|
+
|
791
|
+
finalize_from_uri
|
792
|
+
finalize_proxy_command
|
793
|
+
|
794
|
+
# forward port with id 'ssh'
|
795
|
+
@forward_ssh_port = false if @forward_ssh_port == UNSET_VALUE
|
796
|
+
|
697
797
|
@storage_pool_name = 'default' if @storage_pool_name == UNSET_VALUE
|
698
798
|
@snapshot_pool_name = @storage_pool_name if @snapshot_pool_name == UNSET_VALUE
|
699
799
|
@storage_pool_path = nil if @storage_pool_path == UNSET_VALUE
|
@@ -708,24 +808,9 @@ module VagrantPlugins
|
|
708
808
|
@management_network_pci_bus = nil if @management_network_pci_bus == UNSET_VALUE
|
709
809
|
@management_network_pci_slot = nil if @management_network_pci_slot == UNSET_VALUE
|
710
810
|
@management_network_domain = nil if @management_network_domain == UNSET_VALUE
|
811
|
+
@management_network_mtu = nil if @management_network_mtu == UNSET_VALUE
|
711
812
|
@system_uri = 'qemu:///system' if @system_uri == UNSET_VALUE
|
712
813
|
|
713
|
-
# If uri isn't set then let's build one from various sources.
|
714
|
-
# Default to passing false for qemu_use_session if it's not set.
|
715
|
-
if @uri == UNSET_VALUE
|
716
|
-
@uri = _generate_uri(@qemu_use_session == UNSET_VALUE ? false : @qemu_use_session)
|
717
|
-
end
|
718
|
-
|
719
|
-
# Set qemu_use_session based on the URI if it wasn't set by the user
|
720
|
-
if @qemu_use_session == UNSET_VALUE
|
721
|
-
uri = _parse_uri(@uri)
|
722
|
-
if (uri.scheme.start_with? "qemu") && (uri.path.include? "session")
|
723
|
-
@qemu_use_session = true
|
724
|
-
else
|
725
|
-
@qemu_use_session = false
|
726
|
-
end
|
727
|
-
end
|
728
|
-
|
729
814
|
# Domain specific settings.
|
730
815
|
@title = '' if @title == UNSET_VALUE
|
731
816
|
@description = '' if @description == UNSET_VALUE
|
@@ -749,6 +834,8 @@ module VagrantPlugins
|
|
749
834
|
@shares = nil if @shares == UNSET_VALUE
|
750
835
|
@features = ['acpi','apic','pae'] if @features == UNSET_VALUE
|
751
836
|
@features_hyperv = [] if @features_hyperv == UNSET_VALUE
|
837
|
+
@clock_offset = 'utc' if @clock_offset == UNSET_VALUE
|
838
|
+
@clock_timers = [] if @clock_timers == UNSET_VALUE
|
752
839
|
@numa_nodes = @numa_nodes == UNSET_VALUE ? nil : _generate_numa
|
753
840
|
@loader = nil if @loader == UNSET_VALUE
|
754
841
|
@nvram = nil if @nvram == UNSET_VALUE
|
@@ -757,9 +844,10 @@ module VagrantPlugins
|
|
757
844
|
@machine_virtual_size = nil if @machine_virtual_size == UNSET_VALUE
|
758
845
|
@disk_bus = 'virtio' if @disk_bus == UNSET_VALUE
|
759
846
|
@disk_device = 'vda' if @disk_device == UNSET_VALUE
|
847
|
+
@disk_driver_opts = {} if @disk_driver_opts == UNSET_VALUE
|
760
848
|
@nic_model_type = nil if @nic_model_type == UNSET_VALUE
|
761
849
|
@nested = false if @nested == UNSET_VALUE
|
762
|
-
@volume_cache =
|
850
|
+
@volume_cache = nil if @volume_cache == UNSET_VALUE
|
763
851
|
@kernel = nil if @kernel == UNSET_VALUE
|
764
852
|
@cmd_line = '' if @cmd_line == UNSET_VALUE
|
765
853
|
@initrd = '' if @initrd == UNSET_VALUE
|
@@ -781,6 +869,11 @@ module VagrantPlugins
|
|
781
869
|
@tpm_model = 'tpm-tis' if @tpm_model == UNSET_VALUE
|
782
870
|
@tpm_type = 'passthrough' if @tpm_type == UNSET_VALUE
|
783
871
|
@tpm_path = nil if @tpm_path == UNSET_VALUE
|
872
|
+
@tpm_version = nil if @tpm_version == UNSET_VALUE
|
873
|
+
@memballoon_enabled = nil if @memballoon_enabled == UNSET_VALUE
|
874
|
+
@memballoon_model = 'virtio' if @memballoon_model == UNSET_VALUE
|
875
|
+
@memballoon_pci_bus = '0x00' if @memballoon_pci_bus == UNSET_VALUE
|
876
|
+
@memballoon_pci_slot = '0x0f' if @memballoon_pci_slot == UNSET_VALUE
|
784
877
|
@nic_adapter_count = 8 if @nic_adapter_count == UNSET_VALUE
|
785
878
|
@emulator_path = nil if @emulator_path == UNSET_VALUE
|
786
879
|
|
@@ -872,6 +965,14 @@ module VagrantPlugins
|
|
872
965
|
end
|
873
966
|
end
|
874
967
|
|
968
|
+
if !machine.provider_config.volume_cache.nil? and machine.provider_config.volume_cache != UNSET_VALUE
|
969
|
+
machine.ui.warn("Libvirt Provider: volume_cache is deprecated. Use disk_driver :cache => '#{machine.provider_config.volume_cache}' instead.")
|
970
|
+
|
971
|
+
if !machine.provider_config.disk_driver_opts.empty?
|
972
|
+
machine.ui.warn("Libvirt Provider: volume_cache has no effect when disk_driver is defined.")
|
973
|
+
end
|
974
|
+
end
|
975
|
+
|
875
976
|
{ 'Libvirt Provider' => errors }
|
876
977
|
end
|
877
978
|
|
@@ -885,11 +986,103 @@ module VagrantPlugins
|
|
885
986
|
c += other.cdroms
|
886
987
|
result.cdroms = c
|
887
988
|
|
989
|
+
result.disk_driver_opts = disk_driver_opts.merge(other.disk_driver_opts)
|
990
|
+
|
991
|
+
c = clock_timers.dup
|
992
|
+
c += other.clock_timers
|
993
|
+
result.clock_timers = c
|
994
|
+
|
888
995
|
c = qemu_env != UNSET_VALUE ? qemu_env.dup : {}
|
889
996
|
c.merge!(other.qemu_env) if other.qemu_env != UNSET_VALUE
|
890
997
|
result.qemu_env = c
|
891
998
|
end
|
892
999
|
end
|
1000
|
+
|
1001
|
+
private
|
1002
|
+
|
1003
|
+
def finalize_from_uri
|
1004
|
+
# Parse uri to extract individual components
|
1005
|
+
uri = _parse_uri(@uri)
|
1006
|
+
|
1007
|
+
# only set @connect_via_ssh if not explicitly to avoid overriding
|
1008
|
+
# and allow an error to occur if the @uri and @connect_via_ssh disagree
|
1009
|
+
@connect_via_ssh = uri.scheme.include? "ssh" if @connect_via_ssh == UNSET_VALUE
|
1010
|
+
|
1011
|
+
# Set qemu_use_session based on the URI if it wasn't set by the user
|
1012
|
+
if @qemu_use_session == UNSET_VALUE
|
1013
|
+
if (uri.scheme.start_with? "qemu") && (uri.path.include? "session")
|
1014
|
+
@qemu_use_session = true
|
1015
|
+
else
|
1016
|
+
@qemu_use_session = false
|
1017
|
+
end
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
# Extract host and username values from uri if provided, otherwise nil
|
1021
|
+
@host = uri.host
|
1022
|
+
@port = uri.port
|
1023
|
+
@username = uri.user
|
1024
|
+
if uri.query
|
1025
|
+
params = CGI.parse(uri.query)
|
1026
|
+
@id_ssh_key_file = params['keyfile'].first if params.has_key?('keyfile')
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
finalize_id_ssh_key_file
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
def resolve_ssh_key_file(key_file)
|
1033
|
+
# set ssh key for access to Libvirt host
|
1034
|
+
# if no slash, prepend $HOME/.ssh/
|
1035
|
+
key_file.prepend("#{ENV['HOME']}/.ssh/") if key_file && key_file !~ /\A\//
|
1036
|
+
|
1037
|
+
key_file
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
def finalize_id_ssh_key_file
|
1041
|
+
# resolve based on the following roles
|
1042
|
+
# 1) if @connect_via_ssh is set to true, and id_ssh_key_file not current set,
|
1043
|
+
# set default if the file exists
|
1044
|
+
# 2) if supplied the key name, attempt to expand based on user home
|
1045
|
+
# 3) otherwise set to nil
|
1046
|
+
|
1047
|
+
if @connect_via_ssh == true && @id_ssh_key_file == UNSET_VALUE
|
1048
|
+
# set default if using ssh while allowing a user using nil to disable this
|
1049
|
+
id_ssh_key_file = resolve_ssh_key_file('id_rsa')
|
1050
|
+
id_ssh_key_file = nil if !File.file?(id_ssh_key_file)
|
1051
|
+
elsif @id_ssh_key_file != UNSET_VALUE
|
1052
|
+
id_ssh_key_file = resolve_ssh_key_file(@id_ssh_key_file)
|
1053
|
+
else
|
1054
|
+
id_ssh_key_file = nil
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
@id_ssh_key_file = id_ssh_key_file
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
def finalize_proxy_command
|
1061
|
+
if @connect_via_ssh
|
1062
|
+
if @proxy_command == UNSET_VALUE
|
1063
|
+
proxy_command = "ssh '#{@host}' "
|
1064
|
+
proxy_command << "-p #{@port} " if @port
|
1065
|
+
proxy_command << "-l '#{@username}' " if @username
|
1066
|
+
proxy_command << "-i '#{@id_ssh_key_file}' " if @id_ssh_key_file
|
1067
|
+
proxy_command << '-W %h:%p'
|
1068
|
+
else
|
1069
|
+
inputs = { host: @host }
|
1070
|
+
inputs << { port: @port } if @port
|
1071
|
+
inputs[:username] = @username if @username
|
1072
|
+
inputs[:id_ssh_key_file] = @id_ssh_key_file if @id_ssh_key_file
|
1073
|
+
|
1074
|
+
proxy_command = @proxy_command
|
1075
|
+
# avoid needing to escape '%' symbols
|
1076
|
+
inputs.each do |key, value|
|
1077
|
+
proxy_command.gsub!("{#{key}}", value)
|
1078
|
+
end
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
@proxy_command = proxy_command
|
1082
|
+
else
|
1083
|
+
@proxy_command = nil
|
1084
|
+
end
|
1085
|
+
end
|
893
1086
|
end
|
894
1087
|
end
|
895
1088
|
end
|