vagrant-libvirt 0.3.0 → 0.4.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +170 -17
  3. data/lib/vagrant-libvirt/action/create_domain.rb +30 -9
  4. data/lib/vagrant-libvirt/action/forward_ports.rb +1 -1
  5. data/lib/vagrant-libvirt/action/package_domain.rb +2 -1
  6. data/lib/vagrant-libvirt/action/start_domain.rb +86 -29
  7. data/lib/vagrant-libvirt/action/wait_till_up.rb +7 -27
  8. data/lib/vagrant-libvirt/config.rb +202 -41
  9. data/lib/vagrant-libvirt/driver.rb +46 -31
  10. data/lib/vagrant-libvirt/provider.rb +2 -9
  11. data/lib/vagrant-libvirt/templates/domain.xml.erb +29 -5
  12. data/lib/vagrant-libvirt/version +1 -1
  13. data/lib/vagrant-libvirt/version.rb +57 -9
  14. data/spec/spec_helper.rb +28 -2
  15. data/spec/support/libvirt_context.rb +2 -0
  16. data/spec/support/sharedcontext.rb +4 -0
  17. data/spec/unit/action/create_domain_spec.rb +110 -35
  18. data/spec/unit/action/create_domain_spec/{default_storage_pool.xml → default_system_storage_pool.xml} +0 -0
  19. data/spec/unit/action/create_domain_spec/default_user_storage_pool.xml +17 -0
  20. data/spec/unit/action/start_domain_spec.rb +183 -1
  21. data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +50 -0
  22. data/spec/unit/action/start_domain_spec/default.xml +2 -2
  23. data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +48 -0
  24. data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +48 -0
  25. data/spec/unit/action/wait_till_up_spec.rb +14 -9
  26. data/spec/unit/config_spec.rb +392 -127
  27. data/spec/unit/provider_spec.rb +11 -0
  28. data/spec/unit/templates/domain_all_settings.xml +6 -3
  29. data/spec/unit/templates/domain_custom_cpu_model.xml +2 -1
  30. data/spec/unit/templates/domain_defaults.xml +2 -1
  31. data/spec/unit/templates/domain_spec.rb +80 -2
  32. data/spec/unit/templates/tpm/version_1.2.xml +54 -0
  33. data/spec/unit/templates/tpm/version_2.0.xml +53 -0
  34. metadata +74 -17
@@ -1,3 +1,5 @@
1
+ require 'contextual_proc'
2
+
1
3
  require 'spec_helper'
2
4
  require 'support/sharedcontext'
3
5
 
@@ -8,6 +10,50 @@ describe VagrantPlugins::ProviderLibvirt::Config do
8
10
 
9
11
  let(:fake_env) { Hash.new }
10
12
 
13
+ describe '#clock_timer' do
14
+ it 'should handle all options' do
15
+ expect(
16
+ subject.clock_timer(
17
+ :name => 'rtc',
18
+ :track => 'wall',
19
+ :tickpolicy => 'delay',
20
+ :present => 'yes',
21
+ ).length
22
+ ).to be(1)
23
+ expect(
24
+ subject.clock_timer(
25
+ :name => 'tsc',
26
+ :tickpolicy => 'delay',
27
+ :frequency => '100',
28
+ :mode => 'auto',
29
+ :present => 'yes',
30
+ ).length
31
+ ).to be(2)
32
+ end
33
+
34
+ it 'should correctly save the options' do
35
+ opts = {:name => 'rtc', :track => 'wall'}
36
+ expect(subject.clock_timer(opts).length).to be(1)
37
+
38
+ expect(subject.clock_timers[0]).to eq(opts)
39
+
40
+ opts[:name] = 'tsc'
41
+ expect(subject.clock_timers[0]).to_not eq(opts)
42
+ end
43
+
44
+ it 'should error name option is missing' do
45
+ expect{ subject.clock_timer(:track => "wall") }.to raise_error("Clock timer name must be specified")
46
+ end
47
+
48
+ it 'should error if nil value for option supplied' do
49
+ expect{ subject.clock_timer(:name => "rtc", :track => nil) }.to raise_error("Value of timer option track is nil")
50
+ end
51
+
52
+ it 'should error if unrecognized option specified' do
53
+ expect{ subject.clock_timer(:name => "tsc", :badopt => "value") }.to raise_error("Unknown clock timer option: badopt")
54
+ end
55
+ end
56
+
11
57
  describe '#finalize!' do
