vagrant-libvirt 0.1.0 → 0.4.1
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 +321 -76
- data/lib/vagrant-libvirt/action.rb +1 -1
- data/lib/vagrant-libvirt/action/create_domain.rb +54 -14
- data/lib/vagrant-libvirt/action/create_domain_volume.rb +0 -2
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +1 -0
- data/lib/vagrant-libvirt/action/forward_ports.rb +4 -3
- data/lib/vagrant-libvirt/action/handle_box_image.rb +6 -3
- data/lib/vagrant-libvirt/action/package_domain.rb +10 -4
- data/lib/vagrant-libvirt/action/prune_nfs_exports.rb +4 -3
- data/lib/vagrant-libvirt/action/start_domain.rb +86 -29
- data/lib/vagrant-libvirt/action/wait_till_up.rb +7 -27
- data/lib/vagrant-libvirt/cap/public_address.rb +16 -0
- data/lib/vagrant-libvirt/config.rb +233 -32
- data/lib/vagrant-libvirt/driver.rb +49 -32
- data/lib/vagrant-libvirt/plugin.rb +6 -0
- data/lib/vagrant-libvirt/provider.rb +2 -9
- data/lib/vagrant-libvirt/templates/domain.xml.erb +34 -5
- data/lib/vagrant-libvirt/templates/public_interface.xml.erb +5 -1
- data/lib/vagrant-libvirt/util.rb +1 -0
- data/lib/vagrant-libvirt/util/erb_template.rb +6 -7
- data/lib/vagrant-libvirt/util/ui.rb +23 -0
- data/lib/vagrant-libvirt/version +1 -0
- data/lib/vagrant-libvirt/version.rb +72 -1
- data/spec/spec_helper.rb +28 -2
- data/spec/support/binding_proc.rb +24 -0
- data/spec/support/libvirt_context.rb +3 -1
- data/spec/support/sharedcontext.rb +7 -3
- data/spec/unit/action/create_domain_spec.rb +160 -0
- data/spec/unit/action/create_domain_spec/default_system_storage_pool.xml +17 -0
- data/spec/unit/action/create_domain_spec/default_user_storage_pool.xml +17 -0
- data/spec/unit/action/destroy_domain_spec.rb +2 -2
- data/spec/unit/action/set_name_of_domain_spec.rb +2 -2
- data/spec/unit/action/start_domain_spec.rb +231 -0
- data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +50 -0
- data/spec/unit/action/start_domain_spec/default.xml +48 -0
- 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 +32 -9
- data/spec/unit/config_spec.rb +438 -0
- data/spec/unit/provider_spec.rb +11 -0
- data/spec/unit/templates/domain_all_settings.xml +8 -3
- data/spec/unit/templates/domain_custom_cpu_model.xml +4 -1
- data/spec/unit/templates/domain_defaults.xml +4 -1
- data/spec/unit/templates/domain_spec.rb +82 -2
- data/spec/unit/templates/tpm/version_1.2.xml +54 -0
- data/spec/unit/templates/tpm/version_2.0.xml +53 -0
- metadata +62 -6
@@ -186,11 +186,11 @@ module VagrantPlugins
|
|
186
186
|
|
187
187
|
b2.use Call, DestroyConfirm do |env2, b3|
|
188
188
|
if env2[:result]
|
189
|
+
b3.use ProvisionerCleanup, :before
|
189
190
|
b3.use ClearForwardedPorts
|
190
191
|
b3.use PruneNFSExports
|
191
192
|
b3.use DestroyDomain
|
192
193
|
b3.use DestroyNetworks
|
193
|
-
b3.use ProvisionerCleanup
|
194
194
|
else
|
195
195
|
b3.use MessageWillNotDestroy
|
196
196
|
end
|
@@ -5,6 +5,7 @@ module VagrantPlugins
|
|
5
5
|
module Action
|
6
6
|
class CreateDomain
|
7
7
|
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
8
|
+
include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
|
8
9
|
|
9
10
|
def initialize(app, _env)
|
10
11
|
@logger = Log4r::Logger.new('vagrant_libvirt::action::create_domain')
|
@@ -31,6 +32,8 @@ module VagrantPlugins
|
|
31
32
|
|
32
33
|
# Gather some info about domain
|
33
34
|
@name = env[:domain_name]
|
35
|
+
@title = config.title
|
36
|
+
@description = config.description
|
34
37
|
@uuid = config.uuid
|
35
38
|
@cpus = config.cpus.to_i
|
36
39
|
@cpuset = config.cpuset
|
@@ -39,6 +42,8 @@ module VagrantPlugins
|
|
39
42
|
@nodeset = config.nodeset
|
40
43
|
@features = config.features
|
41
44
|
@features_hyperv = config.features_hyperv
|
45
|
+
@clock_offset = config.clock_offset
|
46
|
+
@clock_timers = config.clock_timers
|
42
47
|
@shares = config.shares
|
43
48
|
@cpu_mode = config.cpu_mode
|
44
49
|
@cpu_model = config.cpu_model
|
@@ -50,11 +55,12 @@ module VagrantPlugins
|
|
50
55
|
@machine_arch = config.machine_arch
|
51
56
|
@disk_bus = config.disk_bus
|
52
57
|
@disk_device = config.disk_device
|
58
|
+
@disk_driver_opts = config.disk_driver_opts
|
53
59
|
@nested = config.nested
|
54
60
|
@memory_size = config.memory.to_i * 1024
|
55
61
|
@memory_backing = config.memory_backing
|
56
62
|
@management_network_mac = config.management_network_mac
|
57
|
-
@domain_volume_cache = config.volume_cache
|
63
|
+
@domain_volume_cache = config.volume_cache || 'default'
|
58
64
|
@kernel = config.kernel
|
59
65
|
@cmd_line = config.cmd_line
|
60
66
|
@emulator_path = config.emulator_path
|
@@ -78,6 +84,7 @@ module VagrantPlugins
|
|
78
84
|
@tpm_model = config.tpm_model
|
79
85
|
@tpm_type = config.tpm_type
|
80
86
|
@tpm_path = config.tpm_path
|
87
|
+
@tpm_version = config.tpm_version
|
81
88
|
|
82
89
|
# Boot order
|
83
90
|
@boot_order = config.boot_order
|
@@ -145,15 +152,10 @@ module VagrantPlugins
|
|
145
152
|
# If we have a box, take the path from the domain volume and set our storage_prefix.
|
146
153
|
# If not, we dump the storage pool xml to get its defined path.
|
147
154
|
# the default storage prefix is typically: /var/lib/libvirt/images/
|
148
|
-
if
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
storage_pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name(@storage_pool_name)
|
153
|
-
raise Errors::NoStoragePool if storage_pool.nil?
|
154
|
-
xml = Nokogiri::XML(storage_pool.xml_desc)
|
155
|
-
storage_prefix = xml.xpath('/pool/target/path').inner_text.to_s + '/'
|
156
|
-
end
|
155
|
+
if env[:machine].config.vm.box
|
156
|
+
storage_prefix = File.dirname(@domain_volume_path) + '/' # steal
|
157
|
+
else
|
158
|
+
storage_prefix = get_disk_storage_prefix(env, @storage_pool_name)
|
157
159
|
end
|
158
160
|
|
159
161
|
@disks.each do |disk|
|
@@ -167,6 +169,16 @@ module VagrantPlugins
|
|
167
169
|
|
168
170
|
disk[:absolute_path] = storage_prefix + disk[:path]
|
169
171
|
|
172
|
+
if not disk[:pool].nil?
|
173
|
+
disk_pool_name = disk[:pool]
|
174
|
+
@logger.debug "Overriding pool name with: #{disk_pool_name}"
|
175
|
+
disk_storage_prefix = get_disk_storage_prefix(env, disk_pool_name)
|
176
|
+
disk[:absolute_path] = disk_storage_prefix + disk[:path]
|
177
|
+
@logger.debug "Overriding disk path with: #{disk[:absolute_path]}"
|
178
|
+
else
|
179
|
+
disk_pool_name = @storage_pool_name
|
180
|
+
end
|
181
|
+
|
170
182
|
# make the disk. equivalent to:
|
171
183
|
# qemu-img create -f qcow2 <path> 5g
|
172
184
|
begin
|
@@ -175,8 +187,10 @@ module VagrantPlugins
|
|
175
187
|
format_type: disk[:type],
|
176
188
|
path: disk[:absolute_path],
|
177
189
|
capacity: disk[:size],
|
190
|
+
owner: storage_uid(env),
|
191
|
+
group: storage_uid(env),
|
178
192
|
#:allocation => ?,
|
179
|
-
pool_name:
|
193
|
+
pool_name: disk_pool_name
|
180
194
|
)
|
181
195
|
rescue Libvirt::Error => e
|
182
196
|
# It is hard to believe that e contains just a string
|
@@ -186,7 +200,7 @@ module VagrantPlugins
|
|
186
200
|
if e.message == msg and disk[:allow_existing]
|
187
201
|
disk[:preexisting] = true
|
188
202
|
else
|
189
|
-
raise Errors::
|
203
|
+
raise Errors::FogCreateDomainVolumeError,
|
190
204
|
error_message: e.message
|
191
205
|
end
|
192
206
|
end
|
@@ -195,6 +209,8 @@ module VagrantPlugins
|
|
195
209
|
# Output the settings we're going to use to the user
|
196
210
|
env[:ui].info(I18n.t('vagrant_libvirt.creating_domain'))
|
197
211
|
env[:ui].info(" -- Name: #{@name}")
|
212
|
+
env[:ui].info(" -- Title: #{@title}") if @title != ''
|
213
|
+
env[:ui].info(" -- Description: #{@description}") if @description != ''
|
198
214
|
env[:ui].info(" -- Forced UUID: #{@uuid}") if @uuid != ''
|
199
215
|
env[:ui].info(" -- Domain type: #{@domain_type}")
|
200
216
|
env[:ui].info(" -- Cpus: #{@cpus}")
|
@@ -213,6 +229,10 @@ module VagrantPlugins
|
|
213
229
|
@features_hyperv.each do |feature|
|
214
230
|
env[:ui].info(" -- Feature (HyperV): name=#{feature[:name]}, state=#{feature[:state]}")
|
215
231
|
end
|
232
|
+
env[:ui].info(" -- Clock offset: #{@clock_offset}")
|
233
|
+
@clock_timers.each do |timer|
|
234
|
+
env[:ui].info(" -- Clock timer: #{timer.map { |k,v| "#{k}=#{v}"}.join(', ')}")
|
235
|
+
end
|
216
236
|
env[:ui].info(" -- Memory: #{@memory_size / 1024}M")
|
217
237
|
unless @nodeset.nil?
|
218
238
|
env[:ui].info(" -- Nodeset: #{@nodeset}")
|
@@ -231,7 +251,13 @@ module VagrantPlugins
|
|
231
251
|
end
|
232
252
|
env[:ui].info(" -- Storage pool: #{@storage_pool_name}")
|
233
253
|
env[:ui].info(" -- Image: #{@domain_volume_path} (#{env[:box_virtual_size]}G)")
|
234
|
-
|
254
|
+
|
255
|
+
if not @disk_driver_opts.empty?
|
256
|
+
env[:ui].info(" -- Disk driver opts: #{@disk_driver_opts.reject { |k,v| v.nil? }.map { |k,v| "#{k}='#{v}'"}.join(' ')}")
|
257
|
+
else
|
258
|
+
env[:ui].info(" -- Disk driver opts: cache='#{@domain_volume_cache}'")
|
259
|
+
end
|
260
|
+
|
235
261
|
env[:ui].info(" -- Kernel: #{@kernel}")
|
236
262
|
env[:ui].info(" -- Initrd: #{@initrd}")
|
237
263
|
env[:ui].info(" -- Graphics Type: #{@graphics_type}")
|
@@ -242,7 +268,13 @@ module VagrantPlugins
|
|
242
268
|
env[:ui].info(" -- Video VRAM: #{@video_vram}")
|
243
269
|
env[:ui].info(" -- Sound Type: #{@sound_type}")
|
244
270
|
env[:ui].info(" -- Keymap: #{@keymap}")
|
245
|
-
env[:ui].info(" -- TPM
|
271
|
+
env[:ui].info(" -- TPM Backend: #{@tpm_type}")
|
272
|
+
if @tpm_type == 'emulator'
|
273
|
+
env[:ui].info(" -- TPM Model: #{@tpm_model}")
|
274
|
+
env[:ui].info(" -- TPM Version: #{@tpm_version}")
|
275
|
+
else
|
276
|
+
env[:ui].info(" -- TPM Path: #{@tpm_path}")
|
277
|
+
end
|
246
278
|
|
247
279
|
@boot_order.each do |device|
|
248
280
|
env[:ui].info(" -- Boot device: #{device}")
|
@@ -362,6 +394,14 @@ module VagrantPlugins
|
|
362
394
|
|
363
395
|
@app.call(env)
|
364
396
|
end
|
397
|
+
|
398
|
+
private
|
399
|
+
def get_disk_storage_prefix(env, disk_pool_name)
|
400
|
+
disk_storage_pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name(disk_pool_name)
|
401
|
+
raise Errors::NoStoragePool if disk_storage_pool.nil?
|
402
|
+
xml = Nokogiri::XML(disk_storage_pool.xml_desc)
|
403
|
+
disk_storage_prefix = xml.xpath('/pool/target/path').inner_text.to_s + '/'
|
404
|
+
end
|
365
405
|
end
|
366
406
|
end
|
367
407
|
end
|
@@ -51,7 +51,6 @@ module VagrantPlugins
|
|
51
51
|
xml.permissions do
|
52
52
|
xml.owner storage_uid(env)
|
53
53
|
xml.group storage_gid(env)
|
54
|
-
xml.mode '0600'
|
55
54
|
xml.label 'virt_image_t'
|
56
55
|
end
|
57
56
|
end
|
@@ -61,7 +60,6 @@ module VagrantPlugins
|
|
61
60
|
xml.permissions do
|
62
61
|
xml.owner storage_uid(env)
|
63
62
|
xml.group storage_gid(env)
|
64
|
-
xml.mode '0600'
|
65
63
|
xml.label 'virt_image_t'
|
66
64
|
end
|
67
65
|
end
|
@@ -95,6 +95,7 @@ module VagrantPlugins
|
|
95
95
|
template_name = 'public_interface'
|
96
96
|
@logger.info("Setting up public interface using device #{@device} in mode #{@mode}")
|
97
97
|
@ovs = iface_configuration.fetch(:ovs, false)
|
98
|
+
@ovs_interfaceid = iface_configuration.fetch(:ovs_interfaceid, false)
|
98
99
|
@trust_guest_rx_filters = iface_configuration.fetch(:trust_guest_rx_filters, false)
|
99
100
|
# configuration for udp or tcp tunnel interfaces (p2p conn btwn guest OSes)
|
100
101
|
elsif iface_configuration.fetch(:tunnel_type, nil)
|
@@ -98,6 +98,7 @@ module VagrantPlugins
|
|
98
98
|
Port=#{ssh_info[:port]}
|
99
99
|
UserKnownHostsFile=/dev/null
|
100
100
|
ExitOnForwardFailure=yes
|
101
|
+
ControlMaster=no
|
101
102
|
StrictHostKeyChecking=no
|
102
103
|
PasswordAuthentication=no
|
103
104
|
ForwardX11=#{ssh_info[:forward_x11] ? 'yes' : 'no'}
|
@@ -106,10 +107,10 @@ module VagrantPlugins
|
|
106
107
|
"IdentityFile='\"#{pk}\"'"
|
107
108
|
end).map { |s| s.prepend('-o ') }.join(' ')
|
108
109
|
|
109
|
-
options += " -o ProxyCommand=\"#{ssh_info[:proxy_command]}\"" if machine.provider_config.
|
110
|
+
options += " -o ProxyCommand=\"#{ssh_info[:proxy_command]}\"" if machine.provider_config.proxy_command
|
110
111
|
|
111
112
|
# TODO: instead of this, try and lock and get the stdin from spawn...
|
112
|
-
ssh_cmd = '
|
113
|
+
ssh_cmd = ''
|
113
114
|
if host_port <= 1024
|
114
115
|
@@lock.synchronize do
|
115
116
|
# TODO: add i18n
|
@@ -127,7 +128,7 @@ module VagrantPlugins
|
|
127
128
|
log_file = ssh_forward_log_file(host_ip, host_port,
|
128
129
|
guest_ip, guest_port)
|
129
130
|
@logger.info "Logging to #{log_file}"
|
130
|
-
spawn(ssh_cmd, [:out, :err] => [log_file, 'w'])
|
131
|
+
spawn(ssh_cmd, [:out, :err] => [log_file, 'w'], :pgroup => true)
|
131
132
|
end
|
132
133
|
|
133
134
|
def ssh_forward_log_file(host_ip, host_port, guest_ip, guest_port)
|
@@ -5,6 +5,7 @@ module VagrantPlugins
|
|
5
5
|
module Action
|
6
6
|
class HandleBoxImage
|
7
7
|
include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
|
8
|
+
include VagrantPlugins::ProviderLibvirt::Util::Ui
|
8
9
|
|
9
10
|
|
10
11
|
@@lock = Mutex.new
|
@@ -102,13 +103,15 @@ module VagrantPlugins
|
|
102
103
|
# Upload box image to storage pool
|
103
104
|
ret = upload_image(box_image_file, config.storage_pool_name,
|
104
105
|
env[:box_volume_name], env) do |progress|
|
105
|
-
env[:ui]
|
106
|
-
|
106
|
+
rewriting(env[:ui]) do |ui|
|
107
|
+
ui.clear_line
|
108
|
+
ui.report_progress(progress, box_image_size, false)
|
109
|
+
end
|
107
110
|
end
|
108
111
|
|
109
112
|
# Clear the line one last time since the progress meter doesn't
|
110
113
|
# disappear immediately.
|
111
|
-
env[:ui].clear_line
|
114
|
+
rewriting(env[:ui]) {|ui| ui.clear_line}
|
112
115
|
|
113
116
|
# If upload failed or was interrupted, remove created volume from
|
114
117
|
# storage pool.
|
@@ -6,6 +6,9 @@ module VagrantPlugins
|
|
6
6
|
module Action
|
7
7
|
# Action for create new box for Libvirt provider
|
8
8
|
class PackageDomain
|
9
|
+
include VagrantPlugins::ProviderLibvirt::Util::Ui
|
10
|
+
|
11
|
+
|
9
12
|
def initialize(app, env)
|
10
13
|
@logger = Log4r::Logger.new('vagrant_libvirt::action::package_domain')
|
11
14
|
@app = app
|
@@ -31,12 +34,14 @@ module VagrantPlugins
|
|
31
34
|
env[:ui].info("Downloading #{root_disk.name} to #{@tmp_img}")
|
32
35
|
ret = download_image(@tmp_img, env[:machine].provider_config.storage_pool_name,
|
33
36
|
root_disk.name, env) do |progress,image_size|
|
34
|
-
env[:ui]
|
35
|
-
|
37
|
+
rewriting(env[:ui]) do |ui|
|
38
|
+
ui.clear_line
|
39
|
+
ui.report_progress(progress, image_size, false)
|
40
|
+
end
|
36
41
|
end
|
37
42
|
# Clear the line one last time since the progress meter doesn't
|
38
43
|
# disappear immediately.
|
39
|
-
env[:ui].clear_line
|
44
|
+
rewriting(env[:ui]) {|ui| ui.clear_line}
|
40
45
|
backing = `qemu-img info "#{@tmp_img}" | grep 'backing file:' | cut -d ':' -f2`.chomp
|
41
46
|
if backing
|
42
47
|
env[:ui].info('Image has backing image, copying image and rebasing ...')
|
@@ -45,8 +50,9 @@ module VagrantPlugins
|
|
45
50
|
# remove hw association with interface
|
46
51
|
# working for centos with lvs default disks
|
47
52
|
options = ENV.fetch('VAGRANT_LIBVIRT_VIRT_SYSPREP_OPTIONS', '')
|
48
|
-
operations = ENV.fetch('VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS', 'defaults,-ssh-userdir')
|
53
|
+
operations = ENV.fetch('VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS', 'defaults,-ssh-userdir,-customize')
|
49
54
|
`virt-sysprep --no-logfile --operations #{operations} -a #{@tmp_img} #{options}`
|
55
|
+
`virt-sparsify --in-place #{@tmp_img}`
|
50
56
|
# add any user provided file
|
51
57
|
extra = ''
|
52
58
|
@tmp_include = @tmp_dir + '/_include'
|
@@ -8,15 +8,16 @@ module VagrantPlugins
|
|
8
8
|
include VagrantPlugins::ProviderLibvirt::Util::Nfs
|
9
9
|
|
10
10
|
def initialize(app, _env)
|
11
|
+
@logger = Log4r::Logger.new('vagrant_libvirt::action::prune_nfs_exports')
|
11
12
|
@app = app
|
12
13
|
end
|
13
14
|
|
14
15
|
def call(env)
|
15
|
-
|
16
|
+
@machine = env[:machine]
|
16
17
|
|
17
|
-
|
18
|
+
if using_nfs?
|
18
19
|
@logger.info('Using NFS, prunning NFS settings from host')
|
19
|
-
|
20
|
+
if env[:host]
|
20
21
|
uuid = env[:machine].id
|
21
22
|
# get all uuids
|
22
23
|
uuids = env[:machine].provider.driver.connection.servers.all.map(&:id)
|
@@ -37,12 +37,16 @@ module VagrantPlugins
|
|
37
37
|
xml_descr = REXML::Document.new descr
|
38
38
|
descr_changed = false
|
39
39
|
|
40
|
+
# For outputting XML for comparison
|
41
|
+
formatter = REXML::Formatters::Pretty.new
|
42
|
+
|
40
43
|
# additional disk bus
|
41
44
|
config.disks.each do |disk|
|
42
45
|
device = disk[:device]
|
43
46
|
bus = disk[:bus]
|
44
47
|
REXML::XPath.each(xml_descr, '/domain/devices/disk[@device="disk"]/target[@dev="' + device + '"]') do |disk_target|
|
45
48
|
next unless disk_target.attributes['bus'] != bus
|
49
|
+
@logger.debug "disk #{device} bus updated from '#{disk_target.attributes['bus']}' to '#{bus}'"
|
46
50
|
descr_changed = true
|
47
51
|
disk_target.attributes['bus'] = bus
|
48
52
|
disk_target.parent.delete_element("#{disk_target.parent.xpath}/address")
|
@@ -52,6 +56,7 @@ module VagrantPlugins
|
|
52
56
|
# disk_bus
|
53
57
|
REXML::XPath.each(xml_descr, '/domain/devices/disk[@device="disk"]/target[@dev="vda"]') do |disk_target|
|
54
58
|
next unless disk_target.attributes['bus'] != config.disk_bus
|
59
|
+
@logger.debug "domain disk bus updated from '#{disk_target.attributes['bus']}' to '#{bus}'"
|
55
60
|
descr_changed = true
|
56
61
|
disk_target.attributes['bus'] = config.disk_bus
|
57
62
|
disk_target.parent.delete_element("#{disk_target.parent.xpath}/address")
|
@@ -61,6 +66,7 @@ module VagrantPlugins
|
|
61
66
|
unless config.nic_model_type.nil?
|
62
67
|
REXML::XPath.each(xml_descr, '/domain/devices/interface/model') do |iface_model|
|
63
68
|
if iface_model.attributes['type'] != config.nic_model_type
|
69
|
+
@logger.debug "network type updated from '#{iface_model.attributes['type']}' to '#{config.nic_model_type}'"
|
64
70
|
descr_changed = true
|
65
71
|
iface_model.attributes['type'] = config.nic_model_type
|
66
72
|
end
|
@@ -68,7 +74,9 @@ module VagrantPlugins
|
|
68
74
|
end
|
69
75
|
|
70
76
|
# vCpu count
|
71
|
-
|
77
|
+
vcpus_count = libvirt_domain.num_vcpus(0)
|
78
|
+
if config.cpus.to_i != vcpus_count
|
79
|
+
@logger.debug "cpu count updated from '#{vcpus_count}' to '#{config.cpus}'"
|
72
80
|
descr_changed = true
|
73
81
|
REXML::XPath.first(xml_descr, '/domain/vcpu').text = config.cpus
|
74
82
|
end
|
@@ -76,11 +84,13 @@ module VagrantPlugins
|
|
76
84
|
# cpu_mode
|
77
85
|
cpu = REXML::XPath.first(xml_descr, '/domain/cpu')
|
78
86
|
if cpu.nil?
|
87
|
+
@logger.debug "cpu_mode updated from not set to '#{config.cpu_mode}'"
|
79
88
|
descr_changed = true
|
80
89
|
cpu = REXML::Element.new('cpu', REXML::XPath.first(xml_descr, '/domain'))
|
81
90
|
cpu.attributes['mode'] = config.cpu_mode
|
82
91
|
else
|
83
92
|
if cpu.attributes['mode'] != config.cpu_mode
|
93
|
+
@logger.debug "cpu_mode updated from '#{cpu.attributes['mode']}' to '#{config.cpu_mode}'"
|
84
94
|
descr_changed = true
|
85
95
|
cpu.attributes['mode'] = config.cpu_mode
|
86
96
|
end
|
@@ -89,16 +99,19 @@ module VagrantPlugins
|
|
89
99
|
if config.cpu_mode != 'host-passthrough'
|
90
100
|
cpu_model = REXML::XPath.first(xml_descr, '/domain/cpu/model')
|
91
101
|
if cpu_model.nil?
|
102
|
+
@logger.debug "cpu_model updated from not set to '#{config.cpu_model}'"
|
92
103
|
descr_changed = true
|
93
104
|
cpu_model = REXML::Element.new('model', REXML::XPath.first(xml_descr, '/domain/cpu'))
|
94
105
|
cpu_model.attributes['fallback'] = 'allow'
|
95
106
|
cpu_model.text = config.cpu_model
|
96
107
|
else
|
97
|
-
if cpu_model.text != config.cpu_model
|
108
|
+
if (cpu_model.text or '').strip != config.cpu_model.strip
|
109
|
+
@logger.debug "cpu_model text updated from #{cpu_model.text} to '#{config.cpu_model}'"
|
98
110
|
descr_changed = true
|
99
111
|
cpu_model.text = config.cpu_model
|
100
112
|
end
|
101
113
|
if cpu_model.attributes['fallback'] != config.cpu_fallback
|
114
|
+
@logger.debug "cpu_model fallback attribute updated from #{cpu_model.attributes['fallback']} to '#{config.cpu_fallback}'"
|
102
115
|
descr_changed = true
|
103
116
|
cpu_model.attributes['fallback'] = config.cpu_fallback
|
104
117
|
end
|
@@ -107,12 +120,14 @@ module VagrantPlugins
|
|
107
120
|
svm_feature = REXML::XPath.first(xml_descr, '/domain/cpu/feature[@name="svm"]')
|
108
121
|
if config.nested
|
109
122
|
if vmx_feature.nil?
|
123
|
+
@logger.debug "nested mode enabled from unset by setting cpu vmx feature"
|
110
124
|
descr_changed = true
|
111
125
|
vmx_feature = REXML::Element.new('feature', REXML::XPath.first(xml_descr, '/domain/cpu'))
|
112
126
|
vmx_feature.attributes['policy'] = 'optional'
|
113
127
|
vmx_feature.attributes['name'] = 'vmx'
|
114
128
|
end
|
115
129
|
if svm_feature.nil?
|
130
|
+
@logger.debug "nested mode enabled from unset by setting cpu svm feature"
|
116
131
|
descr_changed = true
|
117
132
|
svm_feature = REXML::Element.new('feature', REXML::XPath.first(xml_descr, '/domain/cpu'))
|
118
133
|
svm_feature.attributes['policy'] = 'optional'
|
@@ -120,16 +135,19 @@ module VagrantPlugins
|
|
120
135
|
end
|
121
136
|
else
|
122
137
|
unless vmx_feature.nil?
|
138
|
+
@logger.debug "nested mode disabled for cpu by removing vmx feature"
|
123
139
|
descr_changed = true
|
124
140
|
cpu.delete_element(vmx_feature)
|
125
141
|
end
|
126
142
|
unless svm_feature.nil?
|
143
|
+
@logger.debug "nested mode disabled for cpu by removing svm feature"
|
127
144
|
descr_changed = true
|
128
145
|
cpu.delete_element(svm_feature)
|
129
146
|
end
|
130
147
|
end
|
131
148
|
elsif config.numa_nodes == nil
|
132
149
|
unless cpu.elements.to_a.empty?
|
150
|
+
@logger.debug "switching cpu_mode to host-passthrough and removing emulated cpu features"
|
133
151
|
descr_changed = true
|
134
152
|
cpu.elements.each do |elem|
|
135
153
|
cpu.delete_element(elem)
|
@@ -137,6 +155,34 @@ module VagrantPlugins
|
|
137
155
|
end
|
138
156
|
end
|
139
157
|
|
158
|
+
# Clock
|
159
|
+
clock = REXML::XPath.first(xml_descr, '/domain/clock')
|
160
|
+
if clock.attributes['offset'] != config.clock_offset
|
161
|
+
@logger.debug "clock offset changed"
|
162
|
+
descr_changed = true
|
163
|
+
clock.attributes['offset'] = config.clock_offset
|
164
|
+
end
|
165
|
+
|
166
|
+
# clock timers - because timers can be added/removed, just rebuild and then compare
|
167
|
+
if !config.clock_timers.empty? || clock.has_elements?
|
168
|
+
oldclock = ''
|
169
|
+
formatter.write(REXML::XPath.first(xml_descr, '/domain/clock'), oldclock)
|
170
|
+
clock.delete_element('//timer')
|
171
|
+
config.clock_timers.each do |clock_timer|
|
172
|
+
timer = REXML::Element.new('timer', clock)
|
173
|
+
clock_timer.each do |attr, value|
|
174
|
+
timer.attributes[attr.to_s] = value
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
newclock = ''
|
179
|
+
formatter.write(clock, newclock)
|
180
|
+
unless newclock.eql? oldclock
|
181
|
+
@logger.debug "clock timers config changed"
|
182
|
+
descr_changed = true
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
140
186
|
# Graphics
|
141
187
|
graphics = REXML::XPath.first(xml_descr, '/domain/devices/graphics')
|
142
188
|
if config.graphics_type != 'none'
|
@@ -178,31 +224,31 @@ module VagrantPlugins
|
|
178
224
|
end
|
179
225
|
|
180
226
|
# TPM
|
181
|
-
if config.tpm_path
|
182
|
-
|
227
|
+
if [config.tpm_path, config.tpm_version].any?
|
228
|
+
if config.tpm_path
|
229
|
+
raise Errors::FogCreateServerError, 'The TPM Path must be fully qualified' unless config.tpm_path[0].chr == '/'
|
230
|
+
end
|
183
231
|
|
184
|
-
tpm
|
185
|
-
if
|
232
|
+
# just build the tpm element every time
|
233
|
+
# check at the end if it is different
|
234
|
+
oldtpm = REXML::XPath.first(xml_descr, '/domain/devices/tpm')
|
235
|
+
REXML::XPath.first(xml_descr, '/domain/devices').delete_element("tpm")
|
236
|
+
newtpm = REXML::Element.new('tpm', REXML::XPath.first(xml_descr, '/domain/devices'))
|
237
|
+
|
238
|
+
newtpm.attributes['model'] = config.tpm_model
|
239
|
+
backend = newtpm.add_element('backend')
|
240
|
+
backend.attributes['type'] = config.tpm_type
|
241
|
+
|
242
|
+
case config.tpm_type
|
243
|
+
when 'emulator'
|
244
|
+
backend.attributes['version'] = config.tpm_version
|
245
|
+
when 'passthrough'
|
246
|
+
backend.add_element('device').attributes['path'] = config.tpm_path
|
247
|
+
end
|
248
|
+
|
249
|
+
unless "'#{newtpm}'".eql? "'#{oldtpm}'"
|
250
|
+
@logger.debug "tpm config changed"
|
186
251
|
descr_changed = true
|
187
|
-
tpm = REXML::Element.new('tpm', REXML::XPath.first(xml_descr, '/domain/devices/tpm/model'))
|
188
|
-
tpm.attributes['model'] = config.tpm_model
|
189
|
-
tpm_backend_type = tpm.add_element('backend')
|
190
|
-
tpm_backend_type.attributes['type'] = config.tpm_type
|
191
|
-
tpm_device_path = tpm_backend_type.add_element('device')
|
192
|
-
tpm_device_path.attributes['path'] = config.tpm_path
|
193
|
-
else
|
194
|
-
if tpm.attributes['model'] != config.tpm_model
|
195
|
-
descr_changed = true
|
196
|
-
tpm.attributes['model'] = config.tpm_model
|
197
|
-
end
|
198
|
-
if tpm.elements['backend'].attributes['type'] != config.tpm_type
|
199
|
-
descr_changed = true
|
200
|
-
tpm.elements['backend'].attributes['type'] = config.tpm_type
|
201
|
-
end
|
202
|
-
if tpm.elements['backend'].elements['device'].attributes['path'] != config.tpm_path
|
203
|
-
descr_changed = true
|
204
|
-
tpm.elements['backend'].elements['device'].attributes['path'] = config.tpm_path
|
205
|
-
end
|
206
252
|
end
|
207
253
|
end
|
208
254
|
|
@@ -210,16 +256,21 @@ module VagrantPlugins
|
|
210
256
|
video = REXML::XPath.first(xml_descr, '/domain/devices/video')
|
211
257
|
if !video.nil? && (config.graphics_type == 'none')
|
212
258
|
# graphics_type = none, video devices are removed since there is no possible output
|
259
|
+
@logger.debug "deleting video elements as config.graphics_type is none"
|
213
260
|
descr_changed = true
|
214
261
|
video.parent.delete_element(video)
|
215
262
|
else
|
216
263
|
video_model = REXML::XPath.first(xml_descr, '/domain/devices/video/model')
|
217
264
|
if video_model.nil?
|
265
|
+
@logger.debug "video updated from not set to type '#{config.video_type}' and vram '#{config.video_vram}'"
|
266
|
+
descr_changed = true
|
218
267
|
video_model = REXML::Element.new('model', REXML::XPath.first(xml_descr, '/domain/devices/video'))
|
219
268
|
video_model.attributes['type'] = config.video_type
|
220
269
|
video_model.attributes['vram'] = config.video_vram
|
221
270
|
else
|
222
|
-
if video_model.attributes['type'] != config.video_type || video_model.attributes['vram'] != config.video_vram
|
271
|
+
if video_model.attributes['type'] != config.video_type || video_model.attributes['vram'] != config.video_vram.to_s
|
272
|
+
@logger.debug "video type updated from '#{video_model.attributes['type']}' to '#{config.video_type}'"
|
273
|
+
@logger.debug "video vram updated from '#{video_model.attributes['vram']}' to '#{config.video_vram}'"
|
223
274
|
descr_changed = true
|
224
275
|
video_model.attributes['type'] = config.video_type
|
225
276
|
video_model.attributes['vram'] = config.video_vram
|
@@ -237,11 +288,13 @@ module VagrantPlugins
|
|
237
288
|
if config.dtb
|
238
289
|
dtb = REXML::XPath.first(xml_descr, '/domain/os/dtb')
|
239
290
|
if dtb.nil?
|
291
|
+
@logger.debug "dtb updated from not set to '#{config.dtb}'"
|
240
292
|
descr_changed = true
|
241
293
|
dtb = REXML::Element.new('dtb', REXML::XPath.first(xml_descr, '/domain/os'))
|
242
294
|
dtb.text = config.dtb
|
243
295
|
else
|
244
|
-
if dtb.text != config.dtb
|
296
|
+
if (dtb.text or '') != config.dtb
|
297
|
+
@logger.debug "dtb updated from '#{dtb.text}' to '#{config.dtb}'"
|
245
298
|
descr_changed = true
|
246
299
|
dtb.text = config.dtb
|
247
300
|
end
|
@@ -252,11 +305,13 @@ module VagrantPlugins
|
|
252
305
|
if config.kernel
|
253
306
|
kernel = REXML::XPath.first(xml_descr, '/domain/os/kernel')
|
254
307
|
if kernel.nil?
|
308
|
+
@logger.debug "kernel updated from not set to '#{config.kernel}'"
|
255
309
|
descr_changed = true
|
256
310
|
kernel = REXML::Element.new('kernel', REXML::XPath.first(xml_descr, '/domain/os'))
|
257
311
|
kernel.text = config.kernel
|
258
312
|
else
|
259
|
-
if kernel.text != config.kernel
|
313
|
+
if (kernel.text or '').strip != config.kernel
|
314
|
+
@logger.debug "kernel updated from '#{kernel.text}' to '#{config.kernel}'"
|
260
315
|
descr_changed = true
|
261
316
|
kernel.text = config.kernel
|
262
317
|
end
|
@@ -265,11 +320,13 @@ module VagrantPlugins
|
|
265
320
|
if config.initrd
|
266
321
|
initrd = REXML::XPath.first(xml_descr, '/domain/os/initrd')
|
267
322
|
if initrd.nil?
|
323
|
+
@logger.debug "initrd updated from not set to '#{config.initrd}'"
|
268
324
|
descr_changed = true
|
269
325
|
initrd = REXML::Element.new('initrd', REXML::XPath.first(xml_descr, '/domain/os'))
|
270
326
|
initrd.text = config.initrd
|
271
327
|
else
|
272
|
-
if initrd.text != config.initrd
|
328
|
+
if (initrd.text or '').strip != config.initrd
|
329
|
+
@logger.debug "initrd updated from '#{initrd.text}' to '#{config.initrd}'"
|
273
330
|
descr_changed = true
|
274
331
|
initrd.text = config.initrd
|
275
332
|
end
|