foreman_kubevirt 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eb14b9910b51e87d3bd699260b39936ecf751d2e
4
- data.tar.gz: a2ff30c7286f23678e50f1bcafc77b27abe47ab4
3
+ metadata.gz: f2ab728beaf6449390b9686a3578738848ac1da3
4
+ data.tar.gz: dc79c8e150b8d7cb02c679c9e1ffd4cf63495e0b
5
5
  SHA512:
6
- metadata.gz: 406d06d9e17c37437d133513d44e89e6c006b99510a96145895e6584080dcc7bd3ea2f7e25d024b12351bfece8d51e2b08e6253cf52e96f9c128bc4bc54d696f
7
- data.tar.gz: d16ddc90d2ad8652a71e05840fdbe605bc9ed20dccf38242bc5d767e03c814d7ba748eece054f09dbb084e2b51624b94e9a1dc95e0d1d465d3ce8a1cad35f64d
6
+ metadata.gz: 53d8317d77b47588d0b049ae083aa4e261ac4983c6a047870f4dc4eb899c77fa3b1b32d2edbe1f4e23201bec197a6c171708b9a77710fde52bf78a5805a612f9
7
+ data.tar.gz: d961f6dff0ebf22b0e8a326b08c7c20d555b9e2ce6aed4bae7e4b39c6922c512a1c3f04c2215371f55a13b461bc0d3836d5938a47e1bd65e2cb746877ef29655
@@ -1,5 +1,5 @@
1
1
  bootableRadio = function (item) {
2
- const disabled = $('[id$=_bootable_true]:disabled:checked:visible');
2
+ disabled = $('[id$=_bootable_true]:disabled:checked:visible');
3
3
 
4
4
  $('[id$=_bootable_true]').prop('checked', false);
5
5
  if (disabled.length > 0) {
@@ -10,8 +10,8 @@ bootableRadio = function (item) {
10
10
  }
11
11
 
12
12
  cniProviderSelected = function (item) {
13
- const selected = $(item).val().toLowerCase();
14
- const networks = $(item).parentsUntil('.fields').parent().find('#networks');
13
+ selected = $(item).val().toLowerCase();
14
+ networks = $(item).parentsUntil('.fields').parent().find('#networks');
15
15
 
16
16
  if (selected == "pod") {
17
17
  disableDropdown(networks);
@@ -57,7 +57,8 @@ module ForemanKubevirt
57
57
  def networks
58
58
  client.networkattachmentdefs.all
59
59
  rescue StandardError => e
60
- logger.warn("Failed to retrieve network attachments definition from KubeVirt, make sure KubeVirt has CNI provider and NetworkAttachmentDefinition CRD deployed: #{e.message}")
60
+ logger.warn("Failed to retrieve network attachments definition from KubeVirt,
61
+ make sure KubeVirt has CNI provider and NetworkAttachmentDefinition CRD deployed: #{e.message}")
61
62
  []
62
63
  end
63
64
 
@@ -130,84 +131,16 @@ module ForemanKubevirt
130
131
  # "capacity"=>"2"
131
132
  # }
132
133
  # }
133
-
134
- def verify_booting_from_image_is_possible(volumes)
135
- raise ::Foreman::Exception.new N_('It is not possible to set a bootable volume and image based provisioning.') if
136
- volumes.any? { |_, v| v["bootable"] == "true" }
137
- end
138
-
139
134
  def create_vm(args = {})
140
135
  options = vm_instance_defaults.merge(args.to_hash.deep_symbolize_keys)
141
136
  logger.debug("creating VM with the following options: #{options.inspect}")
142
- volumes = []
143
-
144
- image = args["image_id"]
145
- volumes_attributes = args["volumes_attributes"]
146
- raise ::Foreman::Exception.new N_('VM should be created based on Persistent Volume Claim or Image') unless (volumes_attributes.present? || image)
147
-
148
- # Add image as volume to the virtual machine
149
- image_provision = args["provision_method"] == "image"
150
- if image_provision
151
- verify_booting_from_image_is_possible(volumes_attributes)
152
- volume = Fog::Kubevirt::Compute::Volume.new
153
- raise ::Foreman::Exception.new N_('VM should be created based on an image') unless image
154
-
155
- volume.info = image
156
- volume.boot_order = 1
157
- volume.type = 'containerDisk'
158
- volumes << volume
159
- end
160
137
 
161
- volumes_attributes.each { |_, v| raise ::Foreman::Exception.new N_('Capacity was not found') if v["capacity"].empty? }
162
- volumes_attributes&.each_with_index do |(_, v), index|
163
- # Add PVC as volumes to the virtual machine
164
- pvc_name = options[:name].gsub(/[._]+/, '-') + "-claim-" + (index + 1).to_s
165
- capacity = v["capacity"]
166
- storage_class = v["storage_class"]
167
- bootable = v["bootable"] && !image_provision
168
-
169
- volume = create_vm_volume(pvc_name, capacity, storage_class, bootable)
170
- volumes << volume
171
- end
138
+ volumes = create_volumes_for_vm(options)
172
139
 
173
140
  # FIXME: Add cloud-init support
174
141
  # init = { 'userData' => "#!/bin/bash\necho \"fedora\" | passwd fedora --stdin"}
175
142
 
176
- interfaces = []
177
- networks = []
178
-
179
- args["interfaces_attributes"].values.each do |iface|
180
- if iface["cni_provider"] == 'pod'
181
- nic = {
182
- :bridge => {},
183
- :name => 'pod'
184
- }
185
-
186
- net = { :name => 'pod', :pod => {} }
187
- else
188
- nic = {
189
- :bridge => {},
190
- :name => iface["network"]
191
- }
192
-
193
- cni = iface["cni_provider"].to_sym
194
- net = {
195
- :name => iface["network"],
196
- cni => { :networkName => iface["network"] }
197
- }
198
- end
199
-
200
- # TODO: Consider replacing with 'free' boot order, also verify uniqueness
201
- # there is a bug with bootOrder https://bugzilla.redhat.com/show_bug.cgi?id=1687341
202
- # therefore adding to the condition not to boot from netwotk device if already asked
203
- # to boot from disk
204
- if iface["provision"] == true && volumes.select { |v| v.boot_order == 1 }.empty?
205
- nic[:bootOrder] = 1
206
- end
207
- nic[:macAddress] = iface["mac"] if iface["mac"]
208
- interfaces << nic
209
- networks << net
210
- end
143
+ interfaces, networks = create_network_devices_for_vm(options, volumes)
211
144
 
212
145
  begin
213
146
  client.vms.create(:vm_name => options[:name],
@@ -224,34 +157,6 @@ module ForemanKubevirt
224
157
  end
225
158
  end
226
159
 
227
- def create_new_pvc(pvc_name, capacity, storage_class)
228
- client.pvcs.create(:name => pvc_name,
229
- :namespace => namespace,
230
- :storage_class => storage_class,
231
- :access_modes => ['ReadWriteOnce'],
232
- :requests => { :storage => capacity + "G" })
233
- end
234
-
235
- def delete_pvcs(volumes)
236
- volumes.each do |volume|
237
- begin
238
- client.pvcs.delete(volume.info) if volume.type == "persistentVolumeClaim"
239
- rescue StandardError => e
240
- logger.error("The PVC #{volume.info} couldn't be delete due to #{e.message}")
241
- end
242
- end
243
- end
244
-
245
- def create_vm_volume(pvc_name, capacity, storage_class, bootable)
246
- create_new_pvc(pvc_name, capacity, storage_class)
247
-
248
- volume = Fog::Kubevirt::Compute::Volume.new
249
- volume.type = 'persistentVolumeClaim'
250
- volume.info = pvc_name
251
- volume.boot_order = 1 if bootable == "true"
252
- volume
253
- end
254
-
255
160
  def destroy_vm(vm_uuid)
256
161
  vm = find_vm_by_uuid(vm_uuid)
257
162
  delete_pvcs(vm.volumes)
@@ -315,11 +220,13 @@ module ForemanKubevirt
315
220
  vm_attrs = super
316
221
  interfaces = vm.interfaces || []
317
222
  vm_attrs[:interfaces_attributes] = interfaces.each_with_index.each_with_object({}) do |(interface, index), hsh|
318
- interface_attrs = {}
319
- interface_attrs[:compute_attributes] = {}
320
- interface_attrs[:mac] = interface.mac
321
- interface_attrs[:compute_attributes][:network] = interface.network
322
- interface_attrs[:compute_attributes][:cni_provider] = interface.cni_provider
223
+ interface_attrs = {
224
+ mac: interface.mac,
225
+ compute_attributes: {
226
+ network: interface.network,
227
+ cni_provider: interface.cni_provider
228
+ }
229
+ }
323
230
  hsh[index.to_s] = interface_attrs
324
231
  end
325
232
 
@@ -385,5 +292,141 @@ module ForemanKubevirt
385
292
  ca_cert
386
293
  )
387
294
  end
295
+
296
+ private
297
+
298
+ def verify_at_least_one_volume_provided(options)
299
+ image = options[:image_id]
300
+ volumes_attributes = options[:volumes_attributes]
301
+ raise ::Foreman::Exception.new N_('VM should be created based on Persistent Volume Claim or Image') unless
302
+ (volumes_attributes.present? || image)
303
+ end
304
+
305
+ def verify_booting_from_image_is_possible(volumes)
306
+ raise ::Foreman::Exception.new N_('It is not possible to set a bootable volume and image based provisioning.') if
307
+ volumes.any? { |_, v| v[:bootable] == "true" }
308
+ end
309
+
310
+ def add_volume_for_image_provision(options)
311
+ image = options[:image_id]
312
+ raise ::Foreman::Exception.new N_('VM should be created based on an image') unless image
313
+
314
+ verify_booting_from_image_is_possible(options[:volumes_attributes])
315
+
316
+ volume = Fog::Kubevirt::Compute::Volume.new
317
+ volume.info = image
318
+ volume.boot_order = 1
319
+ volume.type = 'containerDisk'
320
+ volume
321
+ end
322
+
323
+ def validate_volume_capacity(volumes_attributes)
324
+ volumes_attributes.each { |_, v| raise ::Foreman::Exception.new N_('Capacity was not found') if v[:capacity].empty? }
325
+ end
326
+
327
+ def validate_only_single_bootable_volume(volumes_attributes)
328
+ raise ::Foreman::Exception.new N_('Only one volume can be bootable') if volumes_attributes.select { |_, v| v[:bootable] == "true" }.count > 1
329
+ end
330
+
331
+ def create_new_pvc(pvc_name, capacity, storage_class)
332
+ client.pvcs.create(:name => pvc_name,
333
+ :namespace => namespace,
334
+ :storage_class => storage_class,
335
+ :access_modes => ['ReadWriteOnce'],
336
+ :requests => { :storage => capacity + "G" })
337
+ end
338
+
339
+ def delete_pvcs(volumes)
340
+ volumes.each do |volume|
341
+ begin
342
+ client.pvcs.delete(volume.info) if volume.type == "persistentVolumeClaim"
343
+ rescue StandardError => e
344
+ logger.error("The PVC #{volume.info} couldn't be delete due to #{e.message}")
345
+ end
346
+ end
347
+ end
348
+
349
+ def create_vm_volume(pvc_name, capacity, storage_class, bootable)
350
+ create_new_pvc(pvc_name, capacity, storage_class)
351
+
352
+ volume = Fog::Kubevirt::Compute::Volume.new
353
+ volume.type = 'persistentVolumeClaim'
354
+ volume.info = pvc_name
355
+ volume.boot_order = 1 if bootable == "true"
356
+ volume
357
+ end
358
+
359
+ def add_volumes_based_on_pvcs(options, image_provision)
360
+ volumes_attributes = options[:volumes_attributes]
361
+ return [] if volumes_attributes.blank?
362
+
363
+ validate_volume_capacity(volumes_attributes)
364
+ validate_only_single_bootable_volume(volumes_attributes)
365
+
366
+ volumes = []
367
+ vm_name = options[:name].gsub(/[._]+/, '-')
368
+ volumes_attributes.each_with_index do |(_, v), index|
369
+ # Add PVC as volumes to the virtual machine
370
+ pvc_name = vm_name + "-claim-" + (index + 1).to_s
371
+ capacity = v[:capacity]
372
+ storage_class = v[:storage_class]
373
+ bootable = v[:bootable] && !image_provision
374
+
375
+ volume = create_vm_volume(pvc_name, capacity, storage_class, bootable)
376
+ volumes << volume
377
+ end
378
+
379
+ volumes
380
+ end
381
+
382
+ # Creates volume elements for the VM based on provided parameters
383
+ #
384
+ # @param options[Hash] contains VM creation parameters
385
+ #
386
+ def create_volumes_for_vm(options)
387
+ verify_at_least_one_volume_provided(options)
388
+
389
+ # Add image as volume to the virtual machine
390
+ volumes = []
391
+ image_provision = options[:provision_method] == "image"
392
+
393
+ volumes << add_volume_for_image_provision(options) if image_provision
394
+ volumes.concat(add_volumes_based_on_pvcs(options, image_provision))
395
+ end
396
+
397
+ def create_pod_network_element
398
+ nic = { bridge: {}, name: 'pod' }
399
+ net = { name: 'pod', pod: {} }
400
+ [nic, net]
401
+ end
402
+
403
+ def create_network_element(iface)
404
+ nic = { bridge: {}, name: iface[:network] }
405
+ cni = iface[:cni_provider].to_sym
406
+ net = { :name => iface[:network], cni => { :networkName => iface[:network] } }
407
+ [nic, net]
408
+ end
409
+
410
+ def create_network_devices_for_vm(options, volumes)
411
+ interfaces = []
412
+ networks = []
413
+
414
+ options[:interfaces_attributes].values.each do |iface|
415
+ if iface[:cni_provider] == 'pod'
416
+ nic, net = create_pod_network_element
417
+ else
418
+ nic, net = create_network_element(iface)
419
+ end
420
+
421
+ if iface[:provision] == true && volumes.select { |v| v.boot_order == 1 }.empty?
422
+ nic[:bootOrder] = 1
423
+ end
424
+ nic[:macAddress] = iface[:mac] if iface[:mac]
425
+ interfaces << nic
426
+ networks << net
427
+ end
428
+
429
+ [interfaces, networks]
430
+ end
388
431
  end
389
432
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanKubevirt
2
- VERSION = '0.1.1'.freeze
2
+ VERSION = '0.1.2'.freeze
3
3
  end
@@ -19,11 +19,42 @@ class ForemanKubevirtTest < ActiveSupport::TestCase
19
19
 
20
20
  require 'kubeclient'
21
21
 
22
- test "create_vm network based" do
23
- vm_args = { "cpu_cores" => "1", "memory" => "1073741824", "start" => "1", "volumes_attributes" => { "1554559479978" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "1", "bootable" => "true" }, "1554559483803" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "2" } }, "name" => "robin-rykert.example.com", "provision_method" => "build", "firmware_type" => :bios, "interfaces_attributes" => { "0" => { "cni_provider" => "multus", "network" => "ovs-foreman", "ip" => "192.168.111.193", "mac" => "a2:b4:a2:b6:a2:a8", "provision" => true } } }
22
+ NETWORK_BASED_VM_ARGS = {
23
+ "cpu_cores" => "1",
24
+ "memory" => "1073741824",
25
+ "start" => "1",
26
+ "volumes_attributes" => {
27
+ "0" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "1", "bootable" => "true" },
28
+ "1" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "2" }
29
+ },
30
+ "name" => "robin-rykert.example.com",
31
+ "provision_method" => "build",
32
+ "firmware_type" => :bios,
33
+ "interfaces_attributes" => {
34
+ "0" => { "cni_provider" => "multus", "network" => "ovs-foreman", "ip" => "192.168.111.193", "mac" => "a2:b4:a2:b6:a2:a8", "provision" => true }
35
+ }
36
+ }.freeze
37
+
38
+ IMAGE_BASED_VM_ARGS = {
39
+ "cpu_cores" => "1",
40
+ "memory" => "1073741824",
41
+ "start" => "1",
42
+ "volumes_attributes" => {
43
+ "0" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "1", "bootable" => "false" }
44
+ },
45
+ "image_id" => "kubevirt/fedora-cloud-registry-disk-demo",
46
+ "name" => "olive-kempter.example.com",
47
+ "provision_method" => "image",
48
+ "firmware_type" => :bios,
49
+ "interfaces_attributes" => {
50
+ "0" => { "cni_provider" => "multus", "network" => "ovs-foreman", "ip" => "192.168.111.184", "mac" => "a2:a4:a2:b2:a2:b6", "provision" => true }
51
+ }
52
+ }.freeze
53
+
54
+ test "create_vm network based should pass" do
24
55
  Fog.mock!