12
58
  it 'is valid with defaults' do
13
59
  subject.finalize!
@@ -16,96 +62,264 @@ describe VagrantPlugins::ProviderLibvirt::Config do
16
62
  context '@uri' do
17
63
  before(:example) do
18
64
  stub_const("ENV", fake_env)
65
+ fake_env['HOME'] = "/home/tests"
19
66
  end
20
67
 
21
- context 'when LIBVIRT_DEFAULT_URI is defined' do
22
- it 'should always use this value' do
23
- fake_env['LIBVIRT_DEFAULT_URI'] = "custom:///custom_path"
68
+ # table describing expected behaviour of inputs that affect the resulting uri as
69
+ # well as any subsequent settings that might be inferred if the uri was
70
+ # explicitly set.
71
+ [
72
+ # settings
73
+ [ # all default
74
+ {},
75
+ {:uri => "qemu:///system"},
76
+ ],
77
+
78
+ # explicit uri settings
79
+ [ # transport and hostname
80
+ {:uri => "qemu+ssh://localhost/system"},
81
+ {:uri => "qemu+ssh://localhost/system", :connect_via_ssh => true, :host => "localhost", :username => nil},
82
+ ],
83
+ [ # tcp transport with port
84
+ {:uri => "qemu+tcp://localhost:5000/system"},
85
+ {:uri => "qemu+tcp://localhost:5000/system", :connect_via_ssh => false, :host => "localhost", :username => nil},
86
+ ],
87
+ [ # connect explicit to unix socket
88
+ {:uri => "qemu+unix:///system"},
89
+ {:uri => "qemu+unix:///system", :connect_via_ssh => false, :host => nil, :username => nil},
90
+ ],
91
+ [ # via libssh2 should enable ssh as well
92
+ {:uri => "qemu+libssh2://user@remote/system?known_hosts=/home/user/.ssh/known_hosts"},
93
+ {
94
+ :uri => "qemu+libssh2://user@remote/system?known_hosts=/home/user/.ssh/known_hosts",
95
+ :connect_via_ssh => true, :host => "remote", :username => "user",
96
+ },
97
+ ],
98
+ [ # xen
99
+ {:uri => "xen://remote/system?no_verify=1"},
100
+ {
101
+ :uri => "xen://remote/system?no_verify=1",
102
+ :connect_via_ssh => false, :host => "remote", :username => nil,
103
+ :id_ssh_key_file => nil,
104
+ },
105
+ {
106
+ :setup => ContextualProc.new {
107
+ expect(File).to_not receive(:file?)
108
+ }
109
+ }
110
+ ],
111
+ [ # xen
112
+ {:uri => "xen+ssh://remote/system?no_verify=1"},
113
+ {
114
+ :uri => "xen+ssh://remote/system?no_verify=1",
115
+ :connect_via_ssh => true, :host => "remote", :username => nil,
116
+ :id_ssh_key_file => "/home/tests/.ssh/id_rsa",
117
+ },
118
+ {
119
+ :setup => ContextualProc.new {
120
+ expect(File).to receive(:file?).with("/home/tests/.ssh/id_rsa").and_return(true)
121
+ }
122
+ }
123
+ ],
124
+
125
+ # with LIBVIRT_DEFAULT_URI
126
+ [ # all other set to default
127
+ {},
128
+ {:uri => "custom:///custom_path", :qemu_use_session => false},
129
+ {
130
+ :env => {'LIBVIRT_DEFAULT_URI' => "custom:///custom_path"},
131
+ }
132
+ ],
133
+ [ # with session
134
+ {},
135
+ {:uri => "qemu:///session", :qemu_use_session => true},
136
+ {
137
+ :env => {'LIBVIRT_DEFAULT_URI' => "qemu:///session"},
138
+ }
139
+ ],
140
+ [ # with session and using ssh infer connect by ssh and ignore host as not provided
141
+ {},
142
+ {:uri => "qemu+ssh:///session", :qemu_use_session => true, :connect_via_ssh => true, :host => nil},
143
+ {
144
+ :env => {'LIBVIRT_DEFAULT_URI' => "qemu+ssh:///session"},
145
+ }
146
+ ],
147
+ [ # with session and using ssh to specific host with additional query options provided, infer host and ssh
148
+ {},
149
+ {:uri => "qemu+ssh://remote/session?keyfile=my_id_rsa", :qemu_use_session => true, :connect_via_ssh => true, :host => 'remote'},
150
+ {
151
+ :env => {'LIBVIRT_DEFAULT_URI' => "qemu+ssh://remote/session?keyfile=my_id_rsa"},
152
+ }
153
+ ],
154
+ [ # when session not set
155
+ {},
156
+ {:uri => "qemu:///system", :qemu_use_session => false},
157
+ {
158
+ :env => {'LIBVIRT_DEFAULT_URI' => "qemu:///system"},
159
+ }
160
+ ],
161
+ [ # when session appearing elsewhere
162
+ {},
163
+ {:uri => "qemu://remote/system?keyfile=my_session_id", :qemu_use_session => false},
164
+ {
165
+ :env => {'LIBVIRT_DEFAULT_URI' => "qemu://remote/system?keyfile=my_session_id"},
166
+ }
167
+ ],
168
+
169
+ # ignore LIBVIRT_DEFAULT_URI due to explicit settings
170
+ [ # when uri explicitly set
171
+ {:uri => 'qemu:///system'},
172
+ {:uri => 'qemu:///system'},
173
+ {
174
+ :env => {'LIBVIRT_DEFAULT_URI' => 'qemu://session'},
175
+ }
176
+ ],
177
+ [ # when host explicitly set
178
+ {:host => 'remote'},
179
+ {:uri => 'qemu://remote/system'},
180
+ {
181
+ :env => {'LIBVIRT_DEFAULT_URI' => 'qemu://session'},
182
+ }
183
+ ],
184
+ [ # when connect_via_ssh explicitly set
185
+ {:connect_via_ssh => true},
186
+ {:uri => 'qemu+ssh://localhost/system?no_verify=1'},
187
+ {
188
+ :env => {'LIBVIRT_DEFAULT_URI' => 'qemu://session'},
189
+ }
190
+ ],
191
+ [ # when username explicitly set without ssh
192
+ {:username => 'my_user' },
193
+ {:uri => 'qemu:///system'},
194
+ {
195
+ :env => {'LIBVIRT_DEFAULT_URI' => 'qemu://session'},
196
+ }
197
+ ],
198
+ [ # when username explicitly set with host but without ssh
199
+ {:username => 'my_user', :host => 'remote'},
200
+ {:uri => 'qemu://remote/system'},
201
+ {
202
+ :env => {'LIBVIRT_DEFAULT_URI' => 'qemu://session'},
203
+ }
204
+ ],
205
+ [ # when password explicitly set
206
+ {:password => 'some_password'},
207
+ {:uri => 'qemu:///system', :password => 'some_password'},
208
+ {
209
+ :env => {'LIBVIRT_DEFAULT_URI' => 'qemu://session'},
210
+ }
211
+ ],
212
+
213
+ # driver settings
214
+ [ # set to kvm only
215
+ {:driver => 'kvm'},
216
+ {:uri => "qemu:///system"},
217
+ ],
218
+ [ # set to qemu only
219
+ {:driver => 'qemu'},
220
+ {:uri => "qemu:///system"},
221
+ ],
222
+ [ # set to qemu with session enabled
223
+ {:driver => 'qemu', :qemu_use_session => true},
224
+ {:uri => "qemu:///session"},
225
+ ],
226
+ [ # set to openvz only
227
+ {:driver => 'openvz'},
228
+ {:uri => "openvz:///system"},
229
+ ],
230
+ [ # set to esx
231
+ {:driver => 'esx'},
232
+ {:uri => "esx:///"},
233
+ ],
234
+ [ # set to vbox only
235
+ {:driver => 'vbox'},
236
+ {:uri => "vbox:///session"},
237
+ ],
238
+
239
+ # connect_via_ssh settings
240
+ [ # enabled
241
+ {:connect_via_ssh => true},
242
+ {:uri => "qemu+ssh://localhost/system?no_verify=1"},
243
+ ],
244
+ [ # enabled with user
245
+ {:connect_via_ssh => true, :username => 'my_user'},
246
+ {:uri => "qemu+ssh://my_user@localhost/system?no_verify=1"},
247
+ ],
248
+ [ # enabled with host
249
+ {:connect_via_ssh => true, :host => 'remote_server'},
250
+ {:uri => "qemu+ssh://remote_server/system?no_verify=1"},
251
+ ],
252
+
253
+ # id_ssh_key_file behaviour
254
+ [ # set should take given value
255
+ {:connect_via_ssh => true, :id_ssh_key_file => '/path/to/keyfile'},
256
+ {:uri => 'qemu+ssh://localhost/system?no_verify=1&keyfile=/path/to/keyfile', :connect_via_ssh => true},
257
+ ],
258
+ [ # set should infer use of ssh
259
+ {:id_ssh_key_file => '/path/to/keyfile'},
260
+ {:uri => 'qemu+ssh://localhost/system?no_verify=1&keyfile=/path/to/keyfile', :connect_via_ssh => true},
261
+ ],
262
+ [ # connect_via_ssh should enable default but ignore due to not existing
263
+ {:connect_via_ssh => true},
264
+ {:uri => 'qemu+ssh://localhost/system?no_verify=1', :id_ssh_key_file => nil},
265
+ {
266
+ :setup => ContextualProc.new {
267
+ expect(File).to receive(:file?).with("/home/tests/.ssh/id_rsa").and_return(false)
268
+ }
269
+ }
270
+ ],
271
+ [ # connect_via_ssh should enable default and include due to existing
272
+ {:connect_via_ssh => true},
273
+ {:uri => 'qemu+ssh://localhost/system?no_verify=1&keyfile=/home/tests/.ssh/id_rsa', :id_ssh_key_file => '/home/tests/.ssh/id_rsa'},
274
+ {
275
+ :setup => ContextualProc.new {
276
+ expect(File).to receive(:file?).with("/home/tests/.ssh/id_rsa").and_return(true)
277
+ }
278
+ }
279
+ ],
280
+
281
+ # socket behaviour
282
+ [ # set
283
+ {:socket => '/var/run/libvirt/libvirt-sock'},
284
+ {:uri => "qemu:///system?socket=/var/run/libvirt/libvirt-sock"},
285
+ ],
286
+ ].each do |inputs, outputs, options|
287
+ opts = {}
288
+ opts.merge!(options) if options
289
+
290
+ it "should handle inputs #{inputs} with env (#{opts[:env]})" do
291
+ # allow some of these to fail for now if marked as such
292
+ if !opts[:allow_failure].nil?
293
+ pending(opts[:allow_failure])
294
+ end
24
295
 
