foreman_snapshot_management 4.1.0 → 4.2.0

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -9
  3. data/app/assets/javascripts/foreman_snapshot_management/locale/cs_CZ/foreman_snapshot_management.js +1 -1
  4. data/app/assets/javascripts/foreman_snapshot_management/locale/de/foreman_snapshot_management.js +1 -1
  5. data/app/assets/javascripts/foreman_snapshot_management/locale/el/foreman_snapshot_management.js +2 -2
  6. data/app/assets/javascripts/foreman_snapshot_management/locale/en/foreman_snapshot_management.js +282 -3
  7. data/app/assets/javascripts/foreman_snapshot_management/locale/fr/foreman_snapshot_management.js +1 -1
  8. data/app/assets/javascripts/foreman_snapshot_management/locale/ja/foreman_snapshot_management.js +1 -1
  9. data/app/assets/javascripts/foreman_snapshot_management/locale/ka/foreman_snapshot_management.js +1 -1
  10. data/app/assets/javascripts/foreman_snapshot_management/locale/zh_CN/foreman_snapshot_management.js +1 -1
  11. data/app/controllers/api/v2/bulk_snapshots_controller.rb +108 -0
  12. data/app/controllers/foreman_snapshot_management/snapshots_controller.rb +10 -0
  13. data/app/models/foreman_snapshot_management/extensions/bulk_hosts_manager.rb +123 -0
  14. data/app/views/foreman_snapshot_management/snapshots/_index.html.erb +2 -0
  15. data/app/views/foreman_snapshot_management/snapshots/select_multiple_host.html.erb +3 -2
  16. data/config/routes.rb +1 -0
  17. data/lib/foreman_snapshot_management/engine.rb +3 -0
  18. data/lib/foreman_snapshot_management/version.rb +1 -1
  19. data/locale/cs_CZ/LC_MESSAGES/foreman_snapshot_management.mo +0 -0
  20. data/locale/cs_CZ/foreman_snapshot_management.po +1 -1
  21. data/locale/de/LC_MESSAGES/foreman_snapshot_management.mo +0 -0
  22. data/locale/de/foreman_snapshot_management.po +1 -1
  23. data/locale/el/LC_MESSAGES/foreman_snapshot_management.mo +0 -0
  24. data/locale/el/foreman_snapshot_management.po +3 -3
  25. data/locale/en/LC_MESSAGES/foreman_snapshot_management.mo +0 -0
  26. data/locale/en/foreman_snapshot_management.po +288 -0
  27. data/locale/fr/LC_MESSAGES/foreman_snapshot_management.mo +0 -0
  28. data/locale/fr/foreman_snapshot_management.po +1 -1
  29. data/locale/ja/LC_MESSAGES/foreman_snapshot_management.mo +0 -0
  30. data/locale/ja/foreman_snapshot_management.po +1 -1
  31. data/locale/ka/LC_MESSAGES/foreman_snapshot_management.mo +0 -0
  32. data/locale/ka/foreman_snapshot_management.po +1 -1
  33. data/locale/zh_CN/LC_MESSAGES/foreman_snapshot_management.mo +0 -0
  34. data/locale/zh_CN/foreman_snapshot_management.po +1 -1
  35. data/test/controllers/api/v2/bulk_snapshots_controller_test.rb +352 -0
  36. data/webpack/components/SnapshotManagement/SnapshotManagement.js +34 -19
  37. data/webpack/components/SnapshotManagement/SnapshotManagementActions.js +121 -0
  38. data/webpack/components/SnapshotManagement/SnapshotManagementConstants.js +3 -0
  39. data/webpack/components/SnapshotManagement/components/BulkActions/BulkCreateSnapshotMenuItem/BulkCreateSnapshotMenuItem.js +29 -0
  40. data/webpack/components/SnapshotManagement/components/BulkActions/BulkSnapshotModalScene/BulkSnapshotModalScene.js +26 -0
  41. data/webpack/components/SnapshotManagement/components/SnapshotForm/SnapshotForm.js +251 -87
  42. data/webpack/components/SnapshotManagement/components/SnapshotForm/__tests__/SnapshotForm.test.js +7 -3
  43. data/webpack/components/SnapshotManagement/components/SnapshotForm/__tests__/__snapshots__/SnapshotForm.test.js.snap +18 -161
  44. data/webpack/components/SnapshotManagement/components/SnapshotForm/index.js +1 -14
  45. data/webpack/components/SnapshotManagement/components/SnapshotFormModal/SnapshotFormModal.js +75 -22
  46. data/webpack/components/SnapshotManagement/components/SnapshotFormModal/__tests__/SnapshotFormModal.test.js +6 -1
  47. data/webpack/components/SnapshotManagement/components/SnapshotFormModal/__tests__/__snapshots__/SnapshotFormModal.test.js.snap +32 -7
  48. data/webpack/components/SnapshotManagement/components/SnapshotFormModal/index.js +0 -1
  49. data/webpack/components/SnapshotManagement/components/hooks/useSnapshotSubmit.js +13 -0
  50. data/webpack/components/SnapshotManagementCard/SnapshotManagementCard.js +13 -2
  51. data/webpack/components/SnapshotManagementCard/__tests__/SnapshotManagementCard.test.js +18 -0
  52. data/webpack/components/SnapshotManagementCard/__tests__/__snapshots__/SnapshotManagementCard.test.js.snap +26 -21
  53. data/webpack/global_index.js +17 -0
  54. metadata +10 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4c83f5919e167daeb69e987e53f4ed94d675e2b597656a76615fa1b61df2ae5
