Class: HostsController

Constant Summary collapse

PUPPETMASTER_ACTIONS =
[ :externalNodes, :lookup ]
SEARCHABLE_ACTIONS =
%w[index active errors out_of_sync pending disabled ]
AJAX_REQUESTS =
%w{compute_resource_selected hostgroup_or_environment_selected current_parameters puppetclass_parameters process_hostgroup process_taxonomy}
BOOT_DEVICES =
{ :disk => N_('Disk'), :cdrom => N_('CDROM'), :pxe => N_('PXE'), :bios => N_('BIOS') }

Instance Method Summary collapse

Methods included from Foreman::Controller::SmartProxyAuth

#auth_smart_proxy, #require_puppetmaster_or_login

Methods included from Foreman::Controller::TaxonomyMultiple

#select_multiple_location, #select_multiple_organization, #update_multiple_location, #update_multiple_organization

Methods included from Foreman::Controller::AutoCompleteSearch

#auto_complete_search, #invalid_search_query

Methods included from Foreman::Controller::HostDetails

#architecture_selected, #domain_selected, #medium_selected, #os_selected, #use_image_selected

Methods inherited from ApplicationController

#api_request?, #welcome

Methods included from Foreman::ThreadSession::Cleaner

#clear_thread, included

Instance Method Details

#activeObject


416
417
418
419
# File 'app/controllers/hosts_controller.rb', line 416

def active
  merge_search_filter("last_report > \"#{Setting[:puppet_interval] + 5} minutes ago\" and (status.applied > 0 or status.restarted > 0)")
  index _("Active Hosts")
end

#bmcObject


217
218
219
220
221
222
223
224
225
226
# File 'app/controllers/hosts_controller.rb', line 217

def bmc
  render :partial => 'bmc', :locals => { :host => @host }
rescue ActionView::Template::Error => exception
  origin = exception.try(:original_exception)
  message = (origin || exception).message
  logger.warn "Failed to fetch bmc information: #{message}"
  logger.debug "Original exception backtrace:\n" + origin.backtrace.join("\n") if origin.present?
  logger.debug "Causing backtrace:\n" + exception.backtrace.join("\n")
  render :text => "Failure: #{message}"
end

#cancelBuildObject


201
202
203
204
205
206
207
# File 'app/controllers/hosts_controller.rb', line 201

def cancelBuild
  if @host.built(false)
    process_success :success_msg =>  _("Canceled pending build for %s") % (@host.name), :success_redirect => :back
  else
    process_error :redirect => :back, :error_msg => _("Failed to cancel pending build for %s") % (@host.name)
  end
end

#cloneObject

Clone the host


74
75
76
77
78
79
80
81
# File 'app/controllers/hosts_controller.rb', line 74

def clone
  new = @host.dup
  load_vars_for_ajax
  flash[:warning] = _("The marked fields will need reviewing")
  new.valid?
  @host = new
  render :action => :new
end

#compute_resource_selectedObject

form AJAX methods


130
131
132
133
134
135
# File 'app/controllers/hosts_controller.rb', line 130

def compute_resource_selected
  return not_found unless (params[:host] && (id=params[:host][:compute_resource_id]))
  Taxonomy.as_taxonomy @organization, @location do
    render :partial => "compute", :locals => {:compute_resource => ComputeResource.find_by_id(id)}
  end
end

#consoleObject


237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'app/controllers/hosts_controller.rb', line 237

def console
  return unless @host.compute_resource
  @console = @host.compute_resource.console @host.uuid
  render case @console[:type]
           when 'spice'
             "hosts/console/spice"
           when 'vnc'
             "hosts/console/vnc"
           else
             "hosts/console/log"
         end
rescue => e
  process_error :redirect => :back, :error_msg => _("Failed to set console: %s") % (e)
end

#createObject


83
84
85
86
87
88
89
90
91
92
93
94
# File 'app/controllers/hosts_controller.rb', line 83

def create
  @host = Host.new(params[:host])
  @host.managed = true if (params[:host] && params[:host][:managed].nil?)
  forward_url_options
  if @host.save
    process_success :success_redirect => host_path(@host), :redirect_xhr => request.xhr?
  else
    load_vars_for_ajax
    offer_to_overwrite_conflicts
    process_error
  end