25
- subject.finalize!
26
- expect(subject.uri).to eq("custom:///custom_path")
27
- expect(subject.qemu_use_session).to eq(false)
28
- end
296
+ if !opts[:setup].nil?
297
+ opts[:setup].apply(binding)
298
+ end
29
299
 
30
- context 'when LIBVIRT_DEFAULT_URI contains "qemu"' do
31
- [
32
- [
33
- 'set qemu_use_session if "session" present',
34
- 'qemu:///session',
35
- true,
36
- ],
37
- [
38
- 'handle different protocol additions',
39
- 'qemu+ssh:///session',
40
- true,
41
- ],
42
- [
43
- 'handle options before and after path',
44
- 'qemu://remote/session?keyfile=my_id_rsa',
45
- true,
46
- ],
47
- [
48
- 'identify when session not set',
49
- 'qemu://remote/system',
50
- false,
51
- ],
52
- [
53
- 'handle session appearing elsewhere',
54
- 'qemu://remote/system?keyfile=my_session_id',
55
- false,
56
- ],
57
- ].each do |title, uri, session|
58
- it "should #{title}" do
59
- fake_env['LIBVIRT_DEFAULT_URI'] = uri
60
-
61
- subject.finalize!
62
- expect(subject.uri).to eq(uri)
63
- expect(subject.qemu_use_session).to eq(session)
64
- end
300
+ inputs.each do |k, v|
301
+ subject.instance_variable_set("@#{k}", v)
65
302
  end
