foreman_ovirt 2.0.2 → 2.0.4

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -17
  3. data/app/assets/javascripts/foreman_ovirt/ovirt.js +37 -8
  4. data/app/controllers/concerns/foreman_ovirt/api_compute_resources_controller_extension.rb +42 -0
  5. data/app/controllers/concerns/foreman_ovirt/compute_resources_vms_controller.rb +3 -1
  6. data/app/controllers/concerns/foreman_ovirt/parameters_extension.rb +5 -5
  7. data/app/controllers/foreman_ovirt/concerns/compute_resources_controller_extensions.rb +12 -3
  8. data/app/helpers/ovirt_compute_resource_helper.rb +18 -4
  9. data/app/models/concerns/fog_extensions/ovirt/server.rb +13 -4
  10. data/app/models/concerns/fog_extensions/ovirt/template.rb +3 -1
  11. data/app/models/concerns/fog_extensions/ovirt/volume.rb +3 -1
  12. data/app/models/foreman_ovirt/ovirt.rb +167 -142
  13. data/app/views/api/v2/compute_resources/ovirt.json.rabl +2 -0
  14. data/config/routes.rb +8 -5
  15. data/db/migrate/20250810212811_update_legacy_ovirt_compute_resource_type.rb +5 -3
  16. data/lib/foreman_ovirt/engine.rb +8 -5
  17. data/lib/foreman_ovirt/version.rb +3 -1
  18. data/lib/foreman_ovirt.rb +2 -0
  19. data/lib/tasks/foreman_ovirt_tasks.rake +37 -22
  20. data/locale/gemspec.rb +3 -1
  21. data/package.json +1 -0
  22. data/test/controllers/api/v2/compute_resources_controller_test.rb +186 -0
  23. data/test/controllers/hosts_controller_test.rb +46 -0
  24. data/test/factories/foreman_ovirt_factories.rb +27 -2
  25. data/test/fixtures/ovirt_operating_systems.xml +243 -0
  26. data/test/graphql/types/provider_enum_test.rb +12 -0
  27. data/test/integration/compute_profile_js_test.rb +49 -0
  28. data/test/models/compute_resources/compute_resource_test_helpers.rb +143 -0
  29. data/test/models/compute_resources/ovirt_test.rb +687 -0
  30. data/test/models/ovirt_volume_test.rb +104 -0
  31. data/test/test_plugin_helper.rb +2 -0
  32. data/test/unit/compute_resource_host_importer_test.rb +48 -0
  33. data/test/unit/ovirt_connection_test.rb +123 -0
  34. data/webpack/components/__tests__/ovirt.test.js +17 -0
  35. data/webpack/components/extensions/HostDetails/DetailsTabCards/OvirtCard.js +40 -38
  36. data/webpack/global_index.js +0 -2
  37. data/webpack/global_test_setup.js +3 -3
  38. data/webpack/index.js +0 -1
  39. metadata +26 -8
  40. data/test/unit/foreman_ovirt_test.rb +0 -11