25
56
  compute_resource = new_kubevirt_vcr
26
- server = compute_resource.create_vm(vm_args)
57
+ server = compute_resource.create_vm(NETWORK_BASED_VM_ARGS)
27
58
 
28
59
  assert_equal "robin-rykert.example.com", server.name
29
60
  assert_equal 2, server.volumes.count
@@ -31,11 +62,10 @@ class ForemanKubevirtTest < ActiveSupport::TestCase
31
62
  assert_equal 1, server.interfaces.count
32
63
  end
33
64
 
34
- test "create_vm image based" do
35
- vm_args = { "cpu_cores" => "1", "memory" => "1073741824", "start" => "1", "volumes_attributes" => { "1554649143334" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "1", "bootable" => "false" } }, "image_id" => "kubevirt/fedora-cloud-registry-disk-demo", "name" => "olive-kempter.example.com", "provision_method" => "image", "firmware_type" => :bios, "interfaces_attributes" => { "0" => { "cni_provider" => "multus", "network" => "ovs-foreman", "ip" => "192.168.111.184", "mac" => "a2:a4:a2:b2:a2:b6", "provision" => true } } }
65
+ test "create_vm image based should pass" do
36
66
  Fog.mock!
37
67
  compute_resource = new_kubevirt_vcr
38
- server = compute_resource.create_vm(vm_args)
68
+ server = compute_resource.create_vm(IMAGE_BASED_VM_ARGS)
39
69
 