66
- end
67
- end
68
303
 
69
- context 'when @driver is defined' do
70
- defaults = {'id_ssh_key_file' => nil}
71
- [
72
- [
73
- {'driver' => 'kvm'},
74
- 'qemu:///system?no_verify=1',
75
- false,
76
- ],
77
- [
78
- {'driver' => 'qemu'},
79
- 'qemu:///system?no_verify=1',
80
- false,
81
- ],
82
- [
83
- {'driver' => 'qemu', 'qemu_use_session' => true},
84
- 'qemu:///session?no_verify=1',
85
- true,
86
- ],
87
- [
88
- {'driver' => 'openvz'},
89
- 'openvz:///system?no_verify=1',
90
- false,
91
- ],
92
- [
93
- {'driver' => 'vbox'},
94
- 'vbox:///session?no_verify=1',
95
- false,
96
- ],
97
- ].each do |inputs, output_uri, output_session|
98
- it "should detect #{inputs}" do
99
- inputs.merge(defaults).each do |k, v|
100
- subject.instance_variable_set("@#{k}", v)
304
+ if !opts[:env].nil?
305
+ opts[:env].each do |k, v|
306
+ fake_env[k] = v
101
307
  end
308
+ end
102
309
 
103
- subject.finalize!
104
- expect(subject.uri).to eq(output_uri)
105
- expect(subject.qemu_use_session).to eq(output_session)
310
+ subject.finalize!
311
+
312
+ # ensure failed output indicates which settings are incorrect in the failed test
313
+ got = subject.instance_variables.each_with_object({}) do |name, hash|
314
+ if outputs.key?(name.to_s[1..-1].to_sym)
315
+ hash["#{name.to_s[1..-1]}".to_sym] =subject.instance_variable_get(name)
316
+ end
106
317
  end