@@ -0,0 +1,687 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+ require 'models/compute_resources/compute_resource_test_helpers'
5
+
6
+ module ForemanOvirt
7
+ class OvirtTest < ActiveSupport::TestCase
8
+ def setup
9
+ @klass = ForemanOvirt::Ovirt
10
+ end
11
+ include ComputeResourceTestHelpers
12
+
13
+ should validate_presence_of(:url)
14
+ should validate_presence_of(:user)
15
+ should validate_presence_of(:password)
16
+ should allow_values(
17
+ 'http://foo.com', 'http://bar.com/baz'
18
+ ).for(:url)
19
+ should_not allow_values(
20
+ 'ftp://foo.com', 'buz'
21
+ ).for(:url)
22
+
23
+ test '#associated_host matches any NIC' do
24
+ host = FactoryBot.create(
25
+ :host, mac: 'ca:d0:e6:32:16:97'
26
+ )
27
+ cr = FactoryBot.build_stubbed(:ovirt_cr)
28
+ iface1 = mock(
29
+ 'iface1', mac: '36:48:c5:c9:86:f2'
30
+ )
31
+ iface2 = mock(
32
+ 'iface2', mac: 'ca:d0:e6:32:16:97'
33
+ )
34
+ vm = mock(
35
+ 'vm', interfaces: [
36
+ iface1, iface2
37
+ ]
38
+ )
39
+ assert_equal(host, as_admin do
40
+ cr.associated_host(vm)
41
+ end)
42
+ end
43
+
44
+ test '#associated_host matches NIC mac with uppercase letters' do
45
+ host = FactoryBot.create(
46
+ :host, mac: 'ca:d0:e6:32:16:97'
47
+ )
48
+ cr = FactoryBot.build_stubbed(:ovirt_cr)
49
+ iface1 = mock(
50
+ 'iface1', mac: '36:48:c5:c9:86:f2'
51
+ )
52
+ iface2 = mock(
53
+ 'iface2', mac: 'CA:D0:E6:32:16:97'
54
+ )
55
+ vm = mock(
56
+ 'vm', interfaces: [
57
+ iface1, iface2
58
+ ]
59
+ )
60
+ assert_equal(host, as_admin do
61
+ cr.associated_host(vm)
62
+ end)
63
+ end
64
+
65
+ describe 'destroy_vm' do
66
+ it 'handles situation when vm is not present' do
67
+ cr = mock_cr_servers(
68
+ ForemanOvirt::Ovirt.new, empty_servers
69
+ )
70
+ cr.expects(:find_vm_by_uuid).raises(ActiveRecord::RecordNotFound)
71
+ assert cr.destroy_vm('abc')
72
+ end
73
+ end
74
+
75
+ describe 'find_vm_by_uuid' do
76
+ it 'raises RecordNotFound when the vm does not exist' do
77
+ cr = mock_cr_servers(
78
+ ForemanOvirt::Ovirt.new, empty_servers
79
+ )
80
+ assert_find_by_uuid_raises(
81
+ ActiveRecord::RecordNotFound, cr
82
+ )
83
+ end
84
+
85
+ it 'raises RecordNotFound when the compute raises retrieve error' do
86
+ exception = Fog::Ovirt::Errors::OvirtEngineError.new(StandardError.new('VM not found'))
87
+ cr = mock_cr_servers(
88
+ ForemanOvirt::Ovirt.new, servers_raising_exception(exception)
89
+ )
90
+ assert_find_by_uuid_raises(
91
+ ActiveRecord::RecordNotFound, cr
92
+ )
93
+ end
94
+ end
95
+
96
+ describe 'associating operating system' do
97
+ require 'fog/ovirt/models/compute/operating_system'
98
+
99
+ setup do
100
+ # This calculates the path relative to this file, so it works everywhere (CI, local, etc.)
101
+ fixtures_path = ForemanOvirt::Engine.root.join('test', 'fixtures', 'ovirt_operating_systems.xml')
102
+ operating_systems_xml = Nokogiri::XML(File.read(fixtures_path))
103
+ @ovirt_oses = operating_systems_xml.xpath('/operating_systems/operating_system').map do |os|
104
+ Fog::Ovirt::Compute::OperatingSystem.new({
105
+ id: os[:id], name: (os / 'name').text, href: os[:href]
106
+ })
107
+ end
108
+ @os_hashes = @ovirt_oses.map do |ovirt_os|
109
+ {
110
+ id: ovirt_os.id, name: ovirt_os.name, href: ovirt_os.href
111
+ }
112
+ end
113
+ @compute_resource = FactoryBot.build(:ovirt_cr)
114
+ @compute_resource.attrs[:available_operating_systems] =
115
+ @os_hashes
116
+ @host = FactoryBot.build(
117
+ :host, mac: 'ca:d0:e6:32:16:97'
118
+ )
119
+ @quota = Fog::Ovirt::Compute::Quota.new({
120
+ id: '1', name: 'Default'
121
+ })
122
+ end
123
+
124
+ it 'maps operating system to ovirt operating systems' do
125
+ @compute_resource.stubs(:available_operating_systems).returns(@os_hashes)
126
+ assert_equal 'other_linux',
127
+ @compute_resource.determine_os_type(@host)
128
+
129
+ @host.operatingsystem = operatingsystems(:redhat)
130
+ assert_equal 'rhel_6',
131
+ @compute_resource.determine_os_type(@host)
132
+
133
+ @host.architecture = architectures(:x86_64) # rubocop:disable Naming/VariableNumber
134
+ assert_equal 'rhel_6x64',
135
+ @compute_resource.determine_os_type(@host)
136
+
137
+ @host.operatingsystem = operatingsystems(:ubuntu1210)
138
+ assert_equal 'ubuntu_12_10',
139
+ @compute_resource.determine_os_type(@host)
140
+
141
+ @host.operatingsystem = FactoryBot.create(:operatingsystem)
142
+ assert_equal 'other',
143
+ @compute_resource.determine_os_type(@host)
144
+ end
145
+
146
+ it 'respects host param ovirt_ostype' do
147
+ @compute_resource.stubs(:available_operating_systems).returns(@os_hashes)
148
+ @host.stubs(:params).returns({ 'ovirt_ostype' => 'some_os' })
149
+ assert_equal 'some_os',
150
+ @compute_resource.determine_os_type(@host)
151
+ end
152
+
153
+ it 'caches the operating systems in the compute resource' do
154
+ client_mock = mock.tap do |m|
155
+ m.stubs(:operating_systems).returns(@ovirt_oses)
156
+ end
157
+ @compute_resource.stubs(:client).returns(client_mock)
158
+ client_mock.stubs(:quotas).returns([@quota])
159
+ assert @compute_resource.supports_operating_systems?
160
+ assert_equal @os_hashes,
161
+ @compute_resource.available_operating_systems
162
+ end
163
+
164
+ it 'handles a case when the operating systems endpoint is missing' do
165
+ @compute_resource.attrs.delete(:available_operating_systems)
166
+ client_mock = mock.tap do |m|
167
+ m.stubs(:operating_systems).raises(
168
+ Fog::Ovirt::Errors::OvirtEngineError, StandardError.new('404')
169
+ )
170
+ end
171
+ @compute_resource.stubs(:client).returns(client_mock)
172
+ client_mock.stubs(:quotas).returns([@quota])
173
+ assert_not @compute_resource.supports_operating_systems?
174
+ end
175
+ end
176
+
177
+ describe 'APIv4 support' do
178
+ require 'fog/ovirt/models/compute/quota'
179
+
180
+ before do
181
+ @compute_resource = FactoryBot.build(:ovirt_cr)
182
+ @quota = Fog::Ovirt::Compute::Quota.new({
183
+ id: '1', name: 'Default'
184
+ })
185
+ @client_mock = mock.tap do |m|
186
+ m.stubs(
187
+ datacenters: [], quotas: [@quota]
188
+ )
189
+ end
190
+ end
191
+
192
+ it 'passes api_version v4 by default' do
193
+ Fog::Compute.expects(:new).with do |options|
194
+ assert_equal 'v4',
195
+ options[:api_version]
196
+ end.returns(@client_mock)
197
+ @compute_resource.send(:client)
198
+ end
199
+ end
200
+
201
+ describe 'quota validation and name-id substitution' do
202
+ require 'fog/ovirt/models/compute/quota'
203
+
204
+ before do
205
+ @compute_resource = FactoryBot.build(:ovirt_cr)
206
+ @quota = Fog::Ovirt::Compute::Quota.new({
207
+ id: '1', name: 'Default'
208
+ })
209
+ @client_mock = mock.tap do |m|
210
+ m.stubs(
211
+ datacenters: [], quotas: [@quota]
212
+ )
213
+ end
214
+ @compute_resource.stubs(:client).returns(@client_mock)
215
+ end
216
+
217
+ test 'quota validation - id entered' do
218
+ @compute_resource.ovirt_quota = '1'
219
+ assert_equal(
220
+ '1', @compute_resource.validate_quota
221
+ )
222
+ end
223
+
224
+ test 'quota validation - name entered' do
225
+ @compute_resource.ovirt_quota = 'Default'
226
+ assert_equal(
227
+ '1', @compute_resource.validate_quota
228
+ )
229
+ end
230
+
231
+ test 'quota validation - nothing entered' do
232
+ assert_equal(
233
+ '1', @compute_resource.validate_quota
234
+ )
235
+ end
236
+
237
+ test 'quota validation - name entered' do
238
+ @compute_resource.ovirt_quota = 'Default2'
239
+ assert_raise Foreman::Exception do
240
+ @compute_resource.validate_quota
241
+ end
242
+ end
243
+ end
244
+
245
+ describe 'name-id substitution for attributes: network, storage_domain and cluster' do
246
+ let(:cr) do
247
+ mock_cr(FactoryBot.build(:ovirt_cr),
248
+ clusters: [
249
+ stub(
250
+ id: 'c1', name: 'cluster 1'
251
+ ),
252
+ stub(
253
+ id: 'c2', name: 'cluster 2'
254
+ ),
255
+ ],
256
+ networks: [
257
+ stub(
258
+ id: 'net1', name: 'network 1'
259
+ ),
260
+ stub(
261
+ id: 'net2', name: 'network 2'
262
+ ),
263
+ ],
264
+ storage_domains: [
265
+ stub(
266
+ id: '312f6', name: 'domain 1'
267
+ ),
268
+ stub(
269
+ id: '382ec', name: 'domain 2'
270
+ ),
271
+ ])
272
+ end
273
+
274
+ test 'cluster validation - id entered' do
275
+ assert_equal(
276
+ 'c2', cr.get_ovirt_id(
277
+ cr.clusters, 'cluster', 'c2'
278
+ )
279
+ )
280
+ end
281
+
282
+ test 'cluster validation - name entered' do
283
+ assert_equal(
284
+ 'c2', cr.get_ovirt_id(
285
+ cr.clusters, 'cluster', 'cluster 2'
286
+ )
287
+ )
288
+ end
289
+
290
+ test 'cluster validation - not valid' do
291
+ assert_raise Foreman::Exception do
292
+ cr.get_ovirt_id(
293
+ cr.clusters, 'cluster', 'c3'
294
+ )
295
+ end
296
+ end
297
+
298
+ test 'storage domain validation - id entered' do
299
+ assert_equal(
300
+ '312f6', cr.get_ovirt_id(
301
+ cr.storage_domains, 'storage domain', '312f6'
302
+ )
303
+ )
304
+ end
305
+
306
+ test 'storage domain validation - name entered' do
307
+ assert_equal(
308
+ '382ec', cr.get_ovirt_id(
309
+ cr.storage_domains, 'storage domain', 'domain 2'
310
+ )
311
+ )
312
+ end
313
+
314
+ test 'storage domain validation - not valid' do
315
+ assert_raise Foreman::Exception do
316
+ cr.get_ovirt_id(
317
+ cr.storage_domains, 'storage domain', 'domain 3'
318
+ )
319
+ end
320
+ end
321
+
322
+ test 'network validation - id entered' do
323
+ assert_equal(
324
+ 'net1', cr.get_ovirt_id(
325
+ cr.networks, 'network', 'net1'
326
+ )
327
+ )
328
+ end
329
+
330
+ test 'network validation - name entered' do
331
+ assert_equal(
332
+ 'net2', cr.get_ovirt_id(
333
+ cr.networks, 'network', 'network 2'
334
+ )
335
+ )
336
+ end
337
+
338
+ test 'network validation - not valid' do
339
+ assert_raise Foreman::Exception do
340
+ cr.get_ovirt_id(
341
+ cr.networks, 'network', 'network 3'
342
+ )
343
+ end
344
+ end
345
+ end
346
+
347
+ describe '#normalize_vm_attrs' do
348
+ let(:cr) do
349
+ mock_cr(FactoryBot.build(:ovirt_cr),
350
+ clusters: [
351
+ stub(
352
+ id: 'c1', name: 'cluster 1'
353
+ ),
354
+ stub(
355
+ id: 'c2', name: 'cluster 2'
356
+ ),
357
+ ],
358
+ templates: [
359
+ stub(
360
+ id: 'tpl1', name: 'template 1'
361
+ ),
362
+ stub(
363
+ id: 'tpl2', name: 'template 2'
364
+ ),
365
+ ],
366
+ networks: [
367
+ stub(
368
+ id: 'net1', name: 'network 1'
369
+ ),
370
+ stub(
371
+ id: 'net2', name: 'network 2'
372
+ ),
373
+ ],
374
+ storage_domains: [
375
+ stub(
376
+ id: '312f6', name: 'domain 1'
377
+ ),
378
+ stub(
379
+ id: '382ec', name: 'domain 2'
380
+ ),
381
+ stub(
382
+ id: '3ea4f', name: 'domain 3'
383
+ ),
384
+ ])
385
+ end
386
+
387
+ test 'maps cluster to cluster_id' do
388
+ vm_attrs = {
389
+ 'cluster' => 'cluster 1',
390
+ }
391
+ normalized = cr.normalize_vm_attrs(vm_attrs)
392
+
393
+ assert_not(normalized.key?('cluster'))
394
+ assert_equal(
395
+ 'c1', normalized['cluster_id']
396
+ )
397
+ end
398
+
399
+ test 'finds cluster_name' do
400
+ vm_attrs = {
401
+ 'cluster' => 'c2',
402
+ }
403
+ normalized = cr.normalize_vm_attrs(vm_attrs)
404
+
405
+ assert_equal(
406
+ 'cluster 2', normalized['cluster_name']
407
+ )
408
+ end
409
+
410
+ test 'maps template to template_id' do
411
+ vm_attrs = {
412
+ 'template' => 'template 1',
413
+ }
414
+ normalized = cr.normalize_vm_attrs(vm_attrs)
415
+
416
+ assert_not(normalized.key?('template'))
417
+ assert_equal(
418
+ 'tpl1', normalized['template_id']
419
+ )
420
+ end
421
+
422
+ test 'finds template_name' do
423
+ vm_attrs = {
424
+ 'template' => 'tpl2',
425
+ }
426
+ normalized = cr.normalize_vm_attrs(vm_attrs)
427
+
428
+ assert_equal(
429
+ 'template 2', normalized['template_name']
430
+ )
431
+ end
432
+
433
+ test 'normalizes interfaces_attributes' do
434
+ vm_attrs = {
435
+ 'interfaces_attributes' => {
436
+ '0' => {
437
+ 'name' => 'eth0',
438
+ 'network' => 'net1',
439
+ },
440
+ '1' => {
441
+ 'name' => 'eth1',
442
+ 'network' => 'net2',
443
+ },
444
+ },
445
+ }
446
+ expected_attrs = {
447
+ '0' => {
448
+ 'network_id' => 'net1',
449
+ 'network_name' => 'network 1',
450
+ 'name' => 'eth0',
451
+ },
452
+ '1' => {
453
+ 'network_id' => 'net2',
454
+ 'network_name' => 'network 2',
455
+ 'name' => 'eth1',
456
+ },
457
+ }
458
+ normalized = cr.normalize_vm_attrs(vm_attrs)
459
+
460
+ assert_equal(
461
+ expected_attrs, normalized['interfaces_attributes']
462
+ )
463
+ end
464
+
465
+ test 'normalizes volumes_attributes' do
466
+ vm_attrs = {
467
+ 'volumes_attributes' => {
468
+ '0' => {
469
+ 'size_gb' => '15',
470
+ 'storage_domain' => '312f6',
471
+ 'id' => '',
472
+ 'preallocate' => '0',
473
+ },
474
+ '1' => {
475
+ 'size_gb' => '5',
476
+ 'storage_domain' => '382ec',
477
+ 'id' => '',
478
+ 'preallocate' => '1',
479
+ 'bootable' => 'true',
480
+ },
481
+ },
482
+ }
483
+ expected_attrs = {
484
+ '0' => {
485
+ 'size' => 15.gigabyte.to_s,
486
+ 'storage_domain_id' => '312f6',
487
+ 'storage_domain_name' => 'domain 1',
488
+ 'preallocate' => false,
489
+ 'bootable' => nil,
490
+ },
491
+ '1' => {
492
+ 'size' => 5.gigabyte.to_s,
493
+ 'storage_domain_id' => '382ec',
494
+ 'storage_domain_name' => 'domain 2',
495
+ 'preallocate' => true,
496
+ 'bootable' => true,
497
+ },
498
+ }
499
+ normalized = cr.normalize_vm_attrs(vm_attrs)
500
+
501
+ assert_equal(
502
+ expected_attrs, normalized['volumes_attributes']
503
+ )
504
+ end
505
+
506
+ test 'correctly fills empty attributes' do
507
+ normalized = cr.normalize_vm_attrs({})
508
+ expected_attrs = {
509
+ 'cores' => nil,
510
+ 'memory' => nil,
511
+ 'cluster_id' => nil,
512
+ 'cluster_name' => nil,
513
+ 'template_id' => nil,
514
+ 'template_name' => nil,
515
+ 'interfaces_attributes' => {},
516
+ 'volumes_attributes' => {},
517
+ }
518
+
519
+ assert_equal(
520
+ expected_attrs.keys.sort, normalized.keys.sort
521
+ )
522
+ assert_equal(
523
+ expected_attrs, normalized
524
+ )
525
+ end
526
+
527
+ test 'attribute names' do
528
+ check_vm_attribute_names(cr)
529
+ end
530
+ end
531
+
532
+ describe '#display_type' do
533
+ let(:cr) do
534
+ FactoryBot.build_stubbed(:ovirt_cr)
535
+ end
536
+
537
+ test "default display type is 'vnc'" do
538
+ assert_nil cr.attrs[:display]
539
+ assert_equal 'vnc',
540
+ cr.display_type
541
+ end
542
+
543
+ test 'display type can be set' do
544
+ expected = 'spice'
545
+ cr.display_type = 'Spice'
546
+ assert_equal expected,
547
+ cr.attrs[:display]
548
+ assert_equal expected,
549
+ cr.display_type
550
+ assert cr.valid?
551
+ end
552
+
553
+ test "don't allow wrong display type to be set" do
554
+ cr.display_type = 'teletype'
555
+ assert_not cr.valid?
556
+ end
557
+ end
558
+
559
+ describe '#keyboard_layout' do
560
+ let(:cr) do
561
+ FactoryBot.build_stubbed(:ovirt_cr)
562
+ end
563
+
564
+ test "default keyboard layout is 'en-us'" do
565
+ assert_nil cr.attrs[:keyboard_layout]
566
+ assert_equal 'en-us',
567
+ cr.keyboard_layout
568
+ end
569
+
570
+ test 'keyboard layout can be set' do
571
+ expected = 'hu'
572
+ cr.keyboard_layout = 'hu'
573
+ assert_equal expected,
574
+ cr.attrs[:keyboard_layout]
575
+ assert_equal expected,
576
+ cr.keyboard_layout
577
+ assert cr.valid?
578
+ end
579
+
580
+ test "don't allow wrong keyboard layout to be set" do
581
+ cr.keyboard_layout = 'fake-layout'
582
+ assert_not cr.valid?
583
+ end
584
+ end
585
+
586
+ describe '#vm_compute_attributes_for' do
587
+ require 'fog/ovirt/models/compute/volume'
588
+
589
+ before do
590
+ @plain_attrs = {
591
+ id: 'abc',
592
+ cpus: 5,
593
+ }
594
+ @vm = mock
595
+ @vm.stubs(:attributes).returns(@plain_attrs)
596
+
597
+ @cr = FactoryBot.build(:ovirt_cr)
598
+ @cr.stubs(:find_vm_by_uuid).returns(@vm)
599
+ end
600
+
601
+ test 'returns vm attributes with oVirt-specific volume attributes' do
602
+ # oVirt uses different volume attributes than libvirt
603
+ volume1 = Fog::Ovirt::Compute::Volume.new(
604
+ storage_domain: 'storage1',
605
+ size_gb: '1',
606
+ bootable: 'false',
607
+ sparse: 'true',
608
+ wipe_after_delete: 'true',
609
+ name: 'disk1'
610
+ )
611
+ volume2 = Fog::Ovirt::Compute::Volume.new(
612
+ storage_domain: 'storage2',
613
+ size_gb: '2',
614
+ bootable: 'false',
615
+ sparse: 'true',
616
+ wipe_after_delete: 'true',
617
+ name: 'disk2'
618
+ )
619
+
620
+ @vm.stubs(:volumes).returns([volume1, volume2])
621
+
622
+ expected_attrs = {
623
+ cpus: 5,
624
+ volumes_attributes: {
625
+ '0' => {
626
+ size_gb: '1',
627
+ storage_domain: 'storage1',
628
+ preallocate: '0',
629
+ wipe_after_delete: 'true',
630
+ interface: nil,
631
+ bootable: 'false',
632
+ id: nil,
633
+ },
634
+ '1' => {
635
+ size_gb: '2',
636
+ storage_domain: 'storage2',
637
+ preallocate: '0',
638
+ wipe_after_delete: 'true',
639
+ interface: nil,
640
+ bootable: 'false',
641
+ id: nil,
642
+ },
643
+ },
644
+ }
645
+
646
+ attrs = @cr.vm_compute_attributes_for('abc')
647
+ assert_equal expected_attrs, attrs
648
+ end
649
+
650
+ test 'handles oVirt volumes with bootable flag' do
651
+ volume1 = Fog::Ovirt::Compute::Volume.new(
652
+ storage_domain: 'storage1',
653
+ size_gb: '1',
654
+ bootable: 'true',
655
+ sparse: 'true',
656
+ wipe_after_delete: 'false',
657
+ name: 'boot_disk'
658
+ )
659
+
660
+ @vm.stubs(:volumes).returns([volume1])
661
+
662
+ attrs = @cr.vm_compute_attributes_for('abc')
663
+ assert_equal 'true', attrs[:volumes_attributes]['0'][:bootable]
664
+ assert_equal 'false', attrs[:volumes_attributes]['0'][:wipe_after_delete]
665
+ end
666
+ end
667
+
668
+ describe '#get_datacenter_uuid' do
669
+ test 'resolves datacenter name from datacenters list' do
670
+ uuid = Foreman.uuid
671
+ cr = FactoryBot.build(:ovirt_cr)
672
+ cr.stubs(:datacenters).returns([
673
+ ['prod', uuid],
674
+ ['dev', Foreman.uuid],
675
+ ])
676
+ assert_equal uuid, cr.get_datacenter_uuid('prod')
677
+ end
678
+
679
+ test 'raises when datacenter is unknown' do
680
+ cr = FactoryBot.build(:ovirt_cr)
681
+ cr.stubs(:datacenters).returns([['dev', Foreman.uuid]])
682
+ error = assert_raise(Foreman::Exception) { cr.get_datacenter_uuid('prod') }
683
+ assert_match(/Datacenter was not found/, error.message)
684
+ end
685
+ end
686
+ end
687
+ end