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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37ec9e7c41d481b180a6da281a873fc0cad4955c00947354617a4b147cce8f92
4
- data.tar.gz: bb294b1fda5082c78ccb23267209c06c7ab4bc394ee255a0e26a733bf2ac0881
3
+ metadata.gz: 265b540a1760c3b80a0ada6c75748d6d70b01d58cfa769e45ddb320fac93f5c5
4
+ data.tar.gz: c7faf208698abeac35635409c83d14d87e7f0c40cdf8854c1456ec0750bcff04
5
5
  SHA512:
6
- metadata.gz: 905a02afb9b251f55f5ed480a2a2f61c3faef247d12921b949ce775c653939d5e8f293e2281acab761773c1dd8ac78437131997925355f19b8ae8202494243e0
7
- data.tar.gz: f802eb6894065cc7ad52f53fe391dfa604ed76c69129b9291ce0f5763a70d9616fb72e78ac432763f04cfa84de64f3671a0229218f7001e50ea4078c4bd38143
6
+ metadata.gz: ad89324d644b50989e6f8817b4368b4daee16a2caae9cfdc8012fdca7668dd27a9eeac95d015d712837c2f49544efa22e6fbd3ca2a47d0b52593705ab775b82f
7
+ data.tar.gz: 8aa6f8fb851acb66cd4163b02422cd3317e0d77e3ec6c0441fb39c785e1b3ebb208d90dc174676bbffaa33d2ba572818f5b7d0f67ec661b3bfdd6ef76fc95450
data/Rakefile CHANGED
@@ -1,26 +1,11 @@
1
1
  #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
+
2
4
  begin
3
5
  require 'bundler/setup'
4
6
  rescue LoadError
5
7
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
8
  end
7
- begin
8
- require 'rdoc/task'
9
- rescue LoadError
10
- require 'rdoc/rdoc'
11
- require 'rake/rdoctask'
12
- RDoc::Task = Rake::RDocTask
13
- end
14
-
15
- RDoc::Task.new(:rdoc) do |rdoc|
16
- rdoc.rdoc_dir = 'rdoc'
17
- rdoc.title = 'ForemanOvirt'
18
- rdoc.options << '--line-numbers'
19
- rdoc.rdoc_files.include('README.rdoc')
20
- rdoc.rdoc_files.include('lib/**/*.rb')
21
- end
22
-
23
- APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
24
9
 
25
10
  Bundler::GemHelper.install_tasks
26
11
 
