foreman_ovirt 0.3.0 → 2.0.1

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 (69) hide show
  1. checksums.yaml +7 -0
  2. data/{LICENSE.txt → LICENSE} +0 -2
  3. data/README.md +140 -0
  4. data/Rakefile +37 -43
  5. data/app/assets/javascripts/foreman_ovirt/display.js +10 -0
  6. data/app/assets/javascripts/foreman_ovirt/host_edit.js +61 -0
  7. data/app/assets/javascripts/foreman_ovirt/nic_info.js +3 -0
  8. data/app/assets/javascripts/foreman_ovirt/ovirt.js +261 -0
  9. data/app/controllers/concerns/foreman_ovirt/compute_resources_vms_controller.rb +29 -0
  10. data/app/controllers/concerns/foreman_ovirt/parameters_extension.rb +35 -0
  11. data/app/controllers/foreman_ovirt/concerns/compute_resources_controller_extensions.rb +60 -0
  12. data/app/helpers/ovirt_compute_resource_helper.rb +26 -0
  13. data/app/models/concerns/fog_extensions/ovirt/server.rb +42 -0
  14. data/app/models/concerns/fog_extensions/ovirt/template.rb +14 -0
  15. data/app/models/concerns/fog_extensions/ovirt/volume.rb +11 -0
  16. data/app/models/foreman_ovirt/ovirt.rb +752 -0
  17. data/app/views/api/v2/compute_resources/ovirt.json.rabl +1 -0
  18. data/app/views/compute_resources/form/_ovirt.html.erb +14 -0
  19. data/app/views/compute_resources/show/_ovirt.html.erb +16 -0
  20. data/app/views/compute_resources_vms/form/ovirt/_base.html.erb +83 -0
  21. data/app/views/compute_resources_vms/form/ovirt/_network.html.erb +32 -0
  22. data/app/views/compute_resources_vms/form/ovirt/_volume.html.erb +16 -0
  23. data/app/views/compute_resources_vms/index/_ovirt.html.erb +12 -0
  24. data/app/views/compute_resources_vms/index/_ovirt_json.erb +6 -0
  25. data/app/views/compute_resources_vms/show/_ovirt.html.erb +55 -0
  26. data/app/views/images/form/_ovirt.html.erb +4 -0
  27. data/config/routes.rb +8 -13
  28. data/db/migrate/20250810212811_update_legacy_ovirt_compute_resource_type.rb +21 -0
  29. data/lib/foreman_ovirt/engine.rb +70 -0
  30. data/lib/foreman_ovirt/version.rb +3 -0
  31. data/lib/foreman_ovirt.rb +2 -1
  32. data/lib/tasks/foreman_ovirt_tasks.rake +30 -0
  33. data/locale/Makefile +73 -0
  34. data/locale/en/foreman_ovirt.po +19 -0
  35. data/locale/foreman_ovirt.pot +19 -0
  36. data/locale/gemspec.rb +2 -0
  37. data/package.json +39 -0
  38. data/test/factories/foreman_ovirt_factories.rb +5 -0
  39. data/test/test_plugin_helper.rb +6 -0
  40. data/test/unit/foreman_ovirt_test.rb +11 -0
  41. data/webpack/components/extensions/HostDetails/DetailsTabCards/OvirtCard.js +132 -0
  42. data/webpack/components/ovirt.js +20 -0
  43. data/webpack/global_index.js +14 -0
  44. data/webpack/global_test_setup.js +11 -0
  45. data/webpack/index.js +1 -0
  46. data/webpack/test_setup.js +17 -0
  47. metadata +154 -128
  48. data/.document +0 -5
  49. data/Gemfile +0 -14
  50. data/Gemfile.lock +0 -33
  51. data/README.rdoc +0 -20
  52. data/VERSION +0 -1
  53. data/app/controllers/foreman_ovirt/auth_source_ovirts_controller.rb +0 -57
  54. data/app/controllers/foreman_ovirt/dashboard_controller.rb +0 -10
  55. data/app/controllers/foreman_ovirt/hosts_controller.rb +0 -17
  56. data/app/models/foreman_ovirt/auth_source_ovirt.rb +0 -78
  57. data/app/models/foreman_ovirt/user_extensions.rb +0 -26
  58. data/app/views/foreman_ovirt/auth_source_ovirts/_form.html.erb +0 -17
  59. data/app/views/foreman_ovirt/auth_source_ovirts/edit.html.erb +0 -3
  60. data/app/views/foreman_ovirt/auth_source_ovirts/index.html.erb +0 -22
  61. data/app/views/foreman_ovirt/auth_source_ovirts/new.html.erb +0 -3
  62. data/app/views/foreman_ovirt/auth_source_ovirts/welcome.html.erb +0 -8
  63. data/app/views/foreman_ovirt/hosts/_overview.html.erb +0 -27
  64. data/app/views/foreman_ovirt/hosts/show.html.erb +0 -48
  65. data/app/views/foreman_ovirt/hosts/show_graphs.html.erb +0 -13
  66. data/app/views/layouts/application_ovirt.html.erb +0 -36
  67. data/config/initializers/ovirt_setup.rb +0 -30
  68. data/foreman_ovirt.gemspec +0 -74
  69. data/lib/engine.rb +0 -9
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f3243f92dcaf16dec7795fe645d723aa37c4a6c9c07986ef188cddca14111d6f
4
+ data.tar.gz: d72bd33a55e49299cf06ed15da70ecacd1c6b5e6ab57e9463acb6192ceb47cb7
5
+ SHA512:
6
+ metadata.gz: 253437a3d3c5cbc1df95b20f0f40cd96857bce2de51619a23fc9bd671251116c6e3e4e0663d79d777d55ce678c6f6bdfeda499ab0b8b7693f3352ee9ff41e218
7
+ data.tar.gz: '093b3102464f8f6e20138bfcdb2aca2f86f7fa01e25daa4b03bb5a2e7d09a151e082eebe32fa8527c2ed0fa1f87e8c2d26ab6f7e3315dc2ca7e1a20bdf641b10'
@@ -1,5 +1,3 @@
1
- Copyright (c) 2012 Oved Ourfali
2
-
3
1
  GNU GENERAL PUBLIC LICENSE