318
+ expect(got).to eq(outputs)
107
319
  end
320
+ end
108
321
 
322
+ context 'when invalid @driver is defined' do
109
323
  it "should raise exception for unrecognized" do
110
324
  subject.driver = "bad-driver"
111
325
 
@@ -113,65 +327,106 @@ describe VagrantPlugins::ProviderLibvirt::Config do
113
327
  end
114
328
  end
115
329
 
116
- context 'when @connect_via_ssh defined' do
117
- defaults = {'driver' => 'qemu', 'id_ssh_key_file' => nil}
118
- [
119
- [
120
- {'connect_via_ssh' => true},
121
- 'qemu+ssh://localhost/system?no_verify=1',
122
- ],
123
- [
124
- {'connect_via_ssh' => true, 'username' => 'my_user'},
125
- 'qemu+ssh://my_user@localhost/system?no_verify=1',
126
- ],
127
- [
128
- {'connect_via_ssh' => true, 'host' => 'remote_server'},
129
- 'qemu+ssh://remote_server/system?no_verify=1',
130
- ],
131
- ].each do |inputs, output_uri|
132
- it "should detect #{inputs}" do
133
- inputs.merge(defaults).each do |k, v|
134
- subject.instance_variable_set("@#{k}", v)
135
- end
330
+ context 'when invalid @uri is defined' do
331
+ it "should raise exception for unrecognized" do
332
+ subject.uri = "://bad-uri"
136
333
 
137
- subject.finalize!
138
- expect(subject.uri).to eq(output_uri)
139
- end
334
+ expect { subject.finalize! }.to raise_error("@uri set to invalid uri '://bad-uri'")
140
335
  end
141
336
  end
337
+ end
338
+
339
+ context '@proxy_command' do
340
+ before(:example) do
341
+ stub_const("ENV", fake_env)
342
+ fake_env['HOME'] = "/home/tests"
343
+ end
142
344
 