4
- data.tar.gz: cea57fad2f2a0695feac2f7aa61a6d610832d22851b0be29d26851c56ed2823d
3
+ metadata.gz: 5349e63284eef13c5d08260ac71b060ef9bcb8b6bac2e31143d511bf8de66a3b
4
+ data.tar.gz: 7eec5ae8a7a406c464d1d074375af37caf4c7bbff814edb5fe6c3a66497c47b2
5
5
  SHA512:
6
- metadata.gz: fbe7a8c72a88ee6c92cd4fae4b43db8a389acb1ef6aa52677e4fea1191f1ac89b5124bc9000b3b080eb06ecbf10eda3d7c4d10e45277eab73b133169fbd34ab0
7
- data.tar.gz: 5ba063a1df005739f04ea692cdc07b01e2878a6a478c34b7590d12f04af9ddda517736602987b27df85c52fe964a4508248f1ac7e095e761400da47aab844139
6
+ metadata.gz: 523ca42d75b0c24a08351a39c912fee62cc388e65ffa930830361d213eae1e50fd17539b53ad22cc894060fb83dac4382042949b670e6fba5df05cd5b18c25d9
7
+ data.tar.gz: 59f74f5ede323d8cbe3d8a3e625be541af7ffebc98104a5890e54d80712e0e4ececf5a8451af2fd85aaf0e98e12c8680e8192c12734afb13c8f39e341fa7dc2d
data/README.md CHANGED
@@ -27,14 +27,6 @@ For more information, see [Installing the Snapshot Management Plug-in](https://d
27
27
  | >= 3.13 | >= 4.0.0 |
28
28
  | >= 3.7 | >= 3.0.0 |
29
29
  | >= 2.3 | >= 2.0.0 |
30
- | 1.24 | >= 1.7.0 |
31
- | 1.23 | >= 1.7.0 |
32
- | 1.22 | >= 1.6.0 |
33
- | 1.21 | >= 1.5.0 |
34
- | 1.20 | >= 1.5.0 |
35
- | 1.19 | >= 1.5.0 |
36
- | 1.18 | >= 1.5.0 |
37
- | 1.17 | >= 1.5.0 |
38
30
 
39
31
  ## Usage
40
32
 
@@ -230,7 +222,7 @@ curl -s -u "$AUTH" \
230
222
  Fork and send a Pull Request. Thanks!
231
223
 
232
224
  ## Copyright
233
- Copyright (c) 2024 ATIX AG - http://www.atix.de
225
+ Copyright (c) 2025 ATIX AG - http://www.atix.de
234
226
 
235
227
  This program 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 (at your option) any later version.
236
228
 
@@ -3,7 +3,7 @@
3
3
  "locale_data": {
4
4
  "foreman_snapshot_management": {
5
5
  "": {
6
- "Project-Id-Version": "foreman_snapshot_management 3.0.1",
6
+ "Project-Id-Version": "foreman_snapshot_management 4.1.1",
7
7
  "Report-Msgid-Bugs-To": "",
8
8
  "PO-Revision-Date": "2019-10-22 11:54+0000",
9
9
  "Last-Translator": "Pavel Borecki <pavel.borecki@gmail.com>, 2022",
@@ -3,7 +3,7 @@
3
3
  "locale_data": {
4
4
  "foreman_snapshot_management": {
5
5
  "": {
6
- "Project-Id-Version": "foreman_snapshot_management 3.0.1",
6
+ "Project-Id-Version": "foreman_snapshot_management 4.1.1",
7
7
  "Report-Msgid-Bugs-To": "",
8
8
  "PO-Revision-Date": "2019-10-22 11:54+0000",
9
9
  "Last-Translator": "Wiederoder <stefanwiederoder@googlemail.com>, 2022",
@@ -3,10 +3,10 @@
3
3
  "locale_data": {
4
4
  "foreman_snapshot_management": {
5
5
  "": {
6
- "Project-Id-Version": "foreman_snapshot_management 3.0.1",
6
+ "Project-Id-Version": "foreman_snapshot_management 4.1.1",
7
7
  "Report-Msgid-Bugs-To": "",
8
8
  "PO-Revision-Date": "2019-10-22 11:54+0000",
9
- "Last-Translator": "Efstathios Iosifidis <iefstathios@gmail.com>, 2022",
9
+ "Last-Translator": "Efstathios Iosifidis <eiosifidis@gmail.com>, 2022",
10
10
  "Language-Team": "Greek (https://app.transifex.com/foreman/teams/114/el/)",
11
11
  "MIME-Version": "1.0",
12
12
  "Content-Type": "text/plain; charset=UTF-8",
@@ -3,10 +3,289 @@
3
3
  "locale_data": {
4
4
  "foreman_snapshot_management": {
5
5
  "": {
6
+ "Project-Id-Version": "foreman_snapshot_management 4.1.1",
7
+ "Report-Msgid-Bugs-To": "",
8
+ "PO-Revision-Date": "2026-02-11 19:31+0000",
9
+ "Last-Translator": "FULL NAME <EMAIL@ADDRESS>",
10
+ "Language-Team": "LANGUAGE <LL@li.org>",
11
+ "Language": "",
12
+ "MIME-Version": "1.0",
13
+ "Content-Type": "text/plain; charset=UTF-8",
14
+ "Content-Transfer-Encoding": "8bit",
15
+ "Plural-Forms": "nplurals=INTEGER; plural=EXPRESSION;",
6
16
  "lang": "en",
7
17
  "domain": "foreman_snapshot_management",
8
- "plural_forms": null
9
- }
18
+ "plural_forms": "nplurals=INTEGER; plural=EXPRESSION;"
19
+ },
20
+ "%d snapshot succeeded, %d failed.": [
21
+ ""
22
+ ],
23
+ "%d snapshots succeeded, %d failed.": [
24
+ ""
25
+ ],
26
+ "%s host is selected for snapshot creation": [
27
+ ""
28
+ ],
29
+ "%s hosts are selected for snapshot creation": [
30
+ ""
31
+ ],
32
+ "Action": [
33
+ ""
34
+ ],
35
+ "Cancel": [
36
+ ""
37
+ ],
38
+ "Create": [
39
+ ""
40
+ ],
41
+ "Create Snapshot": [
42
+ ""
43
+ ],
44
+ "Create a snapshot": [
45
+ ""
46
+ ],
47
+ "Create snapshot": [
48
+ ""
49
+ ],
50
+ "Create snapshots for multiple hosts": [
51
+ ""
52
+ ],
53
+ "Created %{snapshots} for %{num} %{hosts}": [
54
+ ""
55
+ ],
56
+ "Creating...": [
57
+ ""
58
+ ],
59
+ "Delete": [
60
+ ""
61
+ ],
62
+ "Delete Snapshot \\\"%s\\\"?": [
63
+ ""
64
+ ],
65
+ "Delete a snapshot": [
66
+ ""
67
+ ],
68
+ "Description": [
69
+ ""
70
+ ],
71
+ "Description of the snapshot": [
72
+ ""
73
+ ],
74
+ "Description of this snapshot": [
75
+ ""
76
+ ],
77
+ "Error occurred while creating Snapshot for:%s": [
78
+ ""
79
+ ],
80
+ "Error occurred while creating Snapshot: %s": [
81
+ ""
82
+ ],
83
+ "Error occurred while removing Snapshot: %s": [
84
+ ""
85
+ ],
86
+ "Error occurred while rolling back VM: %s": [
87
+ ""
88
+ ],
89
+ "Error occurred while updating Snapshot: %s": [
90
+ ""
91
+ ],
92
+ "Failed hosts": [
93
+ ""
94
+ ],
95
+ "Failed to load snapshot list": [
96
+ ""
97
+ ],
98
+ "Failed to update Snapshot: %s": [
99
+ ""
100
+ ],
101
+ "Foreman-plugin to manage snapshots in a virtual-hardware environments.": [
102
+ ""
103
+ ],
104
+ "Host has no UUID, cannot create snapshot.": [
105
+ ""
106
+ ],
107
+ "Host has no compute resource, cannot create snapshot.": [
108
+ ""
109
+ ],
110
+ "ID of the organization": [
111
+ ""
112
+ ],
113
+ "Include RAM": [
114
+ ""
115
+ ],
116
+ "Invalid mode": [
117
+ ""
118
+ ],
119
+ "List all snapshots": [
120
+ ""
121
+ ],
122
+ "List of host ids to exclude and not run an action on": [
123
+ ""
124
+ ],
125
+ "List of host ids to perform an action on": [
126
+ ""
127
+ ],
128
+ "Loading Snapshots information ...": [
129
+ ""
130
+ ],
131
+ "N/A": [
132
+ ""
133
+ ],
134
+ "Name": [
135
+ ""
136
+ ],
137
+ "Name must contain at least 2 characters starting with alphabet. Valid characters are A-Z a-z 0-9 _": [
138
+ ""
139
+ ],
140
+ "Name of the snapshot": [
141
+ ""
142
+ ],
143
+ "Name of this snapshot": [
144
+ ""
145
+ ],
146
+ "No capable hosts found.": [
147
+ ""
148
+ ],
149
+ "No capable hosts selected": [
150
+ ""
151
+ ],
152
+ "No hosts were found with that id, name or query filter": [
153
+ ""
154
+ ],
155
+ "None": [
156
+ ""
157
+ ],
158
+ "Note: Not all selected hosts support quiesce. The quiesce option is disabled.": [
159
+ ""
160
+ ],
161
+ "Quiesce": [
162
+ ""
163
+ ],
164
+ "Revert Host to a snapshot": [
165
+ ""
166
+ ],
167
+ "Rollback": [
168
+ ""
169
+ ],
170
+ "Rollback to \\\"%s\\\"?": [
171
+ ""
172
+ ],
173
+ "Search string for hosts to perform an action on": [
174
+ ""
175
+ ],
176
+ "Select Snapshot Mode between mutually exclusive options, 'Memory' (includes RAM) and 'Quiesce'.": [
177
+ ""
178
+ ],
179
+ "Select Snapshot Mode between mutually exclusive options.": [
180
+ ""
181
+ ],
182
+ "Select snapshot mode": [
183
+ ""
184
+ ],
185
+ "Snapshot": [
186
+ "",
187
+ ""
188
+ ],
189
+ "Snapshot Mode": [
190
+ ""
191
+ ],
192
+ "Snapshot creation failed.": [
193
+ ""
194
+ ],
195
+ "Snapshot creation failed: %s": [
196
+ ""
197
+ ],
198
+ "Snapshot mode": [
199
+ ""
200
+ ],
201
+ "Snapshot mode: full (default), include_ram, or quiesce": [
202
+ ""
203
+ ],
204
+ "Snapshot name cannot be changed": [
205
+ ""
206
+ ],
207
+ "Snapshot parameters": [
208
+ ""
209
+ ],
210
+ "Snapshots": [
211
+ ""
212
+ ],
213
+ "Something went wrong while selecting hosts - %s": [
214
+ ""
215
+ ],
216
+ "Successfully removed Snapshot \\\"%s\\\" from host %s": [
217
+ ""
218
+ ],
219
+ "Successfully rolled back Snapshot \\\"%s\\\" on host %s": [
220
+ ""
221
+ ],
222
+ "Successfully triggered bulk snapshot creation": [
223
+ ""
224
+ ],
225
+ "Successfully triggered snapshot creation": [
226
+ ""
227
+ ],
228
+ "Successfully updated Snapshot \\\"%s\\\"": [
229
+ ""
230
+ ],
231
+ "Unable to create Proxmox Snapshot": [
232
+ ""
233
+ ],
234
+ "Unable to create VMWare Snapshot": [
235
+ ""
236
+ ],
237
+ "Unable to create VMWare Snapshot with Quiesce. Check Power and VMWare Tools status.": [
238
+ ""
239
+ ],
240
+ "Unable to create VMWare Snapshot. Cannot set both Memory and Quiesce options.": [
241
+ ""
242
+ ],
243
+ "Unable to remove Proxmox Snapshot": [
244
+ ""
245
+ ],
246
+ "Unable to remove VMWare Snapshot": [
247
+ ""
248
+ ],
249
+ "Unable to revert Proxmox Snapshot": [
250
+ ""
251
+ ],
252
+ "Unable to revert VMWare Snapshot": [
253
+ ""
254
+ ],
255
+ "Unable to update Proxmox Snapshot": [
256
+ ""
257
+ ],
258
+ "Unable to update VMWare Snapshot": [
259
+ ""
260
+ ],
261
+ "Update a snapshot": [
262
+ ""
263
+ ],
264
+ "VM details could not be retrieved from compute resource %s. The VM may be missing/deleted or inaccessible.": [
265
+ ""
266
+ ],
267
+ "VM successfully rolled back.": [
268
+ ""
269
+ ],
270
+ "Warning: In Select All mode, we cannot guarantee that all hosts support the quiesce option as the data is not available. If a host does not support quiesce, the snapshot creation may fail for that host.": [
271
+ ""
272
+ ],
273
+ "Whether to include the Quiesce state in the snapshot": [
274
+ ""
275
+ ],
276
+ "Whether to include the RAM state in the snapshot": [
277
+ ""
278
+ ],
279
+ "edit entry": [
280
+ ""
281
+ ],
282
+ "host": [
283
+ "",
284
+ ""
285
+ ],
286
+ "snapshot.name is required": [
287
+ ""
288
+ ]
10
289
  }
11
290
  }
12
- };
291
+ };
@@ -3,7 +3,7 @@
3
3
  "locale_data": {
4
4
  "foreman_snapshot_management": {
5
5
  "": {
6
- "Project-Id-Version": "foreman_snapshot_management 3.0.1",
6
+ "Project-Id-Version": "foreman_snapshot_management 4.1.1",
7
7
  "Report-Msgid-Bugs-To": "",
8
8
  "PO-Revision-Date": "2019-10-22 11:54+0000",
9
9
  "Last-Translator": "Amit Upadhye <aupadhye@redhat.com>, 2023",
@@ -3,7 +3,7 @@
3
3
  "locale_data": {
4
4
  "foreman_snapshot_management": {
5
5
  "": {
6
- "Project-Id-Version": "foreman_snapshot_management 3.0.1",
6
+ "Project-Id-Version": "foreman_snapshot_management 4.1.1",
7
7
  "Report-Msgid-Bugs-To": "",
8
8
  "PO-Revision-Date": "2019-10-22 11:54+0000",
9
9
  "Last-Translator": "Amit Upadhye <aupadhye@redhat.com>, 2022",
@@ -3,7 +3,7 @@
3
3
  "locale_data": {
4
4
  "foreman_snapshot_management": {
5
5
  "": {
6
- "Project-Id-Version": "foreman_snapshot_management 3.0.1",
6
+ "Project-Id-Version": "foreman_snapshot_management 4.1.1",
7
7
  "Report-Msgid-Bugs-To": "",
8
8
  "PO-Revision-Date": "2019-10-22 11:54+0000",
9
9
  "Last-Translator": "Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022",
@@ -3,7 +3,7 @@
3
3
  "locale_data": {
4
4
  "foreman_snapshot_management": {
5
5
  "": {
6
- "Project-Id-Version": "foreman_snapshot_management 3.0.1",
6
+ "Project-Id-Version": "foreman_snapshot_management 4.1.1",
7
7
  "Report-Msgid-Bugs-To": "",
8
8
  "PO-Revision-Date": "2019-10-22 11:54+0000",
9
9
  "Last-Translator": "Amit Upadhye <aupadhye@redhat.com>, 2022",
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Api
4
+ module V2
5
+ class BulkSnapshotsController < V2::BaseController
6
+ include ::Api::V2::BulkHostsExtension
7
+
8
+ SNAPSHOT_MODES = ForemanSnapshotManagement::Extensions::BulkHostsManager::SNAPSHOT_MODES
9
+
10
+ before_action :validate_snapshot, :validate_mode, :find_snapshotable_hosts, only: :create
11
+
12
+ api :POST, '/snapshots/bulk/create_snapshot', N_('Create snapshots for multiple hosts')
13
+
14
+ param :organization_id, :number, required: true, desc: N_('ID of the organization')
15
+
16
+ param :included, Hash, required: true, action_aware: true do
17
+ param :search, String, required: false,
18
+ desc: N_('Search string for hosts to perform an action on')
19
+ param :ids, Array, required: false,
20
+ desc: N_('List of host ids to perform an action on')
21
+ end
22
+
23
+ param :excluded, Hash, required: true, action_aware: true do
24
+ param :ids, Array, required: false,
25
+ desc: N_('List of host ids to exclude and not run an action on')
26
+ end
27
+
28
+ param :snapshot, Hash, desc: N_('Snapshot parameters'), required: true do
29
+ param :name, String, desc: N_('Name of the snapshot'), required: true
30
+ param :description, String, desc: N_('Description of the snapshot'), required: false
31
+ end
32
+
33
+ param :mode,
34
+ SNAPSHOT_MODES,
35
+ desc: N_('Snapshot mode: full (default), include_ram, or quiesce'),
36
+ required: false
37
+
38
+ def create
39
+ results = ::BulkHostsManager.new(hosts: @hosts).create_snapshots(
40
+ name: @snapshot_name,
41
+ description: @snapshot_description,
42
+ mode: params[:mode]
43
+ )
44
+
45
+ render_results(results)
46
+ end
47
+
48
+ private
49
+
50
+ def find_snapshotable_hosts
51
+ find_bulk_hosts(:create_snapshots, params)
52
+ end
53
+
54
+ def validate_mode
55
+ mode = params[:mode]
56
+ return true if mode.blank? || SNAPSHOT_MODES.include?(mode)
57
+
58
+ render(
59
+ json: {
60
+ error: _('Invalid mode'),
61
+ valid_modes: SNAPSHOT_MODES,
62
+ },
63
+ status: :unprocessable_entity
64
+ )
65
+ false
66
+ end
67
+
68
+ def validate_snapshot
69
+ snap = params[:snapshot] || {}
70
+ @snapshot_name = snap[:name].to_s.strip
71
+ @snapshot_description = snap[:description].to_s
72
+
73
+ return true if @snapshot_name.present?
74
+
75
+ render(
76
+ json: { error: _('snapshot.name is required') },
77
+ status: :unprocessable_entity
78
+ )
79
+ false
80
+ end
81
+
82
+ def render_results(results)
83
+ failed_hosts = results.select { |r| r[:status] == 'failed' }
84
+ failed_count = failed_hosts.length
85
+ status = failed_count.zero? ? :ok : :unprocessable_entity
86
+
87
+ render(
88
+ json: {
89
+ results: results.map { |r| r.except(:errors) },
90
+ total: results.length,
91
+ success_count: results.length - failed_count,
92
+ failed_count: failed_count,
93
+ failed_hosts: failed_hosts,
94
+ },
95
+ status: status
96
+ )
97
+ end
98
+
99
+ def resource_class
100
+ ::ForemanSnapshotManagement::Snapshot
101
+ end
102
+
103
+ def resource_name
104
+ 'snapshot'
105
+ end
106
+ end
107
+ end
108
+ end
@@ -14,6 +14,7 @@ module ForemanSnapshotManagement
14
14
  before_action :enumerate_snapshots, only: [:index]
15
15
  before_action :find_snapshot, only: %i[destroy revert update]
16
16
  helper_method :xeditable?
17
+ helper_method :available_snapshot_modes
17
18
 
18
19
  def xeditable?(_object = nil)
19
20
  true
@@ -186,6 +187,15 @@ module ForemanSnapshotManagement
186
187
  end
187
188
  end
188
189
 
190
+ def available_snapshot_modes
191
+ capable_hosts = @hosts.select { |h| h.compute_resource.capable?(:snapshot_include_quiesce) }
192
+ if capable_hosts.length < @hosts.length
193
+ { 'Include RAM' => 'memory' }
194
+ else
195
+ { 'Include RAM' => 'memory', 'Quiesce' => 'quiesce' }
196
+ end
197
+ end
198
+
189
199
  def check_snapshot_capability
190
200
  not_found unless @host.compute_resource&.capabilities&.include?(:snapshots)
191
201
  end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanSnapshotManagement
4
+ module Extensions
5
+ module BulkHostsManager
6
+ extend ActiveSupport::Concern
7
+
8
+ SNAPSHOT_MODES = %w[full include_ram quiesce].freeze
9
+ QUIESCE_ERROR_MESSAGE =
10
+ _('Unable to create VMWare Snapshot with Quiesce. Check Power and VMWare Tools status.').freeze
11
+
12
+ def create_snapshots(name:, description:, mode:)
13
+ include_ram, quiesce = resolve_mode(mode)
14
+
15
+ @hosts.map do |host|
16
+ process_snapshot_for_host(
17
+ host: host,
18
+ name: name,
19
+ description: description,
20
+ include_ram: include_ram,
21
+ quiesce: quiesce
22
+ )
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def resolve_mode(mode)
29
+ case mode
30
+ when 'include_ram'
31
+ [true, false]
32
+ when 'quiesce'
33
+ [false, true]
34
+ else
35
+ [false, false]
36
+ end
37
+ end
38
+
39
+ def process_snapshot_for_host(host:, name:, description:, include_ram:, quiesce:)
40
+ validation_error = validate_host(host)
41
+ return validation_error if validation_error
42
+
43
+ create_snapshot_for_host(host, name, description, include_ram, quiesce)
44
+ rescue ActiveRecord::RecordNotFound => e
45
+ handle_record_not_found(host, e)
46
+ rescue StandardError => e
47
+ handle_snapshot_error(host, e)
48
+ end
49
+
50
+ def validate_host(host)
51
+ if host.compute_resource.nil?
52
+ return {
53
+ host_id: host.id,
54
+ host_name: host.name,
55
+ status: 'failed',
56
+ errors: [_('Host has no compute resource, cannot create snapshot.')],
57
+ }
58
+ end
59
+
60
+ return if host.uuid.present?
61
+
62
+ {
63
+ host_id: host.id,
64
+ host_name: host.name,
65
+ status: 'failed',
66
+ errors: [_('Host has no UUID, cannot create snapshot.')],
67
+ }
68
+ end
69
+
70
+ def create_snapshot_for_host(host, name, description, include_ram, quiesce)
71
+ snapshot = ::ForemanSnapshotManagement::Snapshot.new(
72
+ name: name,
73
+ description: description,
74
+ include_ram: include_ram,
75
+ quiesce: quiesce,
76
+ host: host
77
+ )
78
+
79
+ if snapshot.create
80
+ { host_id: host.id, host_name: host.name, status: 'success' }
81
+ else
82
+ errors = snapshot.errors.full_messages
83
+ errors << QUIESCE_ERROR_MESSAGE if quiesce
84
+ { host_id: host.id, host_name: host.name, status: 'failed', errors: errors }
85
+ end
86
+ end
87
+
88
+ def handle_record_not_found(host, exception)
89
+ ::Foreman::Logging.exception(
90
+ "Failed to create snapshot for host #{host.name} (ID: #{host.id})",
91
+ exception
92
+ )
93
+
94
+ cr_name = host.compute_resource&.name
95
+ cr_name = "#{cr_name} " if cr_name.present?
96
+
97
+ msg =
98
+ _('VM details could not be retrieved from compute resource %s. The VM may be missing/deleted or inaccessible.') % cr_name
99
+
100
+ {
101
+ host_id: host.id,
102
+ host_name: host.name,
103
+ status: 'failed',
104
+ errors: [msg],
105
+ }
106
+ end
107
+
108
+ def handle_snapshot_error(host, exception)
109
+ ::Foreman::Logging.exception(
110
+ "Failed to create snapshot for host #{host.name} (ID: #{host.id})",
111
+ exception
112
+ )
113
+
114
+ {
115
+ host_id: host.id,
116
+ host_name: host.name,
117
+ status: 'failed',
118
+ errors: [_('Snapshot creation failed: %s') % exception.message],
119
+ }
120
+ end
121
+ end
122
+ end
123
+ end
@@ -1,3 +1,4 @@
1
+ <% if @host.compute_resource && @host.compute_resource.capabilities.include?(:snapshots) && authorized_for(:auth_object => @host, :permission => :view_snapshots) %>
1
2
  <%= react_component('SnapshotManagement', {
2
3
  host: @host,
3
4
  canCreate: authorized_for(:auth_object => @host, :permission => :create_snapshots),
@@ -11,3 +12,4 @@
11
12
  quiesceOption: @host.compute_resource.capable?(:snapshot_include_quiesce)
12
13
  }
13
14
  }) %>
15
+ <% end %>
@@ -3,6 +3,7 @@
3
3
  <% if @hosts.empty? %>
4
4
  <%= _('No capable hosts selected') %>
5
5
  <% else %>
6
+ <% snapshot_modes = available_snapshot_modes %>
6
7
  <%= form_for :snapshot, :url => create_multiple_host_snapshots_path(:host_ids => @hosts.map{ | h| h.id}) do |f| %>
7
8
  <%= text_f f, :name,
8
9
  { :label => _("Snapshot")}
@@ -10,10 +11,10 @@
10
11
  <%= textarea_f f, :description,
11
12
  { :label => _("Description")}
12
13
  %>
13
- <%= selectable_f f, :snapshot_mode, {'Quiesce' => 'quiesce', 'Include RAM' => 'memory'},
14
+ <%= selectable_f f, :snapshot_mode, snapshot_modes,
14
15
  {:include_blank => true}, {
15
16
  :label => _("Snapshot Mode"),
16
- :label_help => _("Select Snapshot Mode between mutually exclusive options, 'Memory' (includes RAM) and 'Quiesce'."),
17
+ :label_help => _("Select Snapshot Mode between mutually exclusive options."),
17
18
  :onchange => "tfm.hosts.table.toggleMultipleOkButton(this)"} %>
18
19
  <% end %>
19
20
  <% end %>