Project

General

Profile

Bug #815 ยป 815.patch

Ohad Levy, 04/22/2011 04:13 PM

View differences:

app/controllers/hosts_controller.rb
before_filter :find_hosts, :only => :query
before_filter :ajax_methods, :only => [:hostgroup_or_environment_selected]
before_filter :find_multiple, :only => [:multiple_actions, :update_multiple_parameters, :multiple_build,
before_filter :find_multiple, :only => [:update_multiple_parameters, :multiple_build,
:select_multiple_hostgroup, :select_multiple_environment, :multiple_parameters, :multiple_destroy,
:multiple_enable, :multiple_disable, :submit_multiple_disable, :submit_multiple_enable]
before_filter :find_by_name, :only => %w[show edit update destroy puppetrun setBuild cancelBuild report
......
# restrict allowed hosts list based on the user permissions
my_hosts = User.current.admin? ? Host : Host.my_hosts
@search = my_hosts.search_for(params[:search],:order => params[:order], :group => 'hosts.id')
flash.clear
rescue => e
error e.to_s
@search = my_hosts.search_for ''
......
# multiple host selection methods
# present the available actions to the user
def multiple_actions
end
def multiple_parameters
@parameters = HostParameter.reference_id_is(@hosts).all(:select => "distinct name")
end
def reset_multiple
session[:selected] = []
flash.keep
notice 'Selection cleared.'
redirect_to hosts_path and return
end
def update_multiple_parameters
if params[:name].empty?
notice "No parameters were allocted to the selected hosts, can't mass assign."
......
@skipped_parameters[host.name] = skipped unless skipped.empty?
end
end
session[:selected] = []
params[:host_ids] = []
if @skipped_parameters.empty?
notice 'Updated all hosts!'
redirect_to(hosts_path) and return
......
# simple validations
if (id=params["hostgroup"]["id"]).empty?
error 'No Hostgroup selected!'
redirect_to(select_multiple_hostgroup_hosts) and return
redirect_to(select_multiple_hostgroup_hosts_path) and return
end
if (hg = Hostgroup.find id).nil?
error 'Empty Hostgroup selected!'
redirect_to(select_multiple_hostgroup_hosts) and return
redirect_to(select_multiple_hostgroup_hosts_path) and return
end
#update the hosts
Host.find(session[:selected]).each do |host|
Host.find(params[:host_ids]).each do |host|
host.hostgroup=hg
host.save(perform_validation = false)
end
session[:selected] = []
notice 'Updated hosts: Changed Hostgroup'
redirect_to(hosts_path)
end
......
end
#update the hosts
Host.find(session[:selected]).each do |host|
Host.find(params[:host_ids]).each do |host|
host.environment=ev
host.save(perform_validation = false)
end
session[:selected] = []
params[:host_ids] = []
notice 'Updated hosts: Changed Environment'
redirect_to(hosts_path)
end
......
end
def submit_multiple_build
hosts = Host.find(session[:selected])
hosts = Host.find(params[:host_ids])
hosts.delete_if do |host|
host.request_url = request.host_with_port if host.respond_to?(:request_url)
host.setBuild
end
session[:selected] = []
params[:host_ids] = []
missed_hosts = hosts.map(&:name).join('<br/>')
notice hosts.empty? ? "The selected hosts will execute a build operation on next reboot" : "The following hosts failed the build operation: #{missed_hosts}"
......
def submit_multiple_destroy
# destroy the hosts
hosts = Host.find(session[:selected])
hosts = Host.find(params[:host_ids])
# keep all the ones that were not deleted for notification.
hosts.delete_if {|host| host.destroy}
session[:selected] = []
params[:host_ids] = []
missed_hosts = hosts.map(&:name).join('<br/>')
notice hosts.empty? ? "Destroyed selected hosts" : "The following hosts were not deleted: #{missed_hosts}"
redirect_to(hosts_path)
......
toggle_hostmode
end
# AJAX method to update our session each time a host has been selected
# we are using AJAX and JS as the user might select multiple hosts across different pages (or requests).
def save_checkbox
return unless request.xhr?
session[:selected] ||= []
case params[:is_checked]
when "true"
session[:selected] << params[:box]
when "false"
session[:selected].delete params[:box]
end
render :nothing => true
end
def errors
params[:search]="last_report > \"#{SETTINGS[:puppet_interval] + 5} minutes ago\" and (status.failed > 0 or status.failed_restarts > 0 or status.skipped > 0)"
show_hosts Host.recent.with_error, "Hosts with errors"
......
end
def find_multiple
if session[:selected].empty?
if params[:host_ids].blank?
error 'No Hosts selected'
redirect_to(hosts_path)
else
begin
@hosts = Host.find(session[:selected], :order => "hostgroup_id ASC")
rescue
error "Something went wrong while selecting hosts - resetting ..."
flash.keep(:foreman_error)
redirect_to reset_multiple_hosts_path
end
redirect_to(hosts_path) and return false
end
@hosts = Host.find(params[:host_ids], :order => "hostgroup_id ASC")
rescue => e
error "Something went wrong while selecting hosts - #{e}"
redirect_to hosts_path
end
def toggle_hostmode mode=true
......
@hosts.delete_if { |host| host.update_attribute(:enabled, mode) }
action = mode ? "enabled" : "disabled"
session[:selected] = []
params[:host_ids] = []
missed_hosts = @hosts.map(&:name).join('<br/>')
notice @hosts.empty? ? "#{action.capitalize} selected hosts" : "The following hosts were not #{action}: #{missed_hosts}"
redirect_to(hosts_path) and return
app/helpers/hosts_helper.rb
((Time.now - time) / 1.day).round.to_i
end
def authorized?
authorized_for(:hosts, :edit) or authorized_for(:hosts, :destroy)
end
def searching?
params[:search].empty?
end
def multiple_actions_select
actions = [
['Change Group', select_multiple_hostgroup_hosts_path],
['Change Environment', select_multiple_environment_hosts_path],
['Edit Parameters', multiple_parameters_hosts_path],
['Destroy Hosts', multiple_destroy_hosts_path],
['Disable Notifications', multiple_disable_hosts_path],
['Enable Notifications', multiple_enable_hosts_path],
]
actions << ['Build Hosts', multiple_build_hosts_path] if SETTINGS[:unattended]
select_tag "Multiple Actions", options_for_select(["Edit Multiple Hosts",""] + actions.sort), :id => "Submit_multiple", :onchange => 'submit_multiple(this.value)'
end
def selected? host
return false if host.nil? or not host.is_a?(Host) or session[:selected].nil?
session[:selected].include?(host.id.to_s)
app/views/hosts/_minilist.html.erb
<% if hosts.size > 0 -%>
<% allow_multiple = authorized_for(:hosts, :edit) or authorized_for(:hosts, :destroy) -%>
<% form_tag(multiple_actions_hosts_path,:method => "get", :id => "host_select_form") do %>
<% title header ||= "" %>
<table class="list">
<tr>
<th><%= sort :name %></th>
<th><%= sort :os, :as => "Operating system" %></th>
<th><%= sort :environment %></th>
<th><%= sort :model %></th>
<th><%= sort :hostgroup, :as => "Host Group" %></th>
<th><%= sort :last_report %></th>
<th></th>
</tr>
<% hosts.each do |host| -%>
<tr class="<%= cycle("even", "odd") -%>">
<td>
<% if allow_multiple -%>
<%= check_box_tag "host_ids[]", host.id, selected?(host), :id => "host_ids_#{host.id}", :class => 'host_select_boxes', :onclick => 'insertHostVal(this)' -%>
<% end -%>
<%=name_column(host) %>
</td>
<td><%=icon(host.os, :size => "18x18", :title => host.os.to_s) + " " + host.os.to_s if host.os %></td>
<td><%=h host.try(:environment) %></td>
<td><%=h host.try(:model) %></td>
<td><%=h host.try(:hostgroup) %></td>
<td><%=last_report_column(host) %></td>
<td>
<%= display_link_if_authorized 'Edit', hash_for_edit_host_path(:id => host) %>
<%= display_link_if_authorized 'Clone', hash_for_clone_host_path(:id => host) %>
<%= display_link_if_authorized 'Destroy', hash_for_host_path(:id => host, :auth_action => :destroy), :confirm => "Delete #{host.name}?", :method => :delete, :action => :destroy %>
</td>
</tr>
<% end -%>
</table>
<div>
<%= submit_tag("Edit Multiple Hosts", :title => "Mass assign values to many hosts") if allow_multiple %><br />
</div>
<% end -%>
<% title header ||= "" %>
<table class="list">
<tr>
<% if authorized? -%>
<th></th>
<% end -%>
<th><%= sort :name %></th>
<th><%= sort :os, :as => "Operating system" %></th>
<th><%= sort :environment %></th>
<th><%= sort :model %></th>
<th><%= sort :hostgroup, :as => "Host Group" %></th>
<th><%= sort :last_report %></th>
<th></th>
</tr>
<% hosts.each do |host| -%>
<tr class="<%= cycle("even", "odd") -%>">
<td>
<% if authorized? -%>
<%= check_box_tag "host_ids[]", nil, false, :id => "host_ids_#{host.id}", :class => 'host_select_boxes', :onclick => 'hostChecked(this)' -%>
<% end -%>
</td>
<td> <%=name_column(host) %> </td>
</td>
<td><%=icon(host.os, :size => "18x18", :title => host.os.to_s) + " " + host.os.to_s if host.os %></td>
<td><%=h host.try(:environment) %></td>
<td><%=h host.try(:model) %></td>
<td><%=h host.try(:hostgroup) %></td>
<td><%=last_report_column(host) %></td>
<td>
<%= display_link_if_authorized 'Edit', hash_for_edit_host_path(:id => host) %>
<%= display_link_if_authorized 'Clone', hash_for_clone_host_path(:id => host) %>
<%= display_link_if_authorized 'Destroy', hash_for_host_path(:id => host, :auth_action => :destroy), :confirm => "Delete #{host.name}?", :method => :delete, :action => :destroy %>
</td>
</tr>
<% end -%>
</table>
<% if authorized? -%>
<div class="multiple_actions">
<%= button_to_function "Toggle All", "toggleCheck()" %>
<%= button_to_function "Reset Selection", "cleanHostsSelection()" %>
<%= multiple_actions_select %>
</div>
<% end -%>
<%= page_entries_info hosts %>
<%= will_paginate hosts %>
app/views/hosts/_selected_hosts.html.erb
<h4>The following hosts are about to be changed:</h4>
<table>
<% for host in hosts %>
<tr>
<% title "The following hosts are about to be changed" %>
<table class="list">
<tr>
<th> Name </th>
<th> Hostgroup </th>
<th> Environment </th>
</tr>
<% hosts.each do |host| -%>
<tr class="<%= cycle("even", "odd") -%>">
<td>
<%= hidden_field_tag "host_ids[]", host.id %>
<%= host.name %>
<%= host.name %>
</td>
<td><%=h host.try(:hostgroup) %></td>
<td><%=h host.try(:environment) %></td>
</tr>
<% end %>
</table>
<h5>Click this button to clear all selected hosts and return to Hosts list:</h5>
<%= button_to 'Clear Selected Hosts', reset_multiple_hosts_path %>
app/views/hosts/index.html.erb
<%= javascript "host_checkbox" %>
<%= javascript "jquery.cookie", "host_checkbox" %>
<%= render 'minilist', :hosts => @hosts, :header => @title || "Hosts" %>
<span class="title_action">
<%= display_link_if_authorized "New Host", hash_for_new_host_path %> |
<% if authorized_for(:hosts, :edit) or authorized_for(:hosts, :destroy) -%>
<%= link_to_function "Toggle All", "toggleCheck()" %>
<%= link_to "Reset Selection", reset_multiple_hosts_path %>
<% end -%>
<%= display_link_if_authorized "New Host", hash_for_new_host_path %>
</span>
app/views/hosts/multiple_actions.html.erb
<%= render 'selected_hosts', :hosts => @hosts %>
<h2>Choose the action you want to apply to the selected Hosts:</h2>
<%= link_to 'Change Group', select_multiple_hostgroup_hosts_path %> |
<%= link_to 'Change Environment', select_multiple_environment_hosts_path %> |
<%= link_to 'Edit Parameters', multiple_parameters_hosts_path %> |
<%= link_to 'Destroy Hosts', multiple_destroy_hosts_path %> |
<%= link_to 'Disable Notifications', multiple_disable_hosts_path %> |
<%= link_to 'Enable Notifications', multiple_enable_hosts_path %>
<% if SETTINGS[:unattended].nil? or SETTINGS[:unattended] -%> |
<%= link_to 'Build Hosts', multiple_build_hosts_path %>
<% end %>
app/views/hosts/multiple_build.html.erb
<%= render 'selected_hosts', :hosts => @hosts %>
<% form_tag submit_multiple_build_hosts_path do -%>
<%= submit_tag "Mark these hosts for a build operation on next boot" %></p>
<% form_tag submit_multiple_build_hosts_path({:host_ids => params[:host_ids]}) do -%>
<%= submit_tag "Mark these hosts for a build operation on next boot" %>
<% end %>
app/views/hosts/multiple_destroy.html.erb
<%= render 'selected_hosts', :hosts => @hosts %>
<% form_tag submit_multiple_destroy_hosts_path do -%>
<%= submit_tag "DESTROY SELECTED HOSTS!" %></p>
<small>This might take a while, as all hosts, facts and reports will be destroyed as well</small>
<% form_tag submit_multiple_destroy_hosts_path(:host_ids => params[:host_ids]) do -%>
<%= submit_tag "DESTROY SELECTED HOSTS!" %>
<small>This might take a while, as all hosts, facts and reports will be destroyed as well</small>
<% end %>
app/views/hosts/multiple_disable.html.erb
<%= render 'selected_hosts', :hosts => @hosts %>
<% form_tag submit_multiple_disable_hosts_path do -%>
<%= submit_tag "Disable alerts for selected hosts" %></p>
<% form_tag submit_multiple_disable_hosts_path({:host_ids => params[:host_ids]}) do -%>
<%= submit_tag "Disable alerts for selected hosts" %>
<% end %>
app/views/hosts/multiple_enable.html.erb
<%= render 'selected_hosts', :hosts => @hosts %>
<% form_tag submit_multiple_enable_hosts_path do -%>
<%= submit_tag "Enable alerts for selected hosts" %></p>
<% form_tag submit_multiple_enable_hosts_path({:host_ids => params[:host_ids]}) do -%>
<%= submit_tag "Enable alerts for selected hosts" %>
<% end %>
app/views/hosts/multiple_parameters.html.erb
Sorry, these hosts do not have parameters assigned to them, you must add them first.
<p><%= link_to "Back to host list", hosts_path %></p>
<% else -%>
<% form_tag update_multiple_parameters_hosts_path do %>
<% for param in @parameters %>
<%= text_field :name, param.name, :size=>'50' %>
<%= param.name %><br/>
<% end %>
<p><%= submit_tag "Submit", :title => pluralize(@parameters.size, 'parameter') %></p>
<% form_tag update_multiple_parameters_hosts_path({:host_ids => params[:host_ids]}) do %>
<div class="span-24">
<% for param in @parameters %>
<div class="span-3">
<%= param.name %>
</div>
<%= text_field :name, param.name, :class => "span-12 last" %>
<% end %>
</div>
<div class="span-24 last"><%= submit_tag "Submit", :title => pluralize(@parameters.size, 'parameter') %></div>
<% end %>
<% end %>
app/views/hosts/select_multiple_environment.html.erb
<%= render 'selected_hosts', :hosts => @hosts %>
<% form_for :environment, :url => update_multiple_environment_hosts_path do |f| %>
<% form_for :environment, :url => update_multiple_environment_hosts_path(:host_ids => params[:host_ids]) do |f| %>
<%= f.collection_select :id, Environment.all, :id, :name, :include_blank => "Select Environment" %>
<%= f.submit "Change Environment!" %></p>
<%= f.submit "Change Environment!" %>
<% end %>
app/views/hosts/select_multiple_hostgroup.html.erb
<%= render 'selected_hosts', :hosts => @hosts %>
<% form_for :hostgroup, :url => update_multiple_hostgroup_hosts_path do |f| %>
<% form_for :hostgroup, :url => update_multiple_hostgroup_hosts_path(:host_ids => params[:host_ids]) do |f| %>
<%= f.collection_select :id, Hostgroup.all, :id, :name, :include_blank => "Select Host Group" %>
<%= f.submit "Change Hostgroup!" %></p>
<%= f.submit "Change Hostgroup!" %>
<% end %>
app/views/layouts/application.html.erb
<%= stylesheet_link_tag 'typography' %>
<%= stylesheet_link_tag 'grid' %>
<%= stylesheet_link_tag 'jquery-ui' %>
<%= yield(:head) %>
<%= javascript_include_tag :defaults, :cache => true %>
<%= yield(:head) %>
</head>
<body>
config/routes.rb
:storeconfig_klasses => :get, :externalNodes => :get, :setBuild => :get, :cancelBuild => :get,
:puppetrun => :get, :facts => :get, :pxe_config => :get },
:collection => { :show_search => :get, :multiple_actions => :get, :multiple_parameters => :get,
:update_multiple_parameters => :post, :save_checkbox => :post, :select_multiple_hostgroup => :get,
:update_multiple_parameters => :post, :select_multiple_hostgroup => :get,
:update_multiple_hostgroup => :post, :select_multiple_environment => :get, :update_multiple_environment => :post,
:multiple_destroy => :get, :submit_multiple_destroy => :post, :multiple_build => :get, :submit_multiple_build => :post,
:reset_multiple => :get, :multiple_disable => :get, :submit_multiple_disable => :post,
public/javascripts/host_checkbox.js
function toggleCheck() {
$('#host_select_form input.host_select_boxes').each(function(box){
box.checked=!box.checked;
insertHostVal(box);
});
// Array contains list of host ids
$.foremanSelectedHosts = readFromCookie();
// triggered by a host checkbox change
function hostChecked(box) {
var cid = parseInt(box.id.replace("host_ids_", ""));
if (box.checked) {
addHostId(cid);
} else {
rmHostId(cid);
}
$.cookie("_ForemanSelectedHosts", JSON.stringify($.foremanSelectedHosts));
toggle_actions();
return false;
}
function insertHostVal(cbox) {
$.ajax({
type: "POST",
url: 'hosts/save_checkbox',
data: {box: cbox.value, is_checked: cbox.checked},
success: function(res){ return false; },
failure: function(res){
alert("Something failed! Select the checkbox again.");
return false;
function addHostId(id) {
if (jQuery.inArray(id, $.foremanSelectedHosts) == -1) {
$.foremanSelectedHosts.push(id)
}
}
function rmHostId(id) {
var pos = jQuery.inArray(id, $.foremanSelectedHosts);
if (pos >= 0) {
$.foremanSelectedHosts.splice(pos, 1)
}
}
function readFromCookie() {
try {
if (r = $.cookie("_ForemanSelectedHosts")) {
return JSON.parse(r);
} else {
return []
}
}
catch(err) {
removeForemanHostsCookie();
return []
}
}
function toggle_actions() {
if ($.foremanSelectedHosts.length > 0) {
$("#Submit_multiple").enable()
} else {
$("#Submit_multiple").disable()
}
}
// setups checkbox values upon document load
$(function() {
for (var i = 0; i < $.foremanSelectedHosts.length; i++) {
var cid = "host_ids_" + $.foremanSelectedHosts[i];
if ((boxes = $('#' + cid)) && (boxes[0])) {
boxes[0].checked = true;
}
}
toggle_actions();
return false;
});
function removeForemanHostsCookie() {
$.cookie("_ForemanSelectedHosts", null);
}
function cleanHostsSelection() {
removeForemanHostsCookie();
$('.host_select_boxes').each(function(index, box) {
box.checked = false;
hostChecked(box);
})
$.foremanSelectedHosts = [];
toggle_actions();
return false;
}
function toggleCheck() {
$('.host_select_boxes').each(function(index, box) {
box.checked = !box.checked;
hostChecked(box);
});
return false;
}
// updates the form URL based on the action selection
function submit_multiple(path) {
window.location.href = path+"?"+$.param({host_ids: $.foremanSelectedHosts});
}
public/javascripts/jquery.cookie.js
/*jslint browser: true */ /*global jQuery: true */
/**
* jQuery Cookie plugin
*
* Copyright (c) 2010 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
// TODO JsDoc
/**
* Create a cookie with the given key and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
* used when the cookie was set.
*
* @param String key The key of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
* If set to null or omitted, the cookie will be a session cookie and will not be retained
* when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
* require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
/**
* Get the value of a cookie with the given key.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String key The key of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
jQuery.cookie = function (key, value, options) {
// key and at least value given, set cookie...
if (arguments.length > 1 && String(value) !== "[object Object]") {
options = jQuery.extend({}, options);
if (value === null || value === undefined) {
options.expires = -1;
}
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setDate(t.getDate() + days);
}
value = String(value);
return (document.cookie = [
encodeURIComponent(key), '=',
options.raw ? value : encodeURIComponent(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// key and possibly options given, get cookie...
options = value || {};
var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
};
    (1-1/1)