40
70
  assert_equal "olive-kempter.example.com", server.name
41
71
  assert_equal 2, server.volumes.count
@@ -44,7 +74,18 @@ class ForemanKubevirtTest < ActiveSupport::TestCase
44
74
  end
45
75
 
46
76
  test "should fail when creating a VM with_bootable flag and image based" do
47
- vm_args = { "cpu_cores" => "1", "memory" => "1073741824", "start" => "1", "volumes_attributes" => { "1554649143334" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "1", "bootable" => "true" } }, "image_id" => "kubevirt/fedora-cloud-registry-disk-demo", "name" => "olive-kempter.example.com", "provision_method" => "image", "firmware_type" => :bios, "interfaces_attributes" => { "0" => { "cni_provider" => "multus", "network" => "ovs-foreman", "ip" => "192.168.111.184", "mac" => "a2:a4:a2:b2:a2:b6", "provision" => true } } }
77
+ vm_args = IMAGE_BASED_VM_ARGS.deep_dup
78
+ vm_args["volumes_attributes"]["0"]["bootable"] = "true"
79
+ Fog.mock!
80
+ compute_resource = new_kubevirt_vcr
81
+ assert_raise(Foreman::Exception) do
82
+ compute_resource.create_vm(vm_args)
83
+ end
84
+ end
85
+
86
+ test "should fail when creating a VM without an image or pvc" do
87
+ vm_args = IMAGE_BASED_VM_ARGS.deep_dup
88
+ vm_args["image_id"] = nil
48
89
  Fog.mock!