4
2
  Version 3, 29 June 2007
5
3
 
data/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # ForemanOvirt
2
+
3
+ #### Table of Contents
4
+
5
+ 1. [Overview](#overview)
6
+ 1. [Installation](#installation)
7
+ 1. [Usage](#usage)
8
+ 1. [Development](#development)
9
+ - [Dev prerequisites](#dev-prerequisites)
10
+ - [Dev server](#dev-server)
11
+ 1. [Contributing](#contributing)
12
+ 1. [Copyright](#copyright)
13
+ - [Plugin](#plugin)
14
+ - [The Foreman](#the-forman)
15
+
16
+ ## Overview
17
+
18
+ [Foreman](http://theforeman.org/) plugin that adds [oVirt](https://www.ovirt.org) compute resource: managing virtual machines using the [fog-ovirt](https://github.com/fog/fog-ovirt) module.
19
+
20
+ This plugin continues the oVirt support that was part of Foreman up to version 3.15 and is now maintained as a standalone plugin. It requires Foreman 3.16+.
21
+
22
+ ## Installation
23
+
24
+ ### From OS packages
25
+
26
+ On Rocky/Alma/RedHat:
27
+
28
+ ```shell
29
+ sudo dnf install rubygem-foreman_ovirt
30
+ ```
31
+
32
+ On Debian/Ubuntu:
33
+
34
+ ```shell
35
+ sudo apt-get install ruby-foreman-ovirt
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ Create a oVirt compute resource and set:
41
+
42
+ * Provider: `oVirt`
43
+ * URL: `https://ovirt.example.com/ovirt-engine/api`
44
+ * Username: `admin@internal`
45
+
46
+ Then click on "Load Datacenters" and add all necessary information to the form.
47
+
48
+ ## Development
49
+
50
+ ### Dev prerequisites
51
+
52
+ See [Foreman dev setup](https://github.com/theforeman/foreman/blob/develop/developer_docs/foreman_dev_setup.asciidoc) and [foreman plugin development](https://github.com/theforeman/foreman/blob/develop/developer_docs/how_to_create_a_plugin.asciidoc) for details and a full explanation.
53
+
54
+ * oVirt 4.5+ is required
55
+ * NodeJS on the dev machine to run webpack-dev-server
56
+
57
+ ### Dev server
58
+
59
+ NOTE: The following ignores all OS-dependant tasks and commands. Please see the official Foreman developer guide for an in-depth walkthrough.
60
+
61
+ Fork and clone this plugin repository:
62
+
63
+ ```shell
64
+ git clone https://github.com/YOUR_FORK/foreman_ovirt.git
65
+ ```
66
+
67
+ Minimal steps to setup a Foreman dev instance:
68
+
69
+ ```shell
70
+ git clone https://github.com/theforeman/foreman.git -b develop
71
+ cd foreman
72
+ cp config/settings.yaml.example config/settings.yaml
73
+ cp config/database.yml.example config/database.yml
74
+ ```
75
+
76
+ Edit `bundler.d/ovirt.rb` and add this content:
77
+
78
+ ```ruby
79
+ gem 'fog-ovirt'
80
+ gem 'foreman_ovirt', :path => '/path/to/foreman_ovirt'
81
+ gem 'irb' # dev
82
+ ```
83
+
84
+ In foreman directory, install dependencies:
85
+
86
+ ```shell
87
+ bundle install --path vendor
88
+ npm install
89
+ ```
90
+
91
+ Run Foreman dev server:
92
+
93
+ ```shell
94
+ BIND=0.0.0.0 bundle exec foreman start
95
+ ```
96
+
97
+ Note that the bundled webpack server may consume HUGE amounts of RAM on startup.
98
+
99
+ ## Contributing
100
+
101
+ Fork and send a Pull Request. Thanks!
102
+
103
+ ## Copyright
104
+
105
+ ### Plugin
106
+
107
+ Copyright (c) 2025 markt.de GmbH & Co. KG
108
+
109
+ This program is free software: you can redistribute it and/or modify
110
+ it under the terms of the GNU General Public License as published by
111
+ the Free Software Foundation, either version 3 of the License, or
112
+ (at your option) any later version.
113
+
114
+ This program is distributed in the hope that it will be useful,
115
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
116
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
117
+ GNU General Public License for more details.
118
+
119
+ You should have received a copy of the GNU General Public License
120
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
121
+
122
+ The [LICENSE](LICENSE) file contains the full text of the GNU GPL v3 license, along with the text for all additional licenses referenced above.
123
+
124
+ ### The Foreman
125
+
126
+ This plugin is based on code from Foreman 3.15.0.
127
+
128
+ The Foreman repository/package is licensed under the GNU GPL v3 or newer, with some exceptions.
129
+
130
+ Copyright (c) 2009-2020 to Ohad Levy, Paul Kelly and their respective owners.
131
+
132
+ All copyright holders for the Foreman project are in the separate file called Contributors.
133
+
134
+ Except where specified below, this program and entire repository is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.
135
+
136
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
137
+
138
+ You should have received a copy of the GNU General Public License along with this program. If not, see [GNU licenses](http://www.gnu.org/licenses/).
139
+
140
+ All rights reserved.
data/Rakefile CHANGED
@@ -1,53 +1,47 @@
1
- # encoding: utf-8
2
-
3
- require 'rubygems'
4
- require 'bundler'
1
+ #!/usr/bin/env rake
5
2
  begin
6
- Bundler.setup(:default, :development)
7
- rescue Bundler::BundlerError => e
8
- $stderr.puts e.message
9
- $stderr.puts "Run `bundle install` to install missing gems"
10
- exit e.status_code
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
11
6
  end
12
- require 'rake'
13
-
14
- require 'jeweler'
15
- Jeweler::Tasks.new do |gem|
16
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
- gem.name = "foreman_ovirt"
18
- gem.homepage = "http://github.com/oourfali/foreman_ovirt"
19
- gem.license = "GPL-3"
20
- gem.summary = %Q{Plugin engine for Foreman-Ovirt integration}
21
- gem.description = %Q{Foreman oVirt plugin}
22
- gem.email = "ovedo@redhat.com"
23
- gem.authors = ["Oved Ourfali"]
24
- # dependencies defined in Gemfile
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
25
13
  end
26
- #Jeweler::RubygemsDotOrgTasks.new
27
14
 
28
- require 'rake/testtask'
29
- Rake::TestTask.new(:test) do |test|
30
- test.libs << 'lib' << 'test'
31
- test.pattern = 'test/**/test_*.rb'
32
- test.verbose = true
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')
33
21
  end
34
22
 
35
- # require 'rcov/rcovtask'
36
- # Rcov::RcovTask.new do |test|
37
- # test.libs << 'test'
38
- # test.pattern = 'test/**/test_*.rb'
39
- # test.verbose = true
40
- # test.rcov_opts << '--exclude "gems/*"'
41
- # end
23
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
42
24
 
43
- task :default => :test
25
+ Bundler::GemHelper.install_tasks
44
26
 
45
- require 'rdoc/task'
46
- Rake::RDocTask.new do |rdoc|
47
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
27
+ require 'rake/testtask'
48
28
 
49
- rdoc.rdoc_dir = 'rdoc'
50
- rdoc.title = "foreman_ovirt #{version}"
51
- rdoc.rdoc_files.include('README*')
52
- rdoc.rdoc_files.include('lib/**/*.rb')
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+ task default: :test
37
+
38
+ begin
39
+ require 'rubocop/rake_task'
40
+ RuboCop::RakeTask.new
41
+ rescue LoadError
42
+ puts 'Rubocop not loaded.'
43
+ end
44
+
45
+ task :default do
46
+ Rake::Task['rubocop'].execute
53
47
  end
@@ -0,0 +1,10 @@
1
+ function toggle_keyboard_options() {
2
+ if ($('select.display_type').val().toLowerCase() === 'vnc') {
3
+ $('.keyboard_layout').parents('.form-group').css('display', '');
4
+ } else {
5
+ $('.keyboard_layout').parents('.form-group').css('display', 'none');
6
+ }
7
+ }
8
+
9
+ $(document).on('change', '.display_type', toggle_keyboard_options);
10
+ $(document).ready(toggle_keyboard_options);
@@ -0,0 +1,61 @@
1
+ $(document).ready(function() {
2
+ var ovirt = {
3
+ update_cluster_tab: function (compute_resource_id) {
4
+ if (compute_resource_id) {
5
+ $('#cluster-indicator').show();
6
+ $.get('/compute_resources/' + compute_resource_id + '/available_clusters', { 'format': 'json' }, function (data) {
7
+ var cluster_id = $('#host_compute_attributes_cluster_id');
8
+ helpers.update_select_options(cluster_id, data);
9
+ cluster_id.change();
10
+ $('#cluster-indicator').hide();
11
+ });
12
+ } else {
13
+ $('#cluster-indicator').hide();
14
+ }
15
+ },
16
+
17
+ update_template_tab: function (compute_resource_id, cluster_id) {
18
+ if (compute_resource_id && cluster_id) {
19
+ $('#template-indicator').show();
20
+ $.get('/compute_resources/' + compute_resource_id + '/available_images', { 'cluster_id': cluster_id, 'format': 'json' }, function (data) {
21
+ var template_id = $('#host_compute_attributes_template_id');
22
+ helpers.update_select_options(template_id, data);
23
+ $('#template-indicator').hide();
24
+ });
25
+ } else {
26
+ $('#template-indicator').hide();
27
+ }
28
+ }
29
+ };
30
+
31
+ $('#host_compute_resource_id').on('change', function () {
32
+ var selected = $(this).find('option:selected');
33
+ if (selected.data('provider') === 'Ovirt') {
34
+ ovirt.update_cluster_tab($(this).val());
35
+ }
36
+ });
37
+
38
+ $('#host_compute_attributes_cluster_id').on('change', function () {
39
+ var compute_resource_id = $('#host_compute_resource_id').val();
40
+ var selected = $('#host_compute_resource_id').find('option:selected');
41
+ if (selected.data('provider') === 'Ovirt') {
42
+ ovirt.update_template_tab(compute_resource_id, $(this).val());
43
+ }
44
+ });
45
+
46
+ if ($('#host_compute_resource_id').find('option:selected').data('provider') === 'Ovirt') {
47
+ ovirt.update_cluster_tab($('#host_compute_resource_id').val());
48
+ }
49
+
50
+ $('#host_interfaces_attributes').on('change', '.type', function() {
51
+ var root = $(this).parents('.fields');
52
+ // show the relevant network
53
+ var network = $(this).val();
54
+ if (network) {
55
+ // hide all other networks
56
+ root.find('.ovirt_network').hide();
57
+ // show the relevant network
58
+ root.find('.' + network.toLowerCase() + '_network').show();
59
+ }
60
+ });
61
+ });
@@ -0,0 +1,3 @@
1
+ providerSpecificNICInfo = function(form) {
2
+ return form.find('select.ovirt_name').val() + ' @ ' + form.find('select.ovirt_network :selected').text();
3
+ }
@@ -0,0 +1,261 @@
1
+ /* eslint-disable jquery/no-each */
2
+ /* eslint-disable jquery/no-text */
3
+ /* eslint-disable jquery/no-data */
4
+ /* eslint-disable jquery/no-sizzle */
5
+ /* eslint-disable jquery/no-hide */
6
+ /* eslint-disable jquery/no-attr */
7
+ /* eslint-disable jquery/no-ajax */
8
+ /* eslint-disable jquery/no-trigger */
9
+ /* eslint-disable jquery/no-val */
10
+ /* eslint-disable jquery/no-prop */
11
+ /* eslint-disable func-names */
12
+
13
+ function templateSelected(item) {
14
+ const template = $(item).val();
15
+
16
+ if (template === null) {
17
+ return;
18
+ }
19
+
20
+ const url = $(item).attr('data-url');
21
+
22
+ tfm.tools.showSpinner();
23
+ $.ajax({
24
+ type: 'post',
25
+ url,
26
+ data: `template_id=${template}`,
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
30
+ if (!$('#host_compute_attributes_instance_type').val()) {
31
+ updateCoresAndSockets(result);
32
+ setMemoryInputProps({ value: result.memory });
33
+ $('[id$=_ha]').prop('checked', result.ha);
34
+ }
35
+ $('#network_interfaces')
36
+ .children('.fields')
37
+ .remove();
38
+ $.each(result.interfaces, function() {
39
+ addNetworkInterface(this);
40
+ });
41
+ $('#storage_volumes .children_fields >.fields').remove();
42
+ $.each(result.volumes, function() {
43
+ // Change variable name because 'interface' is a reserved keyword.
44
+ // eslint-disable-next-line dot-notation
45
+ this.disk_interface = this['interface'];
46
+ addVolume(this);
47
+ });
48
+ const templateSelector = $('#host_compute_attributes_template');
49
+
50
+ if (templateSelector.siblings('.select2-container-disabled').length > 0) {
51
+ templateSelector.val(result.id);
52
+ }
53
+ },
54
+ complete() {
55
+ // eslint-disable-next-line no-undef
56
+ reloadOnAjaxComplete(item);
57
+ },
58
+ });
59
+ }
60
+
61
+ function instanceTypeSelected(item) {
62
+ const instanceType = $(item).val();
63
+
64
+ if (!item.disabled) {
65
+ const url = $(item).attr('data-url');
66
+
67
+ tfm.tools.showSpinner();
68
+ $.ajax({
69
+ type: 'post',
70
+ url,
71
+ data: `instance_type_id=${instanceType}`,
72
+ success(result) {
73
+ if (result.name != null) {
74
+ setMemoryInputProps({ value: result.memory });
75
+ updateCoresAndSockets(result);
76
+ $('[id$=_ha]').prop('checked', result.ha);
77
+ }
78
+ setMemoryInputProps({ disabled: result.name != null });
79
+ disableCoresAndSockets(result);
80
+ ['_ha'].forEach(name =>
81
+ $(`[id$=${name}]`).prop('readOnly', result.name != null)
82
+ );
83
+ const instanceTypeSelector = $(
84
+ '#host_compute_attributes_instance_type'
85
+ );
86
+
87
+ if (instanceTypeSelector.is(':disabled')) {
88
+ instanceTypeSelector.val(result.id).trigger('change');
89
+ }
90
+ },
91
+ complete() {
92
+ // eslint-disable-next-line no-undef
93
+ reloadOnAjaxComplete(item);
94
+ },
95
+ });
96
+ }
97
+ }
98
+
99
+ // fill in the template interfaces.
100
+ function addNetworkInterface({ name, network }) {
101
+ const nestedFields = $('#network_interfaces .add_nested_fields');
102
+ // no network interfaces update when the network editing is not allowed by the compute resource
103
+
104
+ if (nestedFields.length > 0) {
105
+ // eslint-disable-next-line no-undef
106
+ const newId = add_child_node(nestedFields);
107
+
108
+ $(`[id$=${newId}_name]`).val(name);
109
+ $(`[id$=${newId}_network]`).val(network);
110
+ }
111
+ }
112
+
113
+ // fill in the template volumes.
114
+ function addVolume({
115
+ size_gb: sizeGb,
116
+ storage_domain: storageDomain,
117
+ sparse,
118
+ bootable,
119
+ id,
120
+ disk_interface: diskInterface,
121
+ wipe_after_delete: wipeAfterDelete,
122
+ }) {
123
+ // eslint-disable-next-line no-undef
124
+ const newId = add_child_node($('#storage_volumes .add_nested_fields'));
125
+
126
+ disableElement($(`[id$=${newId}_size_gb]`).val(sizeGb));
127
+ $(`[id$=${newId}_storage_domain]`).val(storageDomain);
128
+ disableElement($(`[id$=${newId}_interface]`).val(diskInterface));
129
+ disableElement($(`[id$=${newId}_bootable_true]`).attr('checked', bootable));
130
+ disableElement(
131
+ $(`[id$=${newId}_wipe_after_delete]`).prop('checked', wipeAfterDelete)
132
+ );
133
+ if (id) {
134
+ $(`[id$=${newId}_id]`).val(id);
135
+ }
136
+ $(`[id$=${newId}_storage_domain]`)
137
+ .next()
138
+ .hide();
139
+ }
140
+
141
+ function setMemoryInputProps(props) {
142
+ const newProps = { ...props };
143
+
144
+ if (newProps.value !== undefined && newProps.value !== null) {
145
+ newProps.value = parseInt(newProps.value, 10);
146
+ }
147
+
148
+ const memoryInputElement = getComponentByWrapperId('memory-input');
149
+ memoryInputElement.reactProps = {
150
+ ...memoryInputElement.reactProps,
151
+ ...newProps,
152
+ };
153
+ }
154
+
155
+ function updateCoresAndSockets(result) {
156
+ const coresInputElement = getComponentByWrapperId('cores-input');
157
+ coresInputElement.reactProps = {
158
+ ...coresInputElement.reactProps,
159
+ value: parseInt(result.cores, 10),
160
+ };
161
+ const socketInputElement = getComponentByWrapperId('sockets-input');
162
+ socketInputElement.reactProps = {
163
+ ...socketInputElement.reactProps,
164
+ value: parseInt(result.sockets, 10),
165
+ };
166
+ }
167
+
168
+ function disableCoresAndSockets(result) {
169
+ const coresInputElement = getComponentByWrapperId('cores-input');
170
+ coresInputElement.reactProps = {
171
+ ...coresInputElement.reactProps,
172
+ disabled: result.name != null,
173
+ };
174
+ const socketInputElement = getComponentByWrapperId('sockets-input');
175
+ socketInputElement.reactProps = {
176
+ ...socketInputElement.reactProps,
177
+ disabled: result.name != null,
178
+ };
179
+ }
180
+
181
+ function getComponentByWrapperId(wrapperId) {
182
+ return document
183
+ .getElementById(wrapperId)
184
+ .getElementsByTagName('foreman-react-component')[0];
185
+ }
186
+
187
+ function disableElement(element) {
188
+ element
189
+ .clone()
190
+ .attr('type', 'hidden')
191
+ .appendTo(element);
192
+ element.attr('disabled', 'disabled');
193
+ }
194
+
195
+ function bootableRadio(item) {
196
+ const disabled = $('[id$=_bootable_true]:disabled:checked:visible');
197
+
198
+ $('[id$=_bootable_true]').prop('checked', false);
199
+ if (disabled.length > 0) {
200
+ disabled.prop('checked', true);
201
+ } else {
202
+ $(item).prop('checked', true);
203
+ }
204
+ }
205
+ function clusterSelected(item) {
206
+ const cluster = $(item).val();
207
+ const url = $(item).data('url');
208
+
209
+ tfm.tools.showSpinner();
210
+ $.ajax({
211
+ type: 'post',
212
+ url,
213
+ data: `cluster_id=${cluster}`,
214
+ success(result) {
215
+ const networkOptions = $('select[id$=_network]').empty();
216
+
217
+ $.each(result, function() {
218
+ networkOptions.append(
219
+ $('<option />')
220
+ .val(this.id)
221
+ .text(this.name)
222
+ );
223
+ });
224
+ },
225
+ complete() {
226
+ // eslint-disable-next-line no-undef
227
+ reloadOnAjaxComplete(item);
228
+ },
229
+ });
230
+ }
231
+
232
+ function vnicSelected(item) {
233
+ const selectedVnicProfile = $(item).val();
234
+ if (selectedVnicProfile) {
235
+ const itemId = $(item).attr('id');
236
+ const nicId = itemId.match(/[a-z_]*_([0-9]+)[a-z_]*_vnic_profile/)[1];
237
+ const idNetwork = `id$=_${nicId}_network`;
238
+
239
+ const vnicOptions = JSON.parse(
240
+ $('select[id$=_vnic_profile]')[1].getAttribute('data-profiles')
241
+ );
242
+ const networkOptions = JSON.parse(
243
+ $('select[id$=_vnic_profile]')[1].getAttribute('data-networks')
244
+ );
245
+
246
+ const vnicNetwork = vnicOptions.filter(
247
+ vnicOption => vnicOption.id === selectedVnicProfile
248
+ )[0].network;
249
+ const networkObj = networkOptions.filter(
250
+ network => network.id === vnicNetwork.id
251
+ )[0];
252
+ const networkSelect = $(`select[${idNetwork}]`);
253
+ networkSelect.empty();
254
+ networkSelect.append(
255
+ $('<option />')
256
+ .val(networkObj.id)
257
+ .text(networkObj.name)
258
+ );
259
+ networkSelect.val(networkObj.id).trigger('change');
260
+ }
261
+ }
@@ -0,0 +1,29 @@
1
+ module ForemanOvirt
2
+ module ComputeResourcesVmsController
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ prepend Overrides
7
+ end
8
+
9
+ module Overrides
10
+ def index
11
+ load_vms
12
+ @authorizer = Authorizer.new(User.current, collection: [@compute_resource])
13
+
14
+ respond_to do |format|
15
+ format.html
16
+ format.json do
17
+ if @compute_resource.supports_vms_pagination?
18
+ # XXX: Foreman Core uses ".json", but this results in a "partial missing" error.
19
+ render partial: "compute_resources_vms/index/#{@compute_resource.provider.downcase}_json"
20
+ else
21
+ render json: _('JSON VM listing is not supported for this compute resource.'),
22
+ status: :not_implemented
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanOvirt
4
+ module ParametersExtension
5
+ extend ActiveSupport::Concern
6
+
7
+ # This block is executed when the module is included in the base class.
8
+ # It's responsible for setting up the method alias chain.
9
+ included do
10
+ # We need to modify class methods, so we operate on the singleton class.
11
+ class << self
12
+ # Create an alias for the original method.
13
+ alias_method :compute_resource_params_filter_without_ovirt, :compute_resource_params_filter
14
+ # Make the original method name point to our new implementation.
15
+ alias_method :compute_resource_params_filter, :compute_resource_params_filter_with_ovirt
16
+ end
17
+ end
18
+
19
+ module ClassMethods
20
+ # Our new implementation that extends the original functionality.
21
+ def compute_resource_params_filter_with_ovirt
22
+ # Call the original method via its new alias to get the base filter object.
23
+ compute_resource_params_filter_without_ovirt.tap do |filter|
24
+ # Now, add the oVirt specific parameters to the existing filter.
25
+ filter.permit :datacenter,
26
+ :ovirt_quota,
27
+ :keyboard_layout,
28
+ :use_v4,
29
+ :public_key,
30
+ :uuid
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end