-
Notifications
You must be signed in to change notification settings - Fork 356
/
Copy pathreconfigure.rb
432 lines (376 loc) · 18.1 KB
/
reconfigure.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
module Mixins
module Actions
module VmActions
module Reconfigure
def reconfigure(reconfigure_ids = [])
@sb[:explorer] = true if @explorer
@request_id = nil
@in_a_form = @reconfigure = true
drop_breadcrumb(:name => _("Reconfigure"), :url => "/vm_common/reconfigure")
reconfigure_ids = params[:rec_ids] if params[:rec_ids]
@request_id = params[:req_id] if params[:req_id]
@reconfigitems = find_records_with_rbac(Vm, reconfigure_ids)
build_targets_hash(@reconfigitems)
@force_no_grid_xml = true
@view, @pages = get_view(Vm, :view_suffix => "VmReconfigureRequest", :selected_ids => reconfigure_ids) # Get the records (into a view) and the paginator
get_reconfig_limits(reconfigure_ids)
if @reconfigitems.size == 1
vm = @reconfigitems.first
# NOTE: available_vlans is ovirt specific vlan lookup
@vlan_options = vm.try(:available_vlans) || get_vlan_options(vm.host)
@avail_adapter_names = vm.try(:available_adapter_names) || []
@iso_options = get_iso_options(vm)
end
unless @explorer
render :action => "show"
end
end
def reconfigure_update
case params[:button]
when "cancel" then reconfigure_handle_cancel_button
when "submit" then reconfigure_handle_submit_button
end
end
def reconfigure_form_fields
@request_id, request_data = params[:id].split(/\s*,\s*/, 2)
reconfigure_ids = request_data.split(/\s*,\s*/)
request_hash = build_reconfigure_hash(reconfigure_ids)
render :json => request_hash
end
# reconfiguration for VMs only
def vm_reconfigure
assert_privileges('vm_reconfigure_all', :any => true)
# if coming in to edit from miq_request list view
recs = checked_or_params
if !session[:checked_items].nil? && (@lastaction == "set_checked_items" || params[:pressed] == "miq_request_edit")
recs = session[:checked_items]
request_id = params[:id]
end
if recs.empty?
add_flash(_("One or more %{model} must be selected to Reconfigure") %
{:model => Dictionary.gettext(db.to_s, :type => :model, :notfound => :titleize, :plural => true)}, :error)
javascript_flash
return
else
if VmOrTemplate.includes_template?(recs)
add_flash(_("Reconfigure does not apply because you selected at least one VM Template"), :error)
javascript_flash
return
end
unless VmOrTemplate.reconfigurable?(recs)
add_flash(_("Reconfigure does not apply because you selected at least one un-reconfigurable VM"), :error)
javascript_flash
return
end
reconfigure_ids = recs.collect(&:to_i)
end
if @explorer
reconfigure(reconfigure_ids)
session[:changed] = true # need to enable submit button when screen loads
@refresh_partial = "vm_common/reconfigure"
else
# redirect to build the ownership screen
javascript_redirect(:controller => 'vm', :action => 'reconfigure', :req_id => request_id, :rec_ids => reconfigure_ids, :escape => false)
end
end
def get_reconfig_limits(reconfigure_ids)
@reconfig_limits = VmReconfigureRequest.request_limits(:src_ids => reconfigure_ids)
mem1, fmt1 = reconfigure_calculations(@reconfig_limits[:min__vm_memory])
mem2, fmt2 = reconfigure_calculations(@reconfig_limits[:max__vm_memory])
@reconfig_memory_note = _("Between %{min} and %{max}") % {:min => "#{mem1}#{fmt1}", :max => "#{mem2}#{fmt2}"}
@socket_options = []
@reconfig_limits[:max__number_of_sockets].times do |tidx|
idx = tidx + @reconfig_limits[:min__number_of_sockets]
@socket_options.push(idx) if idx <= @reconfig_limits[:max__number_of_sockets]
end
@cores_options = []
@reconfig_limits[:max__cores_per_socket].times do |tidx|
idx = tidx + @reconfig_limits[:min__cores_per_socket]
@cores_options.push(idx) if idx <= @reconfig_limits[:max__cores_per_socket]
end
end
# Build the reconfigure data hash
def build_reconfigure_hash(reconfigure_ids)
@req = nil
@reconfig_values = {}
if @request_id == 'new'
@reconfig_values = get_reconfig_info(reconfigure_ids)
else
@req = MiqRequest.find_by(:id => @request_id)
@reconfig_values[:src_ids] = @req.options[:src_ids]
@reconfig_values[:memory], @reconfig_values[:memory_type] = @req.options[:vm_memory] ? reconfigure_calculations(@req.options[:vm_memory]) : ['', '']
@reconfig_values[:cores_per_socket_count] = @req.options[:cores_per_socket] ? @req.options[:cores_per_socket].to_s : ''
@reconfig_values[:socket_count] = @req.options[:number_of_sockets] ? @req.options[:number_of_sockets].to_s : ''
# check if there is only one VM that supports disk reconfiguration
@reconfig_values[:disk_add] = @req.options[:disk_add]
@reconfig_values[:disk_resize] = @req.options[:disk_resize]
@reconfig_values[:cdrom_connect] = @req.options[:cdrom_connect]
@reconfig_values[:cdrom_disconnect] = @req.options[:cdrom_disconnect]
vmdisks = []
vmcdroms = []
@req.options[:disk_add]&.each do |disk|
adsize, adunit = reconfigure_calculations(disk[:disk_size_in_mb])
vmdisks << {:hdFilename => disk[:disk_name],
:hdType => disk[:thin_provisioned] ? 'thin' : 'thick',
:hdMode => disk[:persistent] ? 'persistent' : 'nonpersistent',
:hdSize => adsize.to_s,
:hdUnit => adunit,
:new_controller_type => disk[:new_controller_type].to_s,
:cb_dependent => disk[:dependent],
:cb_bootable => disk[:bootable],
:add_remove => 'add'}
end
reconfig_item = Vm.find(reconfigure_ids)
if reconfig_item
reconfig_item.first.hardware.disks.each do |disk|
next if disk.device_type != 'disk'
removing = ''
delbacking = false
if disk.filename && @req.options[:disk_remove]
@req.options[:disk_remove].each do |remdisk|
if remdisk[:disk_name] == disk.filename
removing = 'remove'
delbacking = remdisk[:delete_backing]
end
end
end
dsize, dunit = reconfigure_calculations(disk.size / (1024 * 1024))
vmdisk = {:hdFilename => disk.filename,
:hdType => disk.disk_type.to_s,
:hdMode => disk.mode.to_s,
:hdSize => dsize.to_s,
:hdUnit => dunit.to_s,
:delete_backing => delbacking,
:cb_bootable => disk.bootable,
:add_remove => removing}
vmdisks << vmdisk
end
cdroms = reconfig_item.first.hardware.cdroms
if cdroms.present?
vmcdroms = build_request_cdroms_list(cdroms)
end
end
@reconfig_values[:disks] = vmdisks
@reconfig_values[:cdroms] = vmcdroms
end
@reconfig_values[:cb_memory] = !!(@req && @req.options[:vm_memory]) # default for checkbox is false for new request
@reconfig_values[:cb_cpu] = !!(@req && (@req.options[:number_of_sockets] || @req.options[:cores_per_socket])) # default for checkbox is false for new request
@reconfig_values
end
def build_request_cdroms_list(cdroms)
vmcdroms = []
connect_disconnect = ''
cdroms.map do |cd|
id = cd.id
device_name = cd.device_name
type = cd.device_type
filename = cd.filename
storage_id = cd.storage_id
if cd.filename && @req.options[:cdrom_disconnect]&.find { |d_cd| d_cd[:device_name] == cd.device_name }
filename = ''
connect_disconnect = 'disconnect'
end
conn_cd = @req.options[:cdrom_connect]&.find { |c_cd| c_cd[:device_name] == cd.device_name }
if cd.filename && conn_cd
filename = conn_cd[:filename]
connect_disconnect = 'connect'
end
vmcdroms << {:id => id, :device_name => device_name, :filename => filename, :type => type, :storage_id => storage_id, :connect_disconnect => connect_disconnect}
end
vmcdroms
end
def reconfigure_calculations(mbsize)
humansize = mbsize
fmt = "MB"
if mbsize.to_i > 1024 && (mbsize.to_i % 1024).zero?
humansize = mbsize.to_i / 1024
fmt = "GB"
end
return humansize.to_s, fmt
end
# determine available switches for this host...
def get_vlan_options(host)
switch_ids = Rbac.filtered(host.switches).pluck(:id)
Rbac.filtered(Lan.where(:switch_id => switch_ids).order(:name)).pluck(:name)
end
def get_iso_options(vm)
iso_options = []
return iso_options unless vm&.host&.storages
datastore_ids = vm.host.storages.pluck(:id)
# determine available iso files for the datastores
Rbac.filtered(StorageFile.where("storage_id IN (?) and ext_name = 'iso'", datastore_ids)).each do |sf|
iso_options << [sf.name, sf.name + ',' + sf.storage_id.to_s]
end
iso_options
end
def get_reconfig_info(reconfigure_ids)
@reconfigureitems = Vm.find(reconfigure_ids).sort_by(&:name)
# set memory to nil if multiple items were selected with different mem_cpu values
memory = @reconfigureitems.first.mem_cpu
memory = nil unless @reconfigureitems.all? { |vm| vm.mem_cpu == memory }
socket_count = @reconfigureitems.first.num_cpu
socket_count = '' unless @reconfigureitems.all? { |vm| vm.num_cpu == socket_count }
cores_per_socket = @reconfigureitems.first.cpu_cores_per_socket
cores_per_socket = '' unless @reconfigureitems.all? { |vm| vm.cpu_cores_per_socket == cores_per_socket }
memory, memory_type = reconfigure_calculations(memory)
# if only one vm that supports disk reconfiguration is selected, get the disks information
vmdisks = []
@reconfigureitems.first.hardware.disks.order(:filename).each do |disk|
next if disk.device_type != 'disk'
dsize, dunit = reconfigure_calculations(disk.size / (1024 * 1024))
vmdisks << {:hdFilename => disk.filename,
:hdType => disk.disk_type,
:hdMode => disk.mode,
:hdSize => dsize,
:hdUnit => dunit,
:add_remove => '',
:cb_bootable => disk.bootable}
end
# reconfiguring network adapters is only supported when one vm was selected
network_adapters = []
vmcdroms = []
if @reconfigureitems.size == 1
vm = @reconfigureitems.first
if vm.supports?(:reconfigure_network_adapters)
network_adapters = build_network_adapters_list(vm)
end
if vm.supports?(:reconfigure_cdroms)
# CD-ROMS
vmcdroms = build_vmcdrom_list(vm)
end
end
{:objectIds => reconfigure_ids,
:memory => memory,
:memory_type => memory_type,
:socket_count => socket_count.to_s,
:cores_per_socket_count => cores_per_socket.to_s,
:disks => vmdisks,
:network_adapters => network_adapters,
:cdroms => vmcdroms,
:vm_vendor => @reconfigureitems.first.vendor,
:vm_type => @reconfigureitems.first.class.name,
:orchestration_stack_id => @reconfigureitems.first.try(:orchestration_stack_id),
:disk_default_type => @reconfigureitems.first.try(:disk_default_type) || 'thin'}
end
def build_network_adapters_list(vm)
network_adapters = []
vm.hardware.guest_devices.order(:device_name => 'asc').each do |guest_device|
lan = Lan.find_by(:id => guest_device.lan_id)
network_adapters << {:name => guest_device.device_name, :vlan => lan.name, :mac => guest_device.address, :add_remove => ''} unless lan.nil?
end
if vm.kind_of?(ManageIQ::Providers::Vmware::CloudManager::Vm)
vm.network_ports.order(:name).each do |port|
network_adapters << { :name => port.name, :network => port.cloud_subnets.try(:first).try(:name) || _('None'), :mac => port.mac_address, :add_remove => '' }
end
end
network_adapters
end
def filename_string(name)
# an empty cdrom filename can be in the form of a string containing a pair of square brackets
name.blank? || name == '[]' ? '' : name.to_s
end
def build_vmcdrom_list(vm)
vmcdroms = []
cdroms = vm.hardware.cdroms
if cdroms.present?
cdroms.map do |cd|
id = cd.id
device_name = cd.device_name
type = cd.device_type
filename = filename_string(cd.filename)
storage_id = cd.storage_id || ''
vmcdroms << {:id => id, :device_name => device_name, :filename => filename, :type => type, :storage_id => storage_id}
end
vmcdroms
end
end
private
def item_supports?(*features)
features << :reconfigure_disks if features.include?(:reconfigure_disksize) # special case
item = @reconfigitems.first if @reconfigitems&.size == 1
item && features.all? { |feature| item.supports?(feature) }
end
# 'true' => true
# 'false' => false
# 'rootofevil' => 'rootofevil'
# Example:
#
# {"a" => "true", "b" => "false", "c" => "42"}.transform_values! { |v| eval_if_bool_string(v) }
# => {"a" => true, "b" => false, "c" => "42"}
def eval_if_bool_string(str)
case str
when 'true' then true
when 'false' then false
else str
end
end
def reconfigure_handle_cancel_button
add_flash(_("VM Reconfigure Request was cancelled by the user"))
if @sb[:explorer]
@sb[:action] = nil
replace_right_cell
else
session[:flash_msgs] = @flash_array
javascript_redirect(previous_breadcrumb_url)
end
end
# parameter to accept for vm reconfiguration based on role permissions
def reconfigure_param_list
list = []
if role_allows?(:feature => 'vm_reconfigure_disks')
list += [
%i[vmAddDisks disk_add],
%i[vmResizeDisks disk_resize],
%i[vmRemoveDisks disk_remove]
]
end
if role_allows?(:feature => 'vm_reconfigure_networks')
list += [
%i[vmAddNetworkAdapters network_adapter_add],
%i[vmRemoveNetworkAdapters network_adapter_remove],
%i[vmEditNetworkAdapters network_adapter_edit],
]
end
if role_allows?(:feature => 'vm_reconfigure_drives')
list += [
%i[vmConnectCDRoms cdrom_connect],
%i[vmDisconnectCDRoms cdrom_disconnect]
]
end
list
end
def reconfigure_handle_submit_button
options = {:src_ids => params[:objectIds]}
if params[:cb_memory] == 'true' && role_allows?(:feature => 'vm_reconfigure_memory')
options[:vm_memory] = params[:memory_type] == "MB" ? params[:memory] : params[:memory].to_i * 1024
end
if params[:cb_cpu] == 'true' && role_allows?(:feature => 'vm_reconfigure_cpu')
options[:cores_per_socket] = params[:cores_per_socket_count].nil? ? 1 : params[:cores_per_socket_count].to_i
options[:number_of_sockets] = params[:socket_count].nil? ? 1 : params[:socket_count].to_i
vccores = params[:cores_per_socket_count].to_i.zero? ? 1 : params[:cores_per_socket_count].to_i
vsockets = params[:socket_count].to_i.zero? ? 1 : params[:socket_count].to_i
options[:number_of_cpus] = vccores * vsockets
end
reconfigure_param_list.each do |params_key, options_key|
next if params[params_key].blank?
params[params_key].each do |_key, p|
p.transform_values! { |v| eval_if_bool_string(v) }
end
options[options_key] = params[params_key].values.map(&:to_unsafe_h)
end
if params[:id] && params[:id] != 'new'
@request_id = params[:id]
end
VmReconfigureRequest.make_request(@request_id, options, current_user)
flash_to_session(_("VM Reconfigure Request was saved"))
if role_allows?(:feature => "miq_request_show_list", :any => true)
javascript_redirect(:controller => 'miq_request', :action => 'show_list')
else
url = previous_breadcrumb_url.split('/')
javascript_redirect(:controller => url[1], :action => url[2])
end
end
end
end
end
end