49
90
  compute_resource = new_kubevirt_vcr
50
91
  assert_raise(Foreman::Exception) do
@@ -52,8 +93,10 @@ class ForemanKubevirtTest < ActiveSupport::TestCase
52
93
  end
53
94
  end
54
95
 
55
- test "should fail when creating a VM without an image or pvc " do
56
- vm_args = { "cpu_cores" => "1", "memory" => "1073741824", "start" => "1", "volumes_attributes" => {}, "name" => "olive-kempter.example.com", "provision_method" => "image", "firmware_type" => :bios, "interfaces_attributes" => { "0" => { "cni_provider" => "multus", "network" => "ovs-foreman", "ip" => "192.168.111.184", "mac" => "a2:a4:a2:b2:a2:b6", "provision" => true } } }
96
+ test "should fail when creating image-based VM without an image" do
97
+ vm_args = IMAGE_BASED_VM_ARGS.deep_dup
98
+ vm_args["volumes_attributes"] = {}
99
+ vm_args["image_id"] = nil
57
100
  Fog.mock!
58
101
  compute_resource = new_kubevirt_vcr
59
102
  assert_raise(Foreman::Exception) do
@@ -62,7 +105,19 @@ class ForemanKubevirtTest < ActiveSupport::TestCase
62
105
  end