end

#current_parametersObject


147
148
149
150
151
# File 'app/controllers/hosts_controller.rb', line 147

def current_parameters
  Taxonomy.as_taxonomy @organization, @location do
    render :partial => "common_parameters/inherited_parameters", :locals => {:inherited_parameters => refresh_host.host_inherited_params(true)}
  end
end

#destroyObject


121
122
123
124
125
126
127
# File 'app/controllers/hosts_controller.rb', line 121

def destroy
  if @host.destroy
    process_success
  else
    process_error
  end
end

#disabledObject


431
432
433
434
# File 'app/controllers/hosts_controller.rb', line 431

def disabled
  merge_search_filter("status.enabled = false")
  index _("Hosts with notifications disabled")
end

#editObject


96
97
98
# File 'app/controllers/hosts_controller.rb', line 96

def edit
  load_vars_for_ajax
end

#errorsObject


411
412
413
414
# File 'app/controllers/hosts_controller.rb', line 411

def errors
  merge_search_filter("last_report > \"#{Setting[:puppet_interval] + 5} minutes ago\" and (status.failed > 0 or status.failed_restarts > 0)")
  index _("Hosts with errors")
end

#externalNodesObject

returns a yaml file ready to use for puppet external nodes script expected a fqdn parameter to provide hostname to lookup see example script in extras directory will return HTML error codes upon failure


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'app/controllers/hosts_controller.rb', line 164

def externalNodes
  certname = params[:name]
  @host ||= Host.find_by_certname certname
  @host ||= Host.find_by_name certname
  not_found and return unless @host

  begin
    respond_to do |format|
      format.html { render :text => "<pre>#{@host.info.to_yaml}</pre>" }
      format.yml { render :text => @host.info.to_yaml }
    end
  rescue
    # failed
    logger.warn "Failed to generate external nodes for #{@host} with #{$!}"
    render :text => _('Unable to generate output, Check log files\n'), :status => 412 and return
  end
end

#hostgroup_or_environment_selectedObject


137
138
139
140
141
142
143
144
145
# File 'app/controllers/hosts_controller.rb', line 137

def hostgroup_or_environment_selected
  Taxonomy.as_taxonomy @organization, @location do
    if params['host']['environment_id'].present? || params['host']['hostgroup_id'].present?
      render :partial => 'puppetclasses/class_selection', :locals => {:obj => (refresh_host)}
    else
      logger.info "environment_id or hostgroup_id is required to render puppetclasses"
    end
  end
end

#index(title = nil) ⇒ Object


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
# File 'app/controllers/hosts_controller.rb', line 25

def index (title = nil)
  begin
    search = Host.my_hosts.search_for(params[:search],:order => params[:order])
  rescue => e
    error e.to_s
    search = Host.my_hosts.search_for ''
  end
  respond_to do |format|
    format.html do
      @hosts = search.includes(included_associations).paginate(:page => params[:page])
      # SQL optimizations queries
      @last_reports = Report.where(:host_id => @hosts.map(&:id)).group(:host_id).maximum(:id)
      # rendering index page for non index page requests (out of sync hosts etc)
      render :index if title and (@title = title)
    end
    # should you ever need more attributes just add to the :only array or specify :methods, :include, :except to the options hash
    format.json { render :json => search.includes(included_associations).to_json({:only => [:name, :id, :hostgroup_id, :operatingsystem_id]}) }

    format.yaml do
      render :text => if params["rundeck"]
        result = {}
        search.all(:include => included_associations).each{|h| result.update(h.rundeck)}
        result
      else
        search.all(:select => "hosts.name").map(&:name)
      end.to_yaml
    end
  end
end

#ipmi_bootObject


228
229
230
231
232
233
234
235
# File 'app/controllers/hosts_controller.rb', line 228

def ipmi_boot
  device    = params[:ipmi_device]
  device_id = BOOT_DEVICES.stringify_keys[device.downcase] || device
  @host.ipmi_boot(device)
  process_success :success_redirect => :back, :success_msg => _("%{host} now boots from %{device}") % { :host => @host.name, :device => _(device_id) }
