From d9e318be609b79f0f4495936a4ad4d14f35ba0ab Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Thu, 22 Jan 2026 08:48:19 +0100 Subject: [PATCH 1/7] simplify create_vm mocking --- .../models/compute_resources/kubevirt_test.rb | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/test/models/compute_resources/kubevirt_test.rb b/test/models/compute_resources/kubevirt_test.rb index 5f89bff..3c9aa25 100644 --- a/test/models/compute_resources/kubevirt_test.rb +++ b/test/models/compute_resources/kubevirt_test.rb @@ -9,6 +9,20 @@ def new_kubevirt_vcr ::FactoryBot.build(:compute_resource_kubevirt) end + def mocked_client + vms = stub + pvcs = stub + pvcs.stubs(:create) + pvcs.stubs(:delete) + servers = stub + servers.stubs(:get) + client = stub + client.stubs(:vms).returns(vms) + client.stubs(:pvcs).returns(pvcs) + client.stubs(:servers).returns(servers) + client + end + test "host_interfaces_attrs" do record = new_kubevirt_vcr host = ::FactoryBot.build(:host_kubevirt, :with_interfaces) @@ -23,23 +37,17 @@ def new_kubevirt_vcr describe "create_vm" do test "uses sanitized NIC names" do - vms = stub - pvcs = stub - pvcs.stubs(:create) - pvcs.stubs(:delete) - servers = stub - servers.stubs(:get) - client = stub - client.stubs(:vms).returns(vms) - client.stubs(:pvcs).returns(pvcs) - client.stubs(:servers).returns(servers) record = new_kubevirt_vcr + client = mocked_client record.stubs(:client).returns(client) expected_networks = [{ :name => "default-network", :multus => { :networkName => "default/network" } }] expected_interfaces = [{ :bridge => {}, :name => "default-network" }] - vms.expects(:create).with(vm_name: anything, cpus: anything, memory_size: anything, memory_unit: anything, volumes: anything, cloudinit: anything, networks: expected_networks, interfaces: expected_interfaces) + client.vms.expects(:create).with do |args| + assert_equal expected_networks, args[:networks] + assert_equal expected_interfaces, args[:interfaces] + end record.create_vm({ :name => "test", :volumes_attributes => { 0 => { :capacity => "5" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) end From eb54a9cd63ff4aeb63ed4b835d43ad9293718fd0 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Thu, 22 Jan 2026 08:49:39 +0100 Subject: [PATCH 2/7] use dataVolumeTemplates to create image based hosts --- app/models/foreman_kubevirt/kubevirt.rb | 34 +++++++++++++++++-- .../models/compute_resources/kubevirt_test.rb | 26 ++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/app/models/foreman_kubevirt/kubevirt.rb b/app/models/foreman_kubevirt/kubevirt.rb index 001b0cf..8afbd7f 100644 --- a/app/models/foreman_kubevirt/kubevirt.rb +++ b/app/models/foreman_kubevirt/kubevirt.rb @@ -183,13 +183,14 @@ def create_vm(args = {}) user_data = { "userData" => options[:user_data] } if options[:user_data].present? begin - volumes = create_volumes_for_vm(options) + volumes, volume_templates = create_volumes_for_vm(options) interfaces, networks = create_network_devices_for_vm(options, volumes) client.vms.create(:vm_name => options[:name], :cpus => options[:cpu_cores].to_i, :memory_size => convert_memory(options[:memory] + "b", :mi).to_s, :memory_unit => "Mi", :volumes => volumes, + :volume_templates => volume_templates, :cloudinit => user_data, :networks => networks, :interfaces => interfaces) @@ -388,12 +389,34 @@ def add_volume_for_image_provision(options) verify_booting_from_image_is_possible(options[:volumes_attributes]) volume = Fog::Kubevirt::Compute::Volume.new - volume.info = image + volume.config = { name: rootdisk_name(options) } volume.boot_order = 1 - volume.type = 'containerDisk' + volume.name = 'rootdisk' + volume.type = 'dataVolume' volume end + def add_volume_template_for_image_provision(options) + image = options[:image_id] + raise ::Foreman::Exception.new _('VM should be created based on an image') unless image + + namespace, name = image.split('/', 2) + if name.nil? + name = namespace + namespace = nil + end + + source_ref = { kind: 'DataSource', name: name, namespace: namespace }.compact + storage = { resources: { requests: { storage: nil } } } + metadata = { name: rootdisk_name(options) } + { kind: 'DataVolume', metadata: metadata, spec: { sourceRef: source_ref, storage: storage } } + end + + def rootdisk_name(options) + vm_name = options[:name].parameterize + "#{vm_name}-root" + end + def validate_volume_capacity(volumes_attributes) volumes_attributes.each do |_, vol| if vol[:capacity].to_s.empty? || /\A\d+G?\Z/.match(vol[:capacity].to_s).nil? @@ -465,10 +488,15 @@ def create_volumes_for_vm(options) # Add image as volume to the virtual machine volumes = [] + volume_templates = [] image_provision = options[:provision_method] == "image" volumes << add_volume_for_image_provision(options) if image_provision volumes.concat(add_volumes_based_on_pvcs(options, image_provision)) + + volume_templates << add_volume_template_for_image_provision(options) if image_provision + + [volumes, volume_templates] end def create_pod_network_element diff --git a/test/models/compute_resources/kubevirt_test.rb b/test/models/compute_resources/kubevirt_test.rb index 3c9aa25..f510063 100644 --- a/test/models/compute_resources/kubevirt_test.rb +++ b/test/models/compute_resources/kubevirt_test.rb @@ -51,6 +51,32 @@ def mocked_client record.create_vm({ :name => "test", :volumes_attributes => { 0 => { :capacity => "5" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) end + + test "uses dataVolume for image based provisioning" do + record = new_kubevirt_vcr + client = mocked_client + record.stubs(:client).returns(client) + + client.vms.expects(:create).with do |args| + assert_equal 1, args[:volumes].length + assert_equal 1, args[:volume_templates].length + + volume = args[:volumes].first + assert_equal 'dataVolume', volume.type + assert_equal 'test-root', volume.config[:name] + assert_equal 'rootdisk', volume.name + assert_equal 1, volume.boot_order + + volume_template = args[:volume_templates].first + assert_equal 'DataVolume', volume_template[:kind] + assert_equal 'test-root', volume_template[:metadata][:name] + assert_equal 'DataSource', volume_template[:spec][:sourceRef][:kind] + assert_equal 'default', volume_template[:spec][:sourceRef][:namespace] + assert_equal 'template', volume_template[:spec][:sourceRef][:name] + end + + record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => {}, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) + end end describe "create_network_element" do From 799b83f60d6c5da836ab07388ffd05061f358f74 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Fri, 23 Jan 2026 08:48:03 +0100 Subject: [PATCH 3/7] take first boot volume for the template if any --- app/models/foreman_kubevirt/kubevirt.rb | 26 ++++---- .../models/compute_resources/kubevirt_test.rb | 62 ++++++++++++++++++- test/unit/foreman_kubevirt_test.rb | 11 ---- 3 files changed, 76 insertions(+), 23 deletions(-) diff --git a/app/models/foreman_kubevirt/kubevirt.rb b/app/models/foreman_kubevirt/kubevirt.rb index 8afbd7f..208e7c5 100644 --- a/app/models/foreman_kubevirt/kubevirt.rb +++ b/app/models/foreman_kubevirt/kubevirt.rb @@ -377,17 +377,7 @@ def verify_at_least_one_volume_provided(options) (volumes_attributes.present? || image) end - def verify_booting_from_image_is_possible(volumes) - raise ::Foreman::Exception.new _('It is not possible to set a bootable volume and image based provisioning.') if - volumes&.any? { |_, v| v[:bootable] == "true" } - end - def add_volume_for_image_provision(options) - image = options[:image_id] - raise ::Foreman::Exception.new _('VM should be created based on an image') unless image - - verify_booting_from_image_is_possible(options[:volumes_attributes]) - volume = Fog::Kubevirt::Compute::Volume.new volume.config = { name: rootdisk_name(options) } volume.boot_order = 1 @@ -406,8 +396,20 @@ def add_volume_template_for_image_provision(options) namespace = nil end - source_ref = { kind: 'DataSource', name: name, namespace: namespace }.compact storage = { resources: { requests: { storage: nil } } } + volumes_attributes = options[:volumes_attributes] + if volumes_attributes.present? + _, boot_volume = volumes_attributes.find { |_, vol| vol[:bootable] == 'true' } + if boot_volume + capacity = boot_volume[:capacity] + capacity += "G" unless capacity.end_with? "G" + storage_class = boot_volume[:storage_class] + storage[:resources][:requests][:storage] = capacity + storage[:storageClassName] = storage_class if storage_class.present? + end + end + + source_ref = { kind: 'DataSource', name: name, namespace: namespace }.compact metadata = { name: rootdisk_name(options) } { kind: 'DataVolume', metadata: metadata, spec: { sourceRef: source_ref, storage: storage } } end @@ -466,6 +468,8 @@ def add_volumes_based_on_pvcs(options, image_provision) volumes = [] vm_name = options[:name].gsub(/[._]+/, '-') volumes_attributes.each_with_index do |(_, v), index| + # skip if this is a boot volume for image provisioning + next if image_provision && v[:bootable] # Add PVC as volumes to the virtual machine pvc_name = vm_name + "-claim-" + (index + 1).to_s capacity = v[:capacity] diff --git a/test/models/compute_resources/kubevirt_test.rb b/test/models/compute_resources/kubevirt_test.rb index f510063..1bfca79 100644 --- a/test/models/compute_resources/kubevirt_test.rb +++ b/test/models/compute_resources/kubevirt_test.rb @@ -52,7 +52,7 @@ def mocked_client record.create_vm({ :name => "test", :volumes_attributes => { 0 => { :capacity => "5" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) end - test "uses dataVolume for image based provisioning" do + test "uses dataVolume for image based provisioning without an explicit boot volume" do record = new_kubevirt_vcr client = mocked_client record.stubs(:client).returns(client) @@ -73,10 +73,70 @@ def mocked_client assert_equal 'DataSource', volume_template[:spec][:sourceRef][:kind] assert_equal 'default', volume_template[:spec][:sourceRef][:namespace] assert_equal 'template', volume_template[:spec][:sourceRef][:name] + assert_nil volume_template[:spec][:storage][:resources][:requests][:storage] end record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => {}, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) end + + test "uses dataVolume for image based provisioning with an explicit boot volume" do + record = new_kubevirt_vcr + client = mocked_client + record.stubs(:client).returns(client) + + client.vms.expects(:create).with do |args| + assert_equal 1, args[:volumes].length + assert_equal 1, args[:volume_templates].length + + volume = args[:volumes].first + assert_equal 'dataVolume', volume.type + assert_equal 'test-root', volume.config[:name] + assert_equal 'rootdisk', volume.name + assert_equal 1, volume.boot_order + + volume_template = args[:volume_templates].first + assert_equal 'DataVolume', volume_template[:kind] + assert_equal 'test-root', volume_template[:metadata][:name] + assert_equal 'DataSource', volume_template[:spec][:sourceRef][:kind] + assert_equal 'default', volume_template[:spec][:sourceRef][:namespace] + assert_equal 'template', volume_template[:spec][:sourceRef][:name] + assert_equal '10G', volume_template[:spec][:storage][:resources][:requests][:storage] + end + + record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => { "0" => { :capacity => "10", :bootable => "true" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) + end + + test "uses dataVolume for image based provisioning with an extra data volume" do + record = new_kubevirt_vcr + client = mocked_client + record.stubs(:client).returns(client) + + client.vms.expects(:create).with do |args| + assert_equal 2, args[:volumes].length + assert_equal 1, args[:volume_templates].length + + boot_volume = args[:volumes].first + assert_equal 'dataVolume', boot_volume.type + assert_equal 'test-root', boot_volume.config[:name] + assert_equal 'rootdisk', boot_volume.name + assert_equal 1, boot_volume.boot_order + + data_volume = args[:volumes].last + assert_equal 'persistentVolumeClaim', data_volume.type + assert_equal 'test-claim-1', data_volume.info + assert_nil data_volume.boot_order + + volume_template = args[:volume_templates].first + assert_equal 'DataVolume', volume_template[:kind] + assert_equal 'test-root', volume_template[:metadata][:name] + assert_equal 'DataSource', volume_template[:spec][:sourceRef][:kind] + assert_equal 'default', volume_template[:spec][:sourceRef][:namespace] + assert_equal 'template', volume_template[:spec][:sourceRef][:name] + assert_nil volume_template[:spec][:storage][:resources][:requests][:storage] + end + + record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => { "0" => { :capacity => "10" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) + end end describe "create_network_element" do diff --git a/test/unit/foreman_kubevirt_test.rb b/test/unit/foreman_kubevirt_test.rb index e56e64a..8243800 100644 --- a/test/unit/foreman_kubevirt_test.rb +++ b/test/unit/foreman_kubevirt_test.rb @@ -84,17 +84,6 @@ def new_kubevirt_vcr assert_equal "olive-kempter.example.com", server.name end - test "should fail when creating a VM with_bootable flag and image based" do - vm_args = IMAGE_BASED_VM_ARGS.deep_dup - vm_args["volumes_attributes"]["0"]["bootable"] = "true" - Fog.mock! - compute_resource = new_kubevirt_vcr - exception = assert_raise(Foreman::Exception) do - compute_resource.create_vm(vm_args) - end - assert_match(/It is not possible to set a bootable volume and image based provisioning./, exception.message) - end - test "should fail when creating a VM without an image or pvc" do vm_args = IMAGE_BASED_VM_ARGS.deep_dup vm_args["volumes_attributes"] = {} From 43f58ef86da03d1c7d34122d86c135a0af0ec912 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Thu, 29 Jan 2026 10:03:40 +0100 Subject: [PATCH 4/7] require a bootable volume for image provisioning --- app/models/foreman_kubevirt/kubevirt.rb | 20 +++---- .../models/compute_resources/kubevirt_test.rb | 57 +++---------------- test/unit/foreman_kubevirt_test.rb | 11 ++-- 3 files changed, 22 insertions(+), 66 deletions(-) diff --git a/app/models/foreman_kubevirt/kubevirt.rb b/app/models/foreman_kubevirt/kubevirt.rb index 208e7c5..6802e59 100644 --- a/app/models/foreman_kubevirt/kubevirt.rb +++ b/app/models/foreman_kubevirt/kubevirt.rb @@ -396,18 +396,14 @@ def add_volume_template_for_image_provision(options) namespace = nil end - storage = { resources: { requests: { storage: nil } } } - volumes_attributes = options[:volumes_attributes] - if volumes_attributes.present? - _, boot_volume = volumes_attributes.find { |_, vol| vol[:bootable] == 'true' } - if boot_volume - capacity = boot_volume[:capacity] - capacity += "G" unless capacity.end_with? "G" - storage_class = boot_volume[:storage_class] - storage[:resources][:requests][:storage] = capacity - storage[:storageClassName] = storage_class if storage_class.present? - end - end + volumes_attributes = options.fetch(:volumes_attributes, {}) + _, boot_volume = volumes_attributes.find { |_, vol| vol[:bootable] == 'true' } + raise ::Foreman::Exception.new _('A bootable volume is required as a target for the image') unless boot_volume + capacity = boot_volume[:capacity] + capacity += "G" unless capacity.end_with? "G" + storage_class = boot_volume[:storage_class] + storage = { resources: { requests: { storage: capacity } } } + storage[:storageClassName] = storage_class if storage_class.present? source_ref = { kind: 'DataSource', name: name, namespace: namespace }.compact metadata = { name: rootdisk_name(options) } diff --git a/test/models/compute_resources/kubevirt_test.rb b/test/models/compute_resources/kubevirt_test.rb index 1bfca79..b43ce3c 100644 --- a/test/models/compute_resources/kubevirt_test.rb +++ b/test/models/compute_resources/kubevirt_test.rb @@ -52,31 +52,13 @@ def mocked_client record.create_vm({ :name => "test", :volumes_attributes => { 0 => { :capacity => "5" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) end - test "uses dataVolume for image based provisioning without an explicit boot volume" do + test "raises an error for image based provisioning without an explicit boot volume" do record = new_kubevirt_vcr - client = mocked_client - record.stubs(:client).returns(client) - client.vms.expects(:create).with do |args| - assert_equal 1, args[:volumes].length - assert_equal 1, args[:volume_templates].length - - volume = args[:volumes].first - assert_equal 'dataVolume', volume.type - assert_equal 'test-root', volume.config[:name] - assert_equal 'rootdisk', volume.name - assert_equal 1, volume.boot_order - - volume_template = args[:volume_templates].first - assert_equal 'DataVolume', volume_template[:kind] - assert_equal 'test-root', volume_template[:metadata][:name] - assert_equal 'DataSource', volume_template[:spec][:sourceRef][:kind] - assert_equal 'default', volume_template[:spec][:sourceRef][:namespace] - assert_equal 'template', volume_template[:spec][:sourceRef][:name] - assert_nil volume_template[:spec][:storage][:resources][:requests][:storage] + error = assert_raises(Foreman::Exception) do + record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => {}, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) end - - record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => {}, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) + assert_match(/A bootable volume is required as a target for the image/, error.message) end test "uses dataVolume for image based provisioning with an explicit boot volume" do @@ -106,36 +88,13 @@ def mocked_client record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => { "0" => { :capacity => "10", :bootable => "true" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) end - test "uses dataVolume for image based provisioning with an extra data volume" do + test "raises an error for image based provisioning with only an extra data volume" do record = new_kubevirt_vcr - client = mocked_client - record.stubs(:client).returns(client) - - client.vms.expects(:create).with do |args| - assert_equal 2, args[:volumes].length - assert_equal 1, args[:volume_templates].length - - boot_volume = args[:volumes].first - assert_equal 'dataVolume', boot_volume.type - assert_equal 'test-root', boot_volume.config[:name] - assert_equal 'rootdisk', boot_volume.name - assert_equal 1, boot_volume.boot_order - data_volume = args[:volumes].last - assert_equal 'persistentVolumeClaim', data_volume.type - assert_equal 'test-claim-1', data_volume.info - assert_nil data_volume.boot_order - - volume_template = args[:volume_templates].first - assert_equal 'DataVolume', volume_template[:kind] - assert_equal 'test-root', volume_template[:metadata][:name] - assert_equal 'DataSource', volume_template[:spec][:sourceRef][:kind] - assert_equal 'default', volume_template[:spec][:sourceRef][:namespace] - assert_equal 'template', volume_template[:spec][:sourceRef][:name] - assert_nil volume_template[:spec][:storage][:resources][:requests][:storage] + error = assert_raises(Foreman::Exception) do + record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => { "0" => { :capacity => "10" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) end - - record.create_vm({ :name => "test", :provision_method => 'image', :image_id => "default/template", :volumes_attributes => { "0" => { :capacity => "10" } }, :interfaces_attributes => { "0" => { "cni_provider" => "multus", "network" => "default/network" } } }) + assert_match(/A bootable volume is required as a target for the image/, error.message) end end diff --git a/test/unit/foreman_kubevirt_test.rb b/test/unit/foreman_kubevirt_test.rb index 8243800..5e0c22e 100644 --- a/test/unit/foreman_kubevirt_test.rb +++ b/test/unit/foreman_kubevirt_test.rb @@ -40,7 +40,7 @@ def new_kubevirt_vcr "memory" => "1073741824", "start" => "1", "volumes_attributes" => { - "0" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "1", "bootable" => "false" } + "0" => { "_delete" => "", "storage_class" => "local-storage", "capacity" => "1", "bootable" => "true" } }, "image_id" => "kubevirt/fedora-cloud-registry-disk-demo", "name" => "olive-kempter.example.com", @@ -73,15 +73,16 @@ def new_kubevirt_vcr assert_equal 1, server.interfaces.count end - test "create_vm image based without additional volumes should pass" do + test "create_vm image based without additional volumes should fail" do vm_args = IMAGE_BASED_VM_ARGS.deep_dup vm_args.delete("volumes_attributes") Fog.mock! compute_resource = new_kubevirt_vcr - server = compute_resource.create_vm(vm_args) - - assert_equal "olive-kempter.example.com", server.name + exception = assert_raise(Foreman::Exception) do + compute_resource.create_vm(vm_args) + end + assert_match(/A bootable volume is required as a target for the image/, exception.message) end test "should fail when creating a VM without an image or pvc" do From 20b3aaea72f19102e4378bd6cad573af308937da Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Tue, 3 Feb 2026 07:51:39 +0100 Subject: [PATCH 5/7] Require fog-kubevirt 1.6.0+ for volume_templates support --- foreman_kubevirt.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foreman_kubevirt.gemspec b/foreman_kubevirt.gemspec index b10bb0c..0526ee4 100644 --- a/foreman_kubevirt.gemspec +++ b/foreman_kubevirt.gemspec @@ -15,5 +15,5 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 2.5', '< 4.0' - s.add_dependency('fog-kubevirt', '>= 1.5.1', '< 2') + s.add_dependency('fog-kubevirt', '>= 1.6.0', '< 2') end From abfd1c72438197857ce7ffa719df683cb002c32b Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Tue, 3 Feb 2026 10:41:18 +0100 Subject: [PATCH 6/7] update image help --- app/views/images/form/_kubevirt.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/images/form/_kubevirt.html.erb b/app/views/images/form/_kubevirt.html.erb index da3279f..8145cd6 100644 --- a/app/views/images/form/_kubevirt.html.erb +++ b/app/views/images/form/_kubevirt.html.erb @@ -1,4 +1,4 @@ <%= text_f f, :username, :value => @image.username || "root", :help_inline => _("The user that is used to ssh into the instance, normally cloud-user, ec2-user, ubuntu, root etc") %> <%= password_f f, :password, :help_inline => _("Password to authenticate with - used for SSH finish step.") %> <%= checkbox_f f, :user_data, :help_inline => _("Does this image support user data input (e.g. via cloud-init)?") %> -<%= image_field(f, :label => _("Image"), :help_inline => _("The name of the image in the registry.")) %> +<%= image_field(f, :label => _("Image"), :help_inline => _("The name of the DataSource that contains the image. Use namespace/name notation to use a DataSource in a different namespace.")) %> From ee62ff1005afe5e6e83202895597f40aab8e3429 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Tue, 3 Feb 2026 13:12:09 +0100 Subject: [PATCH 7/7] add default volume --- app/models/foreman_kubevirt/kubevirt.rb | 3 ++- test/models/compute_resources/kubevirt_test.rb | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/foreman_kubevirt/kubevirt.rb b/app/models/foreman_kubevirt/kubevirt.rb index 6802e59..34934c5 100644 --- a/app/models/foreman_kubevirt/kubevirt.rb +++ b/app/models/foreman_kubevirt/kubevirt.rb @@ -222,7 +222,8 @@ def host_compute_attrs(host) def vm_instance_defaults { :memory => 1024.megabytes.to_s, - :cpu_cores => '1' + :cpu_cores => '1', + :volumes => [new_volume].compact, } end diff --git a/test/models/compute_resources/kubevirt_test.rb b/test/models/compute_resources/kubevirt_test.rb index b43ce3c..72ba7a3 100644 --- a/test/models/compute_resources/kubevirt_test.rb +++ b/test/models/compute_resources/kubevirt_test.rb @@ -16,10 +16,13 @@ def mocked_client pvcs.stubs(:delete) servers = stub servers.stubs(:get) + storageclasses = stub + storageclasses.stubs(:all).returns([{ 'name': 'local' }]) client = stub client.stubs(:vms).returns(vms) client.stubs(:pvcs).returns(pvcs) client.stubs(:servers).returns(servers) + client.stubs(:storageclasses).returns(storageclasses) client end