63
106
 
64
107
  test "should fail when creating a VM with PVC and not providing a capacity" do
65
- vm_args = { "cpu_cores" => "1", "memory" => "1073741824", "start" => "1", "volumes_attributes" => { "1554649143334" => { "_delete" => "", "storage_class" => "local-storage", "bootable" => "false" } }, "image_id" => "kubevirt/fedora-cloud-registry-disk-demo", "name" => "olive-kempter.example.com", "provision_method" => "image", "firmware_type" => :bios, "interfaces_attributes" => { "0" => { "cni_provider" => "multus", "network" => "ovs-foreman", "ip" => "192.168.111.184", "mac" => "a2:a4:a2:b2:a2:b6", "provision" => true } } }
108
+ vm_args = NETWORK_BASED_VM_ARGS.deep_dup
109
+ vm_args["volumes_attributes"]["0"]["capacity"] = nil
110
+ Fog.mock!
111
+ compute_resource = new_kubevirt_vcr
112
+ assert_raise(Foreman::Exception) do
113
+ compute_resource.create_vm(vm_args)
114
+ end
115
+ end
116
+
117
+ test "should fail when creating a VM with two bootable PVCs" do
118
+ vm_args = NETWORK_BASED_VM_ARGS.deep_dup
119
+ vm_args["volumes_attributes"]["0"]["bootable"] = "true"
120
+ vm_args["volumes_attributes"]["1"]["bootable"] = "true"
66
121
  Fog.mock!
67
122
  compute_resource = new_kubevirt_vcr
68
123
  assert_raise(Foreman::Exception) do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_kubevirt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moti Asayag
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-24 00:00:00.000000000 Z
11
+ date: 2019-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -96,7 +96,7 @@ files:
96
96
  - test/unit/foreman_kubevirt_test.rb
97
97
  homepage: https://github.com/theforeman/foreman_kubevirt
98
98
  licenses:
99
- - GPLv3
99
+ - GPL-3.0
100
100
  metadata: {}
101
101
  post_install_message:
102
102
  rdoc_options: []