rescue => e
  process_error :redirect => :back, :error_msg => _("Failed to configure %{host} to boot from %{device}: %{e}") % { :device => _(device_id), :host => @host.name, :e => e }
end

#multiple_buildObject


352
353
# File 'app/controllers/hosts_controller.rb', line 352

def multiple_build
end

#multiple_destroyObject


349
350
# File 'app/controllers/hosts_controller.rb', line 349

def multiple_destroy
end

#multiple_disableObject


383
384
# File 'app/controllers/hosts_controller.rb', line 383

def multiple_disable
end

#multiple_enableObject


390
391
# File 'app/controllers/hosts_controller.rb', line 390

def multiple_enable
end

#multiple_parametersObject

multiple host selection methods


274
275
276
# File 'app/controllers/hosts_controller.rb', line 274

def multiple_parameters
  @parameters = HostParameter.where(:reference_id => @hosts).select("distinct name")
end

#multiple_puppetrunObject


397
398
399
# File 'app/controllers/hosts_controller.rb', line 397

def multiple_puppetrun
  deny_access unless Setting[:puppetrun]
end

#newObject


69
70
71
# File 'app/controllers/hosts_controller.rb', line 69

def new
  @host = Host.new :managed => true
end

#out_of_syncObject


426
427
428
429
# File 'app/controllers/hosts_controller.rb', line 426

def out_of_sync
  merge_search_filter("last_report < \"#{Setting[:puppet_interval] + 5} minutes ago\" and status.enabled = true")
  index _("Hosts which didn't run puppet in the last %s") % (view_context.time_ago_in_words((Setting[:puppet_interval]+5).minutes.ago))
end

#pendingObject


421
422
423
424
# File 'app/controllers/hosts_controller.rb', line 421

def pending
  merge_search_filter("last_report > \"#{Setting[:puppet_interval] + 5} minutes ago\" and (status.pending > 0)")
  index _("Pending Hosts")
end

#powerObject


209
210
211
212
213
214
215
# File 'app/controllers/hosts_controller.rb', line 209

def power
  return invalid_request unless PowerManager::SUPPORTED_ACTIONS.include? (params[:power_action])
  @host.power.send(params[:power_action].to_sym)
  process_success :success_redirect => :back, :success_msg => _("%{host} is now %{state}") % { :host => @host, :state => _(@host.power.state) }
rescue => e
  process_error :redirect => :back, :error_msg => _("Failed to %{action} %{host}: %{e}") % { :action => _(params[:power_action]), :host => @host, :e => e }
end

#process_hostgroupObject


436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# File 'app/controllers/hosts_controller.rb', line 436

def process_hostgroup
  @hostgroup = Hostgroup.find(params[:host][:hostgroup_id]) if params[:host][:hostgroup_id].to_i > 0
  return head(:not_found) unless @hostgroup

  @architecture    = @hostgroup.architecture
  @operatingsystem = @hostgroup.operatingsystem
  @environment     = @hostgroup.environment
  @domain          = @hostgroup.domain
  @subnet          = @hostgroup.subnet

  @host = if params[:host][:id]
    host = Host::Base.find(params[:host][:id])
    host = host.becomes Host::Managed
    host.attributes = params[:host]
    host
  else
    Host.new(params[:host])
  end
  @host.set_hostgroup_defaults
  render :partial => "form"

end

#process_taxonomyObject


459
460
461
462
463
464
465
466
467
468
469
# File 'app/controllers/hosts_controller.rb', line 459

def process_taxonomy
  return head(:not_found) unless @location || @organization
  @host = Host.new(params[:host])
  # revert compute resource to "Bare Metal" (nil) if selected
  # compute resource is not included taxonomy
  Taxonomy.as_taxonomy @organization , @location do
    # if compute_resource_id is not in our scope, reset it to nil.
    @host.compute_resource_id = nil unless ComputeResource.exists?(@host.compute_resource_id)
  end
  render :partial => 'form'
end

#puppetclass_parametersObject


153
154
155
156
157
# File 'app/controllers/hosts_controller.rb', line 153