@@ -25,8 +25,8 @@ function templateSelected(item) {
25
25
  url,
26
26
  data: `template_id=${template}`,
27
27
  success(result) {
28
- // As Instance Type values will take precence over templates values,
29
- // we don't update memory/cores values if instance type is already selected
28
+ // As Instance Type values will take precedence over template values,
29
+ // we don't update memory/cores values if an instance type is already selected.
30
30
  if (!$('#host_compute_attributes_instance_type').val()) {
31
31
  updateCoresAndSockets(result);
32
32
  setMemoryInputProps({ value: result.memory });
@@ -61,6 +61,11 @@ function templateSelected(item) {
61
61
  function instanceTypeSelected(item) {
62
62
  const instanceType = $(item).val();
63
63
 
64
+ // Ignore empty instance type values. Select2 can fire change on init.
65
+ if (!instanceType) {
66
+ return;
67
+ }
68
+
64
69
  if (!item.disabled) {
65
70
  const url = $(item).attr('data-url');
66
71
 
@@ -138,6 +143,10 @@ function addVolume({
138
143
  .hide();
139
144
  }
140
145
 
146
+ // Update the memory FormField props and the hidden input value.
147
+ // Memory input component keeps its own internal state on mount, so changing
148
+ // reactProps alone may not update the hidden input used for form submission.
149
+ // To be safe we set reactProps and also update the hidden input directly.
141
150
  function setMemoryInputProps(props) {
142
151
  const newProps = { ...props };
143
152
 
@@ -145,13 +154,32 @@ function setMemoryInputProps(props) {
145
154
  newProps.value = parseInt(newProps.value, 10);
146
155
  }
147
156
 
148
- const memoryInputElement = getComponentByWrapperId('memory-input');
149
- memoryInputElement.reactProps = {
150
- ...memoryInputElement.reactProps,
151
- ...newProps,
152
- };
157
+ const wrapper = document.getElementById('memory-input');
158
+ if (!wrapper) return;
159
+
160
+ const element = wrapper.getElementsByTagName('foreman-react-component')[0];
161
+ if (element) {
162
+ element.reactProps = {
163
+ ...element.reactProps,
164
+ ...newProps,
165
+ };
166
+ }
167
+
168
+ // Also set the hidden input directly because the memory component keeps
169
+ // its own state and may not apply prop updates immediately.
170
+ if (newProps.value !== undefined) {
171
+ const hiddenInput = wrapper.querySelector('input[type="hidden"]');
172
+ if (hiddenInput) hiddenInput.value = newProps.value;
173
+ }
174
+
175
+ if (newProps.disabled !== undefined) {
176
+ const hiddenInput = wrapper.querySelector('input[type="hidden"]');
177
+ if (hiddenInput) hiddenInput.disabled = newProps.disabled;
178
+ }
153
179
  }
154
180
 
181
+ // Update cores and sockets FormField props from AJAX result.
182
+ // These are simple numeric fields so updating reactProps is sufficient.
155
183
  function updateCoresAndSockets(result) {
156
184
  const coresInputElement = getComponentByWrapperId('cores-input');
157
185
  coresInputElement.reactProps = {
@@ -202,6 +230,7 @@ function bootableRadio(item) {
202
230
  $(item).prop('checked', true);
203
231
  }
204
232
  }
233
+
205
234
  function clusterSelected(item) {
206
235
  const cluster = $(item).val();
207
236
  const url = $(item).data('url');
@@ -258,4 +287,4 @@ function vnicSelected(item) {
258
287
  );
259
288
  networkSelect.val(networkObj.id).trigger('change');
260
289
  }
261
- }
290
+ }
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanOvirt
4
+ module ApiComputeResourcesControllerExtension
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ # rubocop:disable Rails/LexicallyScopedActionFilter
9
+ before_action :convert_datacenter_to_uuid, only: %i[create update]
10
+ # rubocop:enable Rails/LexicallyScopedActionFilter
11
+ end
12
+
13
+ private
14
+
15
+ def convert_datacenter_to_uuid
16
+ datacenter = params[:compute_resource][:datacenter]
17
+ return if datacenter.blank? || Foreman.is_uuid?(datacenter)
18
+
19
+ case params[:action]
20
+ when 'create'
21
+ return unless compute_resource_params[:provider]&.downcase == 'ovirt'
22
+ @compute_resource = ComputeResource.new_provider(compute_resource_params.except(:datacenter))
23
+ when 'update'
24
+ return unless @compute_resource.is_a?(ForemanOvirt::Ovirt)
25
+ else
26
+ Rails.logger.error("Convert datacenter to UUID should not be called for action #{params[:action]}")
27
+ return
28
+ end
29
+
30
+ uuid = change_datacenter_to_uuid(datacenter)
31
+ params[:compute_resource][:datacenter] = uuid if uuid.present?
32
+ rescue Foreman::Exception => e
33
+ render_exception(e, status: :unprocessable_entity)
34
+ false
35
+ end
36
+
37
+ def change_datacenter_to_uuid(datacenter)
38
+ @compute_resource.test_connection
39
+ @compute_resource.get_datacenter_uuid(datacenter)
40
+ end
41
+ end
42
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanOvirt
2
4
  module ComputeResourcesVmsController
3
5
  extend ActiveSupport::Concern
@@ -19,7 +21,7 @@ module ForemanOvirt
19
21
  render partial: "compute_resources_vms/index/#{@compute_resource.provider.downcase}_json"
20
22
  else
21
23
  render json: _('JSON VM listing is not supported for this compute resource.'),
22
- status: :not_implemented
24
+ status: :not_implemented
23
25
  end
24
26
  end
25
27
  end
@@ -23,11 +23,11 @@ module ForemanOvirt
23
23
  compute_resource_params_filter_without_ovirt.tap do |filter|
24
24
  # Now, add the oVirt specific parameters to the existing filter.
25
25
  filter.permit :datacenter,
26
- :ovirt_quota,
27
- :keyboard_layout,
28
- :use_v4,
29
- :public_key,
30
- :uuid
26
+ :ovirt_quota,
27
+ :keyboard_layout,
28
+ :use_v4,
29
+ :public_key,
30
+ :uuid
31
31
  end
32
32
  end
33
33
  end
@@ -1,10 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanOvirt
2
4
  module Concerns
3
5
  module ComputeResourcesControllerExtensions
4
6
  extend ActiveSupport::Concern
5
7
 
6
8
  prepended do
7
- before_action :change_datacenter_to_uuid, only: [:create, :update]
9
+ # rubocop:disable Rails/LexicallyScopedActionFilter
10
+ before_action :change_datacenter_to_uuid, only: %i[create update]
11
+ # rubocop:enable Rails/LexicallyScopedActionFilter
8
12
  rescue_from ::ProxyAPI::Ovirt::Unauthorized, with: :render_ovirt_unauthorized_error
9
13
  end
10
14
 
@@ -38,7 +42,11 @@ module ForemanOvirt
38
42
  private
39
43
 
40
44
  def change_datacenter_to_uuid
41
- return unless params[:compute_resource] && params[:compute_resource][:provider] == 'Ovirt' && params[:compute_resource][:datacenter]
45
+ unless params[:compute_resource] &&
46
+ params[:compute_resource][:provider] == 'Ovirt' &&
47
+ params[:compute_resource][:datacenter]
48
+ return
49
+ end
42
50
  proxy = find_resource(params[:id]) if params[:id].present?
43
51
  proxy ||= ::ProxyAPI::Ovirt.new(
44
52
  url: params[:compute_resource][:url],
@@ -48,12 +56,13 @@ module ForemanOvirt
48
56
  uuid = proxy.datacenter_uuid_by_name(params[:compute_resource][:datacenter])
49
57
  params[:compute_resource][:datacenter] = uuid
50
58
  rescue ::ProxyAPI::Ovirt::Unauthorized
59
+ # Do nothing, allow the process to continue or fail elsewhere
51
60
  rescue Foreman::Exception => e
52
61
  render_error e.message, status: :not_found
53
62
  end
54
63
 
55
64
  def render_ovirt_unauthorized_error
56
- render_error "401 Unauthorized", status: :unauthorized
65
+ render_error '401 Unauthorized', status: :unauthorized
57
66
  end
58
67
  end
59
68
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OvirtComputeResourceHelper
2
4
  # Really counting vms is as expensive as loading them all, especially when
3
5
  # a filter is in place. So we create a fake count to get table pagination to work.
@@ -6,21 +8,33 @@ module OvirtComputeResourceHelper
6
8
  end
7
9
 
8
10
  def ovirt_storage_domains_for_select(compute_resource)
9
- compute_resource.storage_domains.map { |sd| OpenStruct.new({ id: sd.id, label: "#{sd.name} (" + _("Available") + ": #{sd.available.to_i / 1.gigabyte} GiB, " + _("Used") + ": #{sd.used.to_i / 1.gigabyte} GiB)" }) }
11
+ compute_resource.storage_domains.map do |sd|
12
+ avail = sd.available.to_i / 1.gigabyte
13
+ used = sd.used.to_i / 1.gigabyte
14
+ OpenStruct.new({ id: sd.id,
15
+ label: "#{sd.name} (" + _('Available') + ": #{avail} GiB, " + _('Used') + ": #{used} GiB)" })
16
+ end
10
17
  end
11
18
 
12
19
  def ovirt_vms_data
13
20
  data = @vms.map do |vm|
14
21
  [
15
- link_to_if_authorized(html_escape(vm.name), hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.id).merge(:auth_object => @compute_resource, :auth_action => 'view', :authorizer => authorizer)),
22
+ link_to_if_authorized(html_escape(vm.name),
23
+ hash_for_compute_resource_vm_path(compute_resource_id: @compute_resource, id: vm.id).merge(
24
+ auth_object: @compute_resource, auth_action: 'view', authorizer: authorizer
25
+ )),
16
26
  vm.cores,
17
27
  number_to_human_size(vm.memory),
18
28
  "<span #{vm_power_class(vm.ready?)}>#{vm_state(vm)}</span>",
19
29
  action_buttons(vm_power_action(vm, authorizer),
20
30
  vm_import_action(vm), vm_associate_link(vm),
21
- display_delete_if_authorized(hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.id).merge(:auth_object => @compute_resource, :authorizer => authorizer))),
31
+ display_delete_if_authorized(
32
+ hash_for_compute_resource_vm_path(compute_resource_id: @compute_resource, id: vm.id).merge(
33
+ auth_object: @compute_resource, authorizer: authorizer
34
+ )
35
+ )),
22
36
  ]
23
37
  end
24
- JSON.fast_generate(data).html_safe
38
+ JSON.fast_generate(data).html_safe # rubocop:disable Rails/OutputSafety
25
39
  end
26
40
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FogExtensions
2
4
  module Ovirt
3
5
  module Server
@@ -22,7 +24,7 @@ module FogExtensions
22
24
  end
23
25
 
24
26
  def poweroff
25
- service.vm_action(:id => id, :action => :shutdown)
27
+ service.vm_action(id: id, action: :shutdown)
26
28
  end
27
29
 
28
30
  def reset
@@ -30,12 +32,19 @@ module FogExtensions
30
32
  end
31
33
 
32
34
  def vm_description
33
- _("%{cores} Cores and %{memory} memory") % {:cores => cores, :memory => number_to_human_size(memory.to_i)}
35
+ format(
36
+ _('%<cores>s Cores and %<memory>s memory'), cores: cores, memory: number_to_human_size(memory.to_i)
37
+ )
34
38
  end
35
39
 
36
40
  def select_nic(fog_nics, nic)
37
- nic_network = @service.list_networks(@attributes[:cluster]).detect { |n| n.name == nic.compute_attributes['network'] }.try(:id) || nic.compute_attributes['network']
38
- fog_nics.detect { |fn| fn.network == nic_network } # grab any nic on the same network
41
+ nic_network = @service.list_networks(@attributes[:cluster]).detect do |n|
42
+ n.name == nic.compute_attributes['network']
43
+ end.try(:id) || nic.compute_attributes['network']
44
+ # grab any nic on the same network
45
+ fog_nics.detect do |fn|
46
+ fn.network == nic_network
47
+ end
39
48
  end
40
49
  end
41
50
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FogExtensions
2
4
  module Ovirt
3
5
  module Template
4
6
  def full_name
5
- version = full_version.present? ? " (#{full_version})" : ""
7
+ version = full_version.present? ? " (#{full_version})" : ''
6
8
  "#{name}#{version}"
7
9
  end
8
10
 
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FogExtensions
2
4
  module Ovirt
3
5
  module Volume
4
6
  extend ActiveSupport::Concern
5
- def as_json(options = { })
7
+ def as_json(options = {})
6
8
  size_gb
7
9
  super options
8
10
  end