143
- context 'when @id_ssh_key_file defined' do
144
- defaults = {'driver' => 'qemu'}
345
+ [
346
+ # no connect_via_ssh
145
347
  [
146
- [
147
- {},
148
- 'qemu:///system?no_verify=1&keyfile=/home/user/.ssh/id_rsa',
149
- ],
150
- [
151
- {'id_ssh_key_file' => '/path/to/keyfile'},
152
- 'qemu:///system?no_verify=1&keyfile=/path/to/keyfile',
153
- ],
154
- ].each do |inputs, output_uri|
155
- it "should detect #{inputs}" do
156
- inputs.merge(defaults).each do |k, v|
157
- subject.instance_variable_set("@#{k}", v)
158
- end
348
+ {:host => "remote"},
349
+ nil,
350
+ ],
351
+
352
+ # connect_via_ssh
353
+ [ # host
354
+ {:connect_via_ssh => true, :host => 'remote'},
355
+ "ssh 'remote' -W %h:%p",
356
+ ],
357
+ [ # include user
358
+ {:connect_via_ssh => true, :host => 'remote', :username => 'myuser'},
359
+ "ssh 'remote' -l 'myuser' -W %h:%p",
360
+ ],
361
+ [ # include user and default ssh key exists
362
+ {:connect_via_ssh => true, :host => 'remote', :username => 'myuser'},
363
+ "ssh 'remote' -l 'myuser' -i '/home/tests/.ssh/id_rsa' -W %h:%p",
364
+ {
365
+ :setup => ContextualProc.new {
366
+ expect(File).to receive(:file?).with("/home/tests/.ssh/id_rsa").and_return(true)
367
+ }
368
+ }
369
+ ],
370
+
371
+ # disable id_ssh_key_file
372
+ [
373
+ {:connect_via_ssh => true, :host => 'remote', :id_ssh_key_file => nil},
374
+ "ssh 'remote' -W %h:%p",
375
+ ],
376
+ [ # include user
377
+ {:connect_via_ssh => true, :host => 'remote', :id_ssh_key_file => nil},
378
+ "ssh 'remote' -W %h:%p",
379
+ ],
380
+
381
+ # use @uri
382
+ [
383
+ {:uri => 'qemu+ssh://remote/system'},
384
+ "ssh 'remote' -W %h:%p",
385
+ ],
386
+ [
387
+ {:uri => 'qemu+ssh://myuser@remote/system'},
388
+ "ssh 'remote' -l 'myuser' -W %h:%p",
389
+ ],
390
+ [
391
+ {:uri => 'qemu+ssh://remote/system?keyfile=/some/path/to/keyfile'},
392
+ "ssh 'remote' -i '/some/path/to/keyfile' -W %h:%p",
393
+ {:allow_failure => "keyfile not yet inferred from uri"},
394
+ ],
159
395
 
160
- fake_env['HOME'] = '/home/user'
396
+ # provide custom template
397
+ [
398
+ {:connect_via_ssh => true, :host => 'remote', :proxy_command => "ssh {host} nc %h %p" },
399
+ "ssh remote nc %h %p",
400
+ ],
401
+ [
402
+ {:connect_via_ssh => true, :host => 'remote', :username => 'myuser', :proxy_command => "ssh {host} nc %h %p" },
403
+ "ssh remote nc %h %p",
404
+ ],
405
+ [
406
+ {:connect_via_ssh => true, :host => 'remote', :username => 'myuser', :proxy_command => "ssh {host} -l {username} nc %h %p" },
407
+ "ssh remote -l myuser nc %h %p",
408
+ ],
409
+ ].each do |inputs, proxy_command, options|
410
+ opts = {}
411
+ opts.merge!(options) if options
412
+
413
+ it "should handle inputs #{inputs}" do
414
+ # allow some of these to fail for now if marked as such
415
+ if !opts[:allow_failure].nil?
416
+ pending(opts[:allow_failure])
417
+ end
161
418
 
162
- subject.finalize!
163
- expect(subject.uri).to eq(output_uri)
419
+ if !opts[:setup].nil?
420
+ opts[:setup].apply(binding)
164
421
  end
165
- end
166
- end
167
422
 
168
- context 'when @socket defined' do
169
- it "should detect @socket set" do
170
- subject.socket = '/var/run/libvirt/libvirt-sock'
171
- subject.id_ssh_key_file = false
423
+ inputs.each do |k, v|
424
+ subject.instance_variable_set("@#{k}", v)
425
+ end
172
426
 
173
427
  subject.finalize!
174
- expect(subject.uri).to eq('qemu:///system?no_verify=1&socket=/var/run/libvirt/libvirt-sock')
428
+
429
+ expect(subject.proxy_command).to eq(proxy_command)
175
430
  end
176
431
  end
177
432
  end
@@ -282,5 +537,15 @@ describe VagrantPlugins::ProviderLibvirt::Config do
282
537
  end
283
538
  end
284
539
  end
540
+
541
+ context 'clock_timers' do
542
+ it 'should merge clock_timers' do
543
+ one.clock_timer(:name => 'rtc', :tickpolicy => 'catchup')
544
+ two.clock_timer(:name => 'hpet', :present => 'no')
545
+
546
+ expect(subject.clock_timers).to include(include(name: 'rtc'),
547
+ include(name: 'hpet'))
548
+ end
549
+ end
285
550
  end
286
551
  end