def puppetclass_parameters
  Taxonomy.as_taxonomy @organization, @location do
    render :partial => "puppetclasses/classes_parameters", :locals => { :obj => refresh_host}
  end
end

#puppetrunObject


182
183
184
185
186
187
188
189
190
# File 'app/controllers/hosts_controller.rb', line 182

def puppetrun
  return deny_access unless Setting[:puppetrun]
  if @host.puppetrun!
    notice _("Successfully executed, check log files for more details")
  else
    error @host.errors[:base]
  end
  redirect_to host_path(@host)
end

#pxe_configObject


265
266
267
# File 'app/controllers/hosts_controller.rb', line 265

def pxe_config
  redirect_to(:controller => "unattended", :action => "pxe_#{@host.operatingsystem.pxe_type}_config", :host_id => @host) if @host
end

#select_multiple_environmentObject


327
328
# File 'app/controllers/hosts_controller.rb', line 327

def select_multiple_environment
end

#select_multiple_hostgroupObject


306
307
# File 'app/controllers/hosts_controller.rb', line 306

def select_multiple_hostgroup
end

#setBuildObject


192
193
194
195
196
197
198
199
# File 'app/controllers/hosts_controller.rb', line 192

def setBuild
  forward_url_options
  if @host.setBuild
    process_success :success_msg => _("Enabled %s for rebuild on next boot") % (@host), :success_redirect => :back
  else
    process_error :redirect => :back, :error_msg => _("Failed to enable %{host} for installation: %{errors}") % { :host => @host, :errors => @host.errors.full_messages }
  end
end

#showObject


55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/controllers/hosts_controller.rb', line 55

def show
  respond_to do |format|
    format.html {
      # filter graph time range
      @range = (params["range"].empty? ? 7 : params["range"].to_i)

      # summary report text
      @report_summary = Report.summarise(@range.days.ago, @host)
    }
    format.yaml { render :text => params["rundeck"].nil? ? @host.info.to_yaml : @host.rundeck.to_yaml }
    format.json { render :json => @host.to_json({:methods => [:host_parameters], :include => :interfaces }) }
  end
end

#storeconfig_klassesObject


269
270
# File 'app/controllers/hosts_controller.rb', line 269

def storeconfig_klasses
end

#submit_multiple_buildObject


355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'app/controllers/hosts_controller.rb', line 355

def submit_multiple_build
  @hosts.delete_if do |host|
    forward_url_options(host)
    host.setBuild
  end

  missed_hosts = @hosts.map(&:name).join('<br/>')
  if @hosts.empty?
    notice _("The selected hosts will execute a build operation on next reboot")
  else
    error _("The following hosts failed the build operation: %s") % (missed_hosts)
  end
  redirect_to(hosts_path)
end

#submit_multiple_destroyObject


370
371
372
373
374
375
376
377
378
379
380
381
# File 'app/controllers/hosts_controller.rb', line 370

def submit_multiple_destroy
  # keep all the ones that were not deleted for notification.
  @hosts.delete_if {|host| host.destroy}

  missed_hosts = @hosts.map(&:name).join('<br/>')
  if @hosts.empty?
    notice _("Destroyed selected hosts")
  else
    error _("The following hosts were not deleted: %s") % (missed_hosts)
  end
  redirect_to(hosts_path)
end

#submit_multiple_disableObject


386
387
388
# File 'app/controllers/hosts_controller.rb', line 386

def submit_multiple_disable
  toggle_hostmode false
end

#submit_multiple_enableObject


393
394
395
# File 'app/controllers/hosts_controller.rb', line 393

def submit_multiple_enable
  toggle_hostmode
end

#template_usedObject


472
473
474
475
476
477
478
479
480
# File 'app/controllers/hosts_controller.rb', line 472

def template_used
  kinds = params[:provisioning] == 'image' ? [TemplateKind.find_by_name('finish')] : TemplateKind.all
  templates = kinds.map do |kind|
    ConfigTemplate.find_template({:kind => kind.name, :operatingsystem_id => params[:operatingsystem_id],
                                 :hostgroup_id => params[:hostgroup_id], :environment_id => params[:environment_id]})
  end.compact
  return not_found if templates.empty?
  render :partial => "provisioning", :locals => {:templates => templates}
