vagrant-libvirt 0.8.2 → 0.9.0
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/lib/vagrant-libvirt/action/create_domain.rb +19 -91
- data/lib/vagrant-libvirt/action/destroy_domain.rb +20 -4
- data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
- data/lib/vagrant-libvirt/action/handle_box_image.rb +2 -0
- data/lib/vagrant-libvirt/action/resolve_disk_settings.rb +174 -0
- data/lib/vagrant-libvirt/action/start_domain.rb +41 -1
- data/lib/vagrant-libvirt/action.rb +4 -0
- data/lib/vagrant-libvirt/config.rb +4 -0
- data/lib/vagrant-libvirt/templates/domain.xml.erb +2 -2
- data/lib/vagrant-libvirt/util/domain_flags.rb +15 -0
- data/lib/vagrant-libvirt/util.rb +1 -0
- data/lib/vagrant-libvirt/version +1 -1
- data/locales/en.yml +4 -2
- data/spec/support/libvirt_context.rb +4 -0
- data/spec/unit/action/cleanup_on_failure_spec.rb +0 -2
- data/spec/unit/action/create_domain_spec.rb +113 -147
- data/spec/unit/action/create_domain_volume_spec.rb +0 -3
- data/spec/unit/action/destroy_domain_spec.rb +43 -10
- data/spec/unit/action/handle_box_image_spec.rb +13 -13
- data/spec/unit/action/package_domain_spec.rb +0 -5
- data/spec/unit/action/resolve_disk_settings_spec/default_domain.xml +43 -0
- data/spec/unit/action/resolve_disk_settings_spec/default_no_aliases.xml +42 -0
- data/spec/unit/action/{create_domain_spec → resolve_disk_settings_spec}/default_system_storage_pool.xml +0 -0
- data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box.xml +55 -0
- data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box_additional_and_custom_no_aliases.xml +67 -0
- data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box_additional_storage.xml +67 -0
- data/spec/unit/action/resolve_disk_settings_spec.rb +361 -0
- data/spec/unit/action/start_domain_spec/existing_added_nvram.xml +62 -0
- data/spec/unit/action/start_domain_spec/nvram_domain.xml +64 -0
- data/spec/unit/action/start_domain_spec/nvram_domain_other_setting.xml +64 -0
- data/spec/unit/action/start_domain_spec/nvram_domain_removed.xml +64 -0
- data/spec/unit/action/start_domain_spec.rb +64 -6
- data/spec/unit/action/wait_till_up_spec.rb +0 -2
- data/spec/unit/action_spec.rb +0 -3
- data/spec/unit/config_spec.rb +18 -0
- data/spec/unit/driver_spec.rb +2 -0
- data/spec/unit/templates/domain_all_settings.xml +2 -2
- data/spec/unit/templates/domain_spec.rb +2 -2
- metadata +37 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79027c1097a7e8136b8d56f74fd0b27932bf17c48387de84c57626c2bd348714
|
4
|
+
data.tar.gz: cd6acea3cf183191ea6bbee6e60d7a1fc76a5f0b556f273f60657238283841ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d6483a73ce398e6fd057b2fc0503392c628ad1fc228d9d954b9a5e31d9a65ab883c25f30cb9360ce5eff46554492dd010b68d741f3c8935e64228207bf2f210
|
7
|
+
data.tar.gz: 1a083a93899bb48d4d750aa8967bdcb8e6b1b0b9a8fb0d88c912097444cd202c52fe0330f81a1e4803dde184b06e035c8bd8d32397035c186653b978db790e12
|
@@ -16,20 +16,6 @@ module VagrantPlugins
|
|
16
16
|
@app = app
|
17
17
|
end
|
18
18
|
|
19
|
-
def _disk_name(name, disk)
|
20
|
-
"#{name}-#{disk[:device]}.#{disk[:type]}" # disk name
|
21
|
-
end
|
22
|
-
|
23
|
-
def _disks_print(disks)
|
24
|
-
disks.collect do |x|
|
25
|
-
"#{x[:device]}(#{x[:type]}, #{x[:bus]}, #{x[:size]})"
|
26
|
-
end.join(', ')
|
27
|
-
end
|
28
|
-
|
29
|
-
def _cdroms_print(cdroms)
|
30
|
-
cdroms.collect { |x| x[:dev] }.join(', ')
|
31
|
-
end
|
32
|
-
|
33
19
|
def call(env)
|
34
20
|
# Get config.
|
35
21
|
config = env[:machine].provider_config
|
@@ -58,8 +44,6 @@ module VagrantPlugins
|
|
58
44
|
@nvram = config.nvram
|
59
45
|
@machine_type = config.machine_type
|
60
46
|
@machine_arch = config.machine_arch
|
61
|
-
@disk_bus = config.disk_bus
|
62
|
-
@disk_device = config.disk_device
|
63
47
|
@disk_driver_opts = config.disk_driver_opts
|
64
48
|
@nested = config.nested
|
65
49
|
@memory_size = config.memory.to_i * 1024
|
@@ -94,9 +78,8 @@ module VagrantPlugins
|
|
94
78
|
|
95
79
|
# Storage
|
96
80
|
@storage_pool_name = config.storage_pool_name
|
97
|
-
@
|
98
|
-
@
|
99
|
-
@disks = config.disks
|
81
|
+
@domain_volumes = env[:domain_volumes] || []
|
82
|
+
@disks = env[:disks] || []
|
100
83
|
@cdroms = config.cdroms
|
101
84
|
|
102
85
|
# Input
|
@@ -139,77 +122,19 @@ module VagrantPlugins
|
|
139
122
|
@memballoon_pci_bus = config.memballoon_pci_bus
|
140
123
|
@memballoon_pci_slot = config.memballoon_pci_slot
|
141
124
|
|
142
|
-
config = env[:machine].provider_config
|
143
125
|
@domain_type = config.driver
|
144
126
|
|
145
127
|
@os_type = 'hvm'
|
146
128
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
else
|
154
|
-
pool_name = @storage_pool_name
|
155
|
-
end
|
156
|
-
|
157
|
-
# special handling for domain volume
|
158
|
-
env[:box_volumes][0][:device] = env[:box_volumes][0].fetch(:device, @disk_device)
|
159
|
-
|
160
|
-
resolver.resolve!(env[:box_volumes])
|
161
|
-
|
162
|
-
@logger.debug "Search for volumes in pool: #{pool_name}"
|
163
|
-
env[:box_volumes].each_index do |index|
|
164
|
-
suffix_index = index > 0 ? "_#{index}" : ''
|
165
|
-
domain_volume = env[:machine].provider.driver.connection.volumes.all(
|
166
|
-
name: "#{@name}#{suffix_index}.img"
|
167
|
-
).find { |x| x.pool_name == pool_name }
|
168
|
-
raise Errors::DomainVolumeExists if domain_volume.nil?
|
169
|
-
|
170
|
-
@domain_volumes.push({
|
171
|
-
:dev => env[:box_volumes][index][:device],
|
172
|
-
:cache => @domain_volume_cache,
|
173
|
-
:bus => @disk_bus,
|
174
|
-
:path => domain_volume.path,
|
175
|
-
:virtual_size => env[:box_volumes][index][:virtual_size]
|
176
|
-
})
|
177
|
-
end
|
178
|
-
|
129
|
+
env[:domain_volumes].each_with_index do |vol, index|
|
130
|
+
suffix_index = index > 0 ? "_#{index}" : ''
|
131
|
+
domain_volume = env[:machine].provider.driver.connection.volumes.all(
|
132
|
+
name: "#{@name}#{suffix_index}.img"
|
133
|
+
).find { |x| x.pool_name == vol[:pool] }
|
134
|
+
raise Errors::NoDomainVolume if domain_volume.nil?
|
179
135
|
end
|
180
136
|
|
181
|
-
# If we have a box, take the path from the domain volume and set our storage_prefix.
|
182
|
-
# If not, we dump the storage pool xml to get its defined path.
|
183
|
-
# the default storage prefix is typically: /var/lib/libvirt/images/
|
184
|
-
if env[:machine].config.vm.box
|
185
|
-
storage_prefix = File.dirname(@domain_volumes[0][:path]) + '/' # steal
|
186
|
-
else
|
187
|
-
storage_prefix = get_disk_storage_prefix(env, @storage_pool_name)
|
188
|
-
end
|
189
|
-
|
190
|
-
resolver.resolve!(@disks)
|
191
|
-
|
192
137
|
@disks.each do |disk|
|
193
|
-
disk[:path] ||= _disk_name(@name, disk)
|
194
|
-
|
195
|
-
# On volume creation, the <path> element inside <target>
|
196
|
-
# is oddly ignored; instead the path is taken from the
|
197
|
-
# <name> element:
|
198
|
-
# http://www.redhat.com/archives/libvir-list/2008-August/msg00329.html
|
199
|
-
disk[:name] = disk[:path]
|
200
|
-
|
201
|
-
disk[:absolute_path] = storage_prefix + disk[:path]
|
202
|
-
|
203
|
-
if not disk[:pool].nil?
|
204
|
-
disk_pool_name = disk[:pool]
|
205
|
-
@logger.debug "Overriding pool name with: #{disk_pool_name}"
|
206
|
-
disk_storage_prefix = get_disk_storage_prefix(env, disk_pool_name)
|
207
|
-
disk[:absolute_path] = disk_storage_prefix + disk[:path]
|
208
|
-
@logger.debug "Overriding disk path with: #{disk[:absolute_path]}"
|
209
|
-
else
|
210
|
-
disk_pool_name = @storage_pool_name
|
211
|
-
end
|
212
|
-
|
213
138
|
# make the disk. equivalent to:
|
214
139
|
# qemu-img create -f qcow2 <path> 5g
|
215
140
|
begin
|
@@ -221,13 +146,13 @@ module VagrantPlugins
|
|
221
146
|
owner: storage_uid(env),
|
222
147
|
group: storage_gid(env),
|
223
148
|
#:allocation => ?,
|
224
|
-
pool_name:
|
149
|
+
pool_name: disk[:pool],
|
225
150
|
)
|
226
151
|
rescue Libvirt::Error => e
|
227
152
|
# It is hard to believe that e contains just a string
|
228
153
|
# and no useful error code!
|
229
154
|
msg = "Call to virStorageVolCreateXML failed: " +
|
230
|
-
"storage volume '#{disk[:
|
155
|
+
"storage volume '#{disk[:absolute_path]}' exists already"
|
231
156
|
if e.message == msg and disk[:allow_existing]
|
232
157
|
disk[:preexisting] = true
|
233
158
|
else
|
@@ -300,7 +225,7 @@ module VagrantPlugins
|
|
300
225
|
end
|
301
226
|
env[:ui].info(" -- Storage pool: #{@storage_pool_name}")
|
302
227
|
@domain_volumes.each do |volume|
|
303
|
-
env[:ui].info(" -- Image(#{volume[:
|
228
|
+
env[:ui].info(" -- Image(#{volume[:device]}): #{volume[:absolute_path]}, #{volume[:bus]}, #{volume[:virtual_size].to_GB}G")
|
304
229
|
end
|
305
230
|
|
306
231
|
if not @disk_driver_opts.empty?
|
@@ -466,11 +391,14 @@ module VagrantPlugins
|
|
466
391
|
end
|
467
392
|
|
468
393
|
private
|
469
|
-
def
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
394
|
+
def _disks_print(disks)
|
395
|
+
disks.collect do |x|
|
396
|
+
"#{x[:device]}(#{x[:type]}, #{x[:bus]}, #{x[:size]})"
|
397
|
+
end.join(', ')
|
398
|
+
end
|
399
|
+
|
400
|
+
def _cdroms_print(cdroms)
|
401
|
+
cdroms.collect { |x| x[:dev] }.join(', ')
|
474
402
|
end
|
475
403
|
end
|
476
404
|
end
|
@@ -1,7 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'log4r'
|
4
|
-
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'rexml'
|
7
|
+
rescue LoadError
|
8
|
+
require 'rexml/rexml'
|
9
|
+
end
|
5
10
|
|
6
11
|
module VagrantPlugins
|
7
12
|
module ProviderLibvirt
|
@@ -43,21 +48,24 @@ module VagrantPlugins
|
|
43
48
|
|
44
49
|
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
45
50
|
|
51
|
+
undefine_flags = 0
|
52
|
+
undefine_flags |= ProviderLibvirt::Util::DomainFlags::VIR_DOMAIN_UNDEFINE_KEEP_NVRAM if env[:machine].provider_config.nvram
|
53
|
+
|
46
54
|
if env[:machine].provider_config.disks.empty? &&
|
47
55
|
env[:machine].provider_config.cdroms.empty?
|
48
56
|
# if using default configuration of disks and cdroms
|
49
57
|
# cdroms are consider volumes, but cannot be destroyed
|
50
|
-
domain
|
58
|
+
destroy_domain(domain, destroy_volumes: true, flags: undefine_flags)
|
51
59
|
else
|
52
60
|
domain_xml = libvirt_domain.xml_desc(1)
|
53
61
|
xml_descr = REXML::Document.new(domain_xml)
|
54
62
|
disks_xml = REXML::XPath.match(xml_descr, '/domain/devices/disk[@device="disk"]')
|
55
63
|
have_aliases = !(REXML::XPath.match(disks_xml, './alias[@name="ua-box-volume-0"]').first).nil?
|
56
64
|
if !have_aliases
|
57
|
-
env[:ui].warn(I18n.t('vagrant_libvirt.
|
65
|
+
env[:ui].warn(I18n.t('vagrant_libvirt.domain_xml.obsolete_method'))
|
58
66
|
end
|
59
67
|
|
60
|
-
domain
|
68
|
+
destroy_domain(domain, destroy_volumes: false, flags: undefine_flags)
|
61
69
|
|
62
70
|
volumes = domain.volumes
|
63
71
|
|
@@ -164,6 +172,14 @@ module VagrantPlugins
|
|
164
172
|
libvirt_disk.destroy if libvirt_disk
|
165
173
|
end
|
166
174
|
end
|
175
|
+
|
176
|
+
def destroy_domain(domain, destroy_volumes:, flags:)
|
177
|
+
if domain.method(:destroy).parameters.first.include?(:flags)
|
178
|
+
domain.destroy(destroy_volumes: destroy_volumes, flags: flags)
|
179
|
+
else
|
180
|
+
domain.destroy(destroy_volumes: destroy_volumes)
|
181
|
+
end
|
182
|
+
end
|
167
183
|
end
|
168
184
|
end
|
169
185
|
end
|
@@ -104,6 +104,8 @@ module VagrantPlugins
|
|
104
104
|
end
|
105
105
|
# save for use by later actions
|
106
106
|
env[:box_volumes][0][:virtual_size] = box_virtual_size
|
107
|
+
# special handling for domain volume
|
108
|
+
env[:box_volumes][0][:device] ||= config.disk_device
|
107
109
|
|
108
110
|
# while inside the synchronize block take care not to call the next
|
109
111
|
# action in the chain, as must exit this block first to prevent
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'log4r'
|
4
|
+
require 'rexml'
|
5
|
+
|
6
|
+
require 'vagrant-libvirt/util/resolvers'
|
7
|
+
|
8
|
+
module VagrantPlugins
|
9
|
+
module ProviderLibvirt
|
10
|
+
module Action
|
11
|
+
class ResolveDiskSettings
|
12
|
+
def initialize(app, _env)
|
13
|
+
@logger = Log4r::Logger.new('vagrant_libvirt::action::resolve_disk_devices')
|
14
|
+
@app = app
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
# Get config.
|
19
|
+
config = env[:machine].provider_config
|
20
|
+
|
21
|
+
domain_name = env[:domain_name] # only set on create
|
22
|
+
disk_bus = config.disk_bus
|
23
|
+
disk_device = config.disk_device
|
24
|
+
domain_volume_cache = config.volume_cache || 'default'
|
25
|
+
|
26
|
+
# Storage
|
27
|
+
storage_pool_name = config.storage_pool_name
|
28
|
+
snapshot_pool_name = config.snapshot_pool_name
|
29
|
+
domain_volumes = []
|
30
|
+
disks = config.disks.dup
|
31
|
+
|
32
|
+
resolver = ::VagrantPlugins::ProviderLibvirt::Util::DiskDeviceResolver.new(disk_device[0..1])
|
33
|
+
|
34
|
+
# Get path to domain image from the storage pool selected if we have a box.
|
35
|
+
if env[:machine].config.vm.box
|
36
|
+
pool_name = if snapshot_pool_name == storage_pool_name
|
37
|
+
storage_pool_name
|
38
|
+
else
|
39
|
+
snapshot_pool_name
|
40
|
+
end
|
41
|
+
|
42
|
+
if env[:box_volumes].nil?
|
43
|
+
# domain must be already created, need to read domain volumes from domain XML
|
44
|
+
libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
|
45
|
+
env[:machine].id
|
46
|
+
)
|
47
|
+
domain_xml = libvirt_domain.xml_desc(1)
|
48
|
+
xml_descr = REXML::Document.new(domain_xml)
|
49
|
+
domain_name = xml_descr.elements['domain'].elements['name'].text
|
50
|
+
disks_xml = REXML::XPath.match(xml_descr, '/domain/devices/disk[@device="disk"]')
|
51
|
+
have_aliases = !REXML::XPath.match(disks_xml, './alias[@name="ua-box-volume-0"]').first.nil?
|
52
|
+
env[:ui].warn(I18n.t('vagrant_libvirt.domain_xml.obsolete_method')) unless have_aliases
|
53
|
+
|
54
|
+
if have_aliases
|
55
|
+
REXML::XPath.match(disks_xml,
|
56
|
+
'./alias[contains(@name, "ua-box-volume-")]').each_with_index do |alias_xml, idx|
|
57
|
+
domain_volumes.push(volume_from_xml(alias_xml.parent, domain_name, idx))
|
58
|
+
end
|
59
|
+
else
|
60
|
+
# fallback to try and infer which boxes are box images, as they are listed first
|
61
|
+
# as soon as there is no match, can exit
|
62
|
+
disks_xml.each_with_index do |box_disk_xml, idx|
|
63
|
+
diskname = box_disk_xml.elements['source'].attributes['file'].rpartition('/').last
|
64
|
+
|
65
|
+
break if volume_name(domain_name, idx) != diskname
|
66
|
+
|
67
|
+
domain_volumes.push(volume_from_xml(box_disk_xml, domain_name, idx))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
else
|
71
|
+
|
72
|
+
@logger.debug "Search for volumes in pool: #{pool_name}"
|
73
|
+
env[:box_volumes].each_index do |index|
|
74
|
+
domain_volume = env[:machine].provider.driver.connection.volumes.all(
|
75
|
+
name: volume_name(domain_name, index)
|
76
|
+
).find { |x| x.pool_name == pool_name }
|
77
|
+
raise Errors::NoDomainVolume if domain_volume.nil?
|
78
|
+
|
79
|
+
domain_volumes.push(
|
80
|
+
{
|
81
|
+
name: volume_name(domain_name, index),
|
82
|
+
device: env[:box_volumes][index][:device],
|
83
|
+
cache: domain_volume_cache,
|
84
|
+
bus: disk_bus,
|
85
|
+
absolute_path: domain_volume.path,
|
86
|
+
virtual_size: env[:box_volumes][index][:virtual_size],
|
87
|
+
pool: pool_name,
|
88
|
+
}
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
resolver.resolve!(domain_volumes)
|
94
|
+
|
95
|
+
# If we have a box, take the path from the domain volume and set our storage_prefix.
|
96
|
+
# If not, we dump the storage pool xml to get its defined path.
|
97
|
+
# the default storage prefix is typically: /var/lib/libvirt/images/
|
98
|
+
storage_prefix = "#{File.dirname(domain_volumes[0][:absolute_path])}/" # steal
|
99
|
+
else
|
100
|
+
# Ensure domain name is set for subsequent steps if restarting a machine without a box
|
101
|
+
libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
|
102
|
+
env[:machine].id
|
103
|
+
)
|
104
|
+
domain_xml = libvirt_domain.xml_desc(1)
|
105
|
+
xml_descr = REXML::Document.new(domain_xml)
|
106
|
+
domain_name = xml_descr.elements['domain'].elements['name'].text
|
107
|
+
|
108
|
+
storage_prefix = get_disk_storage_prefix(env[:machine], storage_pool_name)
|
109
|
+
end
|
110
|
+
|
111
|
+
resolver.resolve!(disks)
|
112
|
+
|
113
|
+
disks.each do |disk|
|
114
|
+
disk[:path] ||= disk_name(domain_name, disk)
|
115
|
+
|
116
|
+
# On volume creation, the <path> element inside <target>
|
117
|
+
# is oddly ignored; instead the path is taken from the
|
118
|
+
# <name> element:
|
119
|
+
# http://www.redhat.com/archives/libvir-list/2008-August/msg00329.html
|
120
|
+
disk[:name] = disk[:path]
|
121
|
+
|
122
|
+
disk[:absolute_path] = storage_prefix + disk[:path]
|
123
|
+
|
124
|
+
if disk[:pool].nil?
|
125
|
+
disk[:pool] = storage_pool_name
|
126
|
+
else
|
127
|
+
@logger.debug "Overriding pool name with: #{disk[:pool]}"
|
128
|
+
disk_storage_prefix = get_disk_storage_prefix(env[:machine], disk[:pool])
|
129
|
+
disk[:absolute_path] = disk_storage_prefix + disk[:path]
|
130
|
+
@logger.debug "Overriding disk path with: #{disk[:absolute_path]}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
env[:domain_volumes] = domain_volumes
|
135
|
+
env[:disks] = disks
|
136
|
+
|
137
|
+
@app.call(env)
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def disk_name(name, disk)
|
143
|
+
"#{name}-#{disk[:device]}.#{disk[:type]}" # disk name
|
144
|
+
end
|
145
|
+
|
146
|
+
def get_disk_storage_prefix(machine, disk_pool_name)
|
147
|
+
disk_storage_pool = machine.provider.driver.connection.client.lookup_storage_pool_by_name(disk_pool_name)
|
148
|
+
raise Errors::NoStoragePool if disk_storage_pool.nil?
|
149
|
+
|
150
|
+
xml = Nokogiri::XML(disk_storage_pool.xml_desc)
|
151
|
+
"#{xml.xpath('/pool/target/path').inner_text}/"
|
152
|
+
end
|
153
|
+
|
154
|
+
def volume_name(domain_name, index)
|
155
|
+
domain_name + (index.zero? ? '.img' : "_#{index}.img")
|
156
|
+
end
|
157
|
+
|
158
|
+
def volume_from_xml(device_xml, domain_name, index)
|
159
|
+
driver = device_xml.elements['driver']
|
160
|
+
source = device_xml.elements['source']
|
161
|
+
target = device_xml.elements['target']
|
162
|
+
|
163
|
+
{
|
164
|
+
name: volume_name(domain_name, index),
|
165
|
+
device: target.attributes['dev'],
|
166
|
+
cache: driver.attributes['cache'],
|
167
|
+
bus: target.attributes['bus'],
|
168
|
+
absolute_path: source.attributes['file'],
|
169
|
+
}
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -375,10 +375,50 @@ module VagrantPlugins
|
|
375
375
|
end
|
376
376
|
end
|
377
377
|
|
378
|
+
loader = REXML::XPath.first(xml_descr, '/domain/os/loader')
|
379
|
+
if config.loader
|
380
|
+
if loader.nil?
|
381
|
+
descr_changed = true
|
382
|
+
loader = REXML::Element.new('loader')
|
383
|
+
REXML::XPath.first(xml_descr, '/domain/os').insert_after('//type', loader)
|
384
|
+
loader.text = config.loader
|
385
|
+
else
|
386
|
+
if (loader.text or '').strip != config.loader
|
387
|
+
descr_changed = true
|
388
|
+
loader.text = config.loader
|
389
|
+
end
|
390
|
+
end
|
391
|
+
loader.attributes['type'] = config.nvram ? 'pflash' : 'rom'
|
392
|
+
elsif !loader.nil?
|
393
|
+
descr_changed = true
|
394
|
+
loader.parent.delete_element(loader)
|
395
|
+
end
|
396
|
+
|
397
|
+
undefine_flags = 0
|
398
|
+
nvram = REXML::XPath.first(xml_descr, '/domain/os/nvram')
|
399
|
+
if config.nvram
|
400
|
+
if nvram.nil?
|
401
|
+
descr_changed = true
|
402
|
+
nvram = REXML::Element.new('nvram')
|
403
|
+
REXML::XPath.first(xml_descr, '/domain/os').insert_after(loader, nvram)
|
404
|
+
nvram.text = config.nvram
|
405
|
+
else
|
406
|
+
if (nvram.text or '').strip != config.nvram
|
407
|
+
descr_changed = true
|
408
|
+
nvram.text = config.nvram
|
409
|
+
end
|
410
|
+
undefine_flags |= ProviderLibvirt::Util::DomainFlags::VIR_DOMAIN_UNDEFINE_KEEP_NVRAM
|
411
|
+
end
|
412
|
+
elsif !nvram.nil?
|
413
|
+
descr_changed = true
|
414
|
+
undefine_flags |= ProviderLibvirt::Util::DomainFlags::VIR_DOMAIN_UNDEFINE_NVRAM
|
415
|
+
nvram.parent.delete_element(nvram)
|
416
|
+
end
|
417
|
+
|
378
418
|
# Apply
|
379
419
|
if descr_changed
|
380
420
|
begin
|
381
|
-
libvirt_domain.undefine
|
421
|
+
libvirt_domain.undefine(undefine_flags)
|
382
422
|
new_descr = String.new
|
383
423
|
xml_descr.write new_descr
|
384
424
|
env[:machine].provider.driver.connection.servers.create(xml: new_descr)
|
@@ -35,6 +35,7 @@ module VagrantPlugins
|
|
35
35
|
autoload :ReadMacAddresses, action_root.join('read_mac_addresses')
|
36
36
|
autoload :RemoveLibvirtImage, action_root.join('remove_libvirt_image')
|
37
37
|
autoload :RemoveStaleVolume, action_root.join('remove_stale_volume')
|
38
|
+
autoload :ResolveDiskSettings, action_root.join('resolve_disk_settings')
|
38
39
|
autoload :ResumeDomain, action_root.join('resume_domain')
|
39
40
|
autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
|
40
41
|
autoload :SetBootOrder, action_root.join('set_boot_order')
|
@@ -81,6 +82,7 @@ module VagrantPlugins
|
|
81
82
|
b2.use SetNameOfDomain
|
82
83
|
|
83
84
|
if !env[:machine].config.vm.box
|
85
|
+
b2.use ResolveDiskSettings
|
84
86
|
b2.use CreateDomain
|
85
87
|
b2.use CreateNetworks
|
86
88
|
b2.use CreateNetworkInterfaces
|
@@ -94,6 +96,7 @@ module VagrantPlugins
|
|
94
96
|
b2.use HandleBox
|
95
97
|
b2.use HandleBoxImage
|
96
98
|
b2.use CreateDomainVolume
|
99
|
+
b2.use ResolveDiskSettings
|
97
100
|
b2.use CreateDomain
|
98
101
|
b2.use CreateNetworks
|
99
102
|
b2.use CreateNetworkInterfaces
|
@@ -104,6 +107,7 @@ module VagrantPlugins
|
|
104
107
|
end
|
105
108
|
else
|
106
109
|
env[:halt_on_error] = true
|
110
|
+
b2.use ResolveDiskSettings
|
107
111
|
b2.use CreateNetworks
|
108
112
|
b2.use action_start
|
109
113
|
end
|
@@ -994,6 +994,10 @@ module VagrantPlugins
|
|
994
994
|
errors << "libvirt.qemu_use_agent must be a boolean."
|
995
995
|
end
|
996
996
|
|
997
|
+
if !@nvram.nil? && @loader.nil?
|
998
|
+
errors << "use of 'nvram' requires a 'loader' to be specified, please add one to the configuration"
|
999
|
+
end
|
1000
|
+
|
997
1001
|
if @qemu_use_agent == true
|
998
1002
|
# if qemu agent is used to optain domain ip configuration, at least
|
999
1003
|
# one qemu channel has to be configured. As there are various options,
|
@@ -117,9 +117,9 @@
|
|
117
117
|
@disk_driver_opts.reject { |k,v| v.nil? }
|
118
118
|
.map { |k,v| "#{k}='#{v}'"}
|
119
119
|
.join(' ') -%>/>
|
120
|
-
<source file='<%= volume[:
|
120
|
+
<source file='<%= volume[:absolute_path] %>'/>
|
121
121
|
<%# we need to ensure a unique target dev -%>
|
122
|
-
<target dev='<%= volume[:
|
122
|
+
<target dev='<%= volume[:device] %>' bus='<%= volume[:bus] %>'/>
|
123
123
|
</disk>
|
124
124
|
<%- end -%>
|
125
125
|
<%# additional disks -%>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Ripped from https://libvirt.org/html/libvirt-libvirt-domain.html#types
|
2
|
+
module VagrantPlugins
|
3
|
+
module ProviderLibvirt
|
4
|
+
module Util
|
5
|
+
module DomainFlags
|
6
|
+
# virDomainUndefineFlagsValues
|
7
|
+
VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = 1 # Also remove any managed save
|
8
|
+
VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA = 2 # If last use of domain, then also remove any snapshot metadata
|
9
|
+
VIR_DOMAIN_UNDEFINE_NVRAM = 4 # Also remove any nvram file
|
10
|
+
VIR_DOMAIN_UNDEFINE_KEEP_NVRAM = 8 # Keep nvram file
|
11
|
+
VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA = 16 # If last use of domain, then also remove any checkpoint metadata Future undefine control flags should come here.
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/vagrant-libvirt/util.rb
CHANGED
@@ -9,6 +9,7 @@ module VagrantPlugins
|
|
9
9
|
autoload :NetworkUtil, 'vagrant-libvirt/util/network_util'
|
10
10
|
autoload :StorageUtil, 'vagrant-libvirt/util/storage_util'
|
11
11
|
autoload :ErrorCodes, 'vagrant-libvirt/util/error_codes'
|
12
|
+
autoload :DomainFlags, 'vagrant-libvirt/util/domain_flags'
|
12
13
|
autoload :Ui, 'vagrant-libvirt/util/ui'
|
13
14
|
end
|
14
15
|
end
|
data/lib/vagrant-libvirt/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.0
|
data/locales/en.yml
CHANGED
@@ -58,9 +58,11 @@ en:
|
|
58
58
|
remove_stale_volume: |-
|
59
59
|
Remove stale volume...
|
60
60
|
|
61
|
-
|
61
|
+
domain_xml:
|
62
62
|
obsolete_method: |
|
63
|
-
|
63
|
+
Machine that was originally created without device aliases (pre 0.6.0), using fall-back approach for device identification.
|
64
|
+
|
65
|
+
destroy:
|
64
66
|
unexpected_volumes: |
|
65
67
|
Unexpected number of volumes detected, possibly additional volumes attached outside of vagrant-libvirt.
|
66
68
|
Attempting to handle this correctly, however may experience unexpected behaviour in the domain destroy.
|
@@ -10,6 +10,7 @@ shared_context 'libvirt' do
|
|
10
10
|
let(:libvirt_context) { true }
|
11
11
|
let(:id) { 'dummy-vagrant_dummy' }
|
12
12
|
let(:connection) { double('connection') }
|
13
|
+
let(:driver) { instance_double(VagrantPlugins::ProviderLibvirt::Driver) }
|
13
14
|
let(:domain) { instance_double(::Fog::Libvirt::Compute::Server) }
|
14
15
|
let(:libvirt_client) { instance_double(::Libvirt::Connect) }
|
15
16
|
let(:libvirt_domain) { instance_double(::Libvirt::Domain) }
|
@@ -33,5 +34,8 @@ shared_context 'libvirt' do
|
|
33
34
|
|
34
35
|
allow(machine).to receive(:id).and_return(id)
|
35
36
|
allow(Log4r::Logger).to receive(:new).and_return(logger)
|
37
|
+
|
38
|
+
allow(machine.provider).to receive('driver').and_return(driver)
|
39
|
+
allow(driver).to receive(:connection).and_return(connection)
|
36
40
|
end
|
37
41
|
end
|
@@ -34,8 +34,6 @@ describe VagrantPlugins::ProviderLibvirt::Action::CleanupOnFailure do
|
|
34
34
|
let(:state) { double('state') }
|
35
35
|
|
36
36
|
before do
|
37
|
-
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
|
38
|
-
.to receive(:connection).and_return(connection)
|
39
37
|
allow(machine).to receive(:id).and_return('test-machine-id')
|
40
38
|
allow(machine).to receive(:state).and_return(state)
|
41
39
|
|