end

#toggle_manageObject


252
253
254
255
256
257
258
259
260
261
262
263
# File 'app/controllers/hosts_controller.rb', line 252

def toggle_manage
  if @host.toggle! :managed
    if @host.managed
      msg = _("Foreman now manages the build cycle for %s") % (@host.name)
    else
      msg = _("Foreman now no longer manages the build cycle for %s") % (@host.name)
    end
    process_success :success_msg => msg, :success_redirect => :back
  else
    process_error :error_msg => _("Failed to modify the build cycle for %s") % @host.name, :redirect => :back
  end
end

#updateObject


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'app/controllers/hosts_controller.rb', line 100

def update
  forward_url_options
  Taxonomy.no_taxonomy_scope do
    # remove from hash :root_pass and bmc :password if blank?
    params[:host].except!(:root_pass) if params[:host][:root_pass].blank?
    if @host.type == "Host::Managed" && params[:host][:interfaces_attributes]
      params[:host][:interfaces_attributes].each do |k, v|
        params[:host][:interfaces_attributes]["#{k}"].except!(:password) if params[:host][:interfaces_attributes]["#{k}"][:password].blank?
      end
    end
    if @host.update_attributes(params[:host])
      process_success :success_redirect => host_path(@host), :redirect_xhr => request.xhr?
    else
      taxonomy_scope
      load_vars_for_ajax
      offer_to_overwrite_conflicts
      process_error
    end
  end
end

#update_multiple_environmentObject


330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'app/controllers/hosts_controller.rb', line 330

def update_multiple_environment
  # simple validations
  if (params[:environment].nil?) or (id=params["environment"]["id"]).nil?
    error _('No environment selected!')
    redirect_to(select_multiple_environment_hosts_path) and return
  end

  ev = Environment.find(id) rescue nil

  #update the hosts
  @hosts.each do |host|
    host.environment = (id == 'inherit' && host.hostgroup.present? ) ? host.hostgroup.environment : ev
    host.save(:validate => false)
  end

  notice _('Updated hosts: changed environment')
  redirect_back_or_to hosts_path
end

#update_multiple_hostgroupObject


309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'app/controllers/hosts_controller.rb', line 309

def update_multiple_hostgroup
  # simple validations
  unless (id=params["hostgroup"]["id"])
    error _('No host group selected!')
    redirect_to(select_multiple_hostgroup_hosts_path) and return
  end
  hg = Hostgroup.find(id) rescue nil
  #update the hosts
  @hosts.each do |host|
    host.hostgroup=hg
    host.save(:validate => false)
  end

  notice _('Updated hosts: changed host group')
  # We prefer to go back as this does not lose the current search
  redirect_back_or_to hosts_path
end

#update_multiple_parametersObject


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
# File 'app/controllers/hosts_controller.rb', line 278

def update_multiple_parameters
  if params[:name].empty?
    notice _("No parameters were allocated to the selected hosts, can't mass assign.")
    redirect_to hosts_path and return
  end

  @skipped_parameters = {}
  counter = 0
  @hosts.each do |host|
    skipped = []
    params[:name].each do |name, value|
      next if value.empty?
      if (host_param = host.host_parameters.find_by_name(name))
        counter += 1 if host_param.update_attribute(:value, value)
      else
        skipped << name
      end
      @skipped_parameters[host.name] = skipped unless skipped.empty?
    end
  end
  if @skipped_parameters.empty?
    notice _('Updated all hosts!')
    redirect_to(hosts_path) and return
  else
    notice _("%s Parameters updated, see below for more information") % (counter)
  end
end

#update_multiple_puppetrunObject


401
402
403
404
405
406
407
408
409
# File 'app/controllers/hosts_controller.rb', line 401

def update_multiple_puppetrun
  return deny_access unless Setting[:puppetrun]
  if @hosts.map(&:puppetrun!).uniq == [true]
    notice _("Successfully executed, check reports and/or log files for more details")
  else
    error _("Some or all hosts execution failed, Please check log files for more information")
  end
  redirect_back_or_to hosts_path
end