[Ovirt-devel] [PATCH] added smart pool UI bits to search results and other flexigrids
Jason Guiditta
jguiditt at redhat.com
Tue Oct 28 16:58:44 UTC 2008
On Wed, 2008-10-22 at 22:16 +0000, Scott Seago wrote:
> Search results now show what smart pools the items belong to. There's also a pulldown selection to add selected results to a smart pool.
>
> 'Add to smart pool' pulldown is also available for the single-type tab pages for hosts, storage, vm pools, and vms.
>
> Signed-off-by: Scott Seago <sseago at redhat.com>
> ---
> src/app/controllers/pool_controller.rb | 4 ++-
> src/app/controllers/search_controller.rb | 6 +++-
> src/app/controllers/smart_pools_controller.rb | 24 ++++++++++++++-
> src/app/models/host.rb | 3 +-
> src/app/models/pool.rb | 3 +-
> src/app/models/smart_pool.rb | 32 +++++++++++++++++++-
> src/app/models/storage_pool.rb | 3 +-
> src/app/models/vm.rb | 3 +-
> src/app/views/hardware/show_hosts.rhtml | 29 +++++++++++++++++++
> src/app/views/hardware/show_storage.rhtml | 29 +++++++++++++++++++
> src/app/views/hardware/show_vms.rhtml | 29 +++++++++++++++++++
> src/app/views/resources/show_vms.rhtml | 29 +++++++++++++++++++
> src/app/views/search/_grid.rhtml | 3 +-
> src/app/views/search/results.rhtml | 38 +++++++++++++++++++++++-
> src/app/views/vm/_grid.rhtml | 2 +-
> 15 files changed, 223 insertions(+), 14 deletions(-)
>
> diff --git a/src/app/controllers/pool_controller.rb b/src/app/controllers/pool_controller.rb
> index 063cc43..03d1316 100644
> --- a/src/app/controllers/pool_controller.rb
> +++ b/src/app/controllers/pool_controller.rb
> @@ -110,7 +110,9 @@ class PoolController < ApplicationController
> attr_list = [:id, :description, :uuid,
> :num_vcpus_allocated, :memory_allocated_in_mb,
> :vnic_mac_addr, :state, :id]
> - attr_list.insert(3, [:host, :hostname]) if @pool.get_hardware_pool.can_view(@user)
> + if (@pool.is_a? VmResourcePool) and @pool.get_hardware_pool.can_view(@user)
> + attr_list.insert(3, [:host, :hostname])
> + end
> json_list(args[:full_items], attr_list, [:all], args[:find_opts])
> end
>
> diff --git a/src/app/controllers/search_controller.rb b/src/app/controllers/search_controller.rb
> index cc7e527..3789309 100644
> --- a/src/app/controllers/search_controller.rb
> +++ b/src/app/controllers/search_controller.rb
> @@ -96,7 +96,9 @@ class SearchController < ApplicationController
> item_hash = {}
> item = result[:model]
> item_hash[:id] = item.class.name+"_"+item.id.to_s
> - item_hash[:cell] = ["display_name", "display_class"].collect do |attr|
> + item_hash[:cell] = []
> + item_hash[:cell] << item_hash[:id] if params[:checkboxes]
> + item_hash[:cell] += ["display_name", "display_class"].collect do |attr|
> if attr.is_a? Array
> value = item
> attr.each { |attr_item| value = value.send(attr_item)}
> @@ -106,6 +108,8 @@ class SearchController < ApplicationController
> end
> end
> item_hash[:cell] << result[:percent]
> + item_hash[:cell] << item.smart_pools.collect {|pool| pool.name}.join(', ')
> +
> item_hash
> end
> render :json => json_hash.to_json
> diff --git a/src/app/controllers/smart_pools_controller.rb b/src/app/controllers/smart_pools_controller.rb
> index 6bfe367..90b1419 100644
> --- a/src/app/controllers/smart_pools_controller.rb
> +++ b/src/app/controllers/smart_pools_controller.rb
As discussed in irc, line 101 needs to be changed to:
pool_items = SmartPool.find(id).send(item_assoc).collect {|x| x.id}
> @@ -23,7 +23,8 @@ class SmartPoolsController < PoolController
> before_filter :pre_modify, :only => [:add_hosts, :remove_hosts,
> :add_storage, :remove_storage,
> :add_vms, :remove_vms,
> - :add_pools, :remove_pools]
> + :add_pools, :remove_pools,
> + :add_items]
> def show_vms
> show
> end
> @@ -106,7 +107,7 @@ class SmartPoolsController < PoolController
> end
> find_opts = {:conditions => conditions}
> end
> - { :full_items => full_items, :find_opts => find_opts, :include_pool => :true}
> + { :full_items => full_items, :find_opts => find_opts, :include_pool => false}
> end
>
> def add_hosts
> @@ -154,6 +155,25 @@ class SmartPoolsController < PoolController
> end
> end
>
> + def add_items
> + class_and_ids_str = params[:class_and_ids]
> + class_and_ids = class_and_ids_str.split(",").collect {|x| x.split("_")}
> +
> + begin
> + @pool.transaction do
> + class_and_ids.each do |class_and_id|
> + @pool.add_item(class_and_id[0].constantize.find(class_and_id[1].to_i))
> + end
> + end
> + render :json => { :success => true,
> + :alert => "Add items to smart pool successful." }
> + rescue => ex
> + render :json => { :success => false,
> + :alert => "Add items to smart pool failed: " + ex.message }
> + end
> +
> + end
> +
> def destroy
> if @pool.destroy
> alert="Smart Pool was successfully deleted."
> diff --git a/src/app/models/host.rb b/src/app/models/host.rb
> index 546da19..429f0c0 100644
> --- a/src/app/models/host.rb
> +++ b/src/app/models/host.rb
> @@ -48,7 +48,8 @@ class Host < ActiveRecord::Base
> :values => [ [ :created_at, 0, "created_at", :date ],
> [ :updated_at, 1, "updated_at", :date ] ],
> :terms => [ [ :hostname, 'H', "hostname" ],
> - [ :search_users, 'U', "search_users" ] ]
> + [ :search_users, 'U', "search_users" ] ],
> + :eager_load => :smart_pools
>
>
> KVM_HYPERVISOR_TYPE = "KVM"
> diff --git a/src/app/models/pool.rb b/src/app/models/pool.rb
> index d189649..b25fa55 100644
> --- a/src/app/models/pool.rb
> +++ b/src/app/models/pool.rb
> @@ -89,7 +89,8 @@ class Pool < ActiveRecord::Base
> end
>
> acts_as_xapian :texts => [ :name ],
> - :terms => [ [ :search_users, 'U', "search_users" ] ]
> + :terms => [ [ :search_users, 'U', "search_users" ] ],
> + :eager_load => :smart_pools
>
> # this method lists pools with direct permission grants, but by default does
> # not include implied permissions (i.e. subtrees)
> diff --git a/src/app/models/smart_pool.rb b/src/app/models/smart_pool.rb
> index 9104ee5..0ecbe05 100644
> --- a/src/app/models/smart_pool.rb
> +++ b/src/app/models/smart_pool.rb
> @@ -39,8 +39,13 @@ class SmartPool < Pool
> end
>
> def add_item(item)
> - tag = SmartPoolTag.new(:smart_pool => self, :tagged => item)
> - tag.save!
> + begin
> + tag = SmartPoolTag.new(:smart_pool => self, :tagged => item)
> + tag.save!
> + rescue ActiveRecord::RecordInvalid
> + # this is thrown if the tagged item already belongs to the smart pool
> + # this operation should be a no-op rather than an error
> + end
> end
> def remove_item(item)
> smart_pool_tags.find(:first, :conditions=> {
> @@ -67,4 +72,27 @@ class SmartPool < Pool
> end
> end
>
> + def self.smart_pools_for_user(user)
> + nested_pools = DirectoryPool.get_smart_root.full_set_nested(
> + :privilege => Permission::PRIV_MODIFY, :user => user,
> + :smart_pool_set => true)
> + user_pools = []
> + other_pools = []
> + nested_pools.each do |pool_element|
> + pool = pool_element[:obj]
> + if pool.name == user
> + pool_element[:children].each do |child_element|
> + child_pool = child_element[:obj]
> + user_pools <<[child_pool.name, child_pool.id]
> + end
> + else
> + pool_element[:children].each do |child_element|
> + child_pool = child_element[:obj]
> + other_pools << [pool.name + " > " + child_pool.name, child_pool.id]
> + end
> + end
> + end
> + user_pools[-1] << "break"
> + user_pools + other_pools
> + end
> end
> diff --git a/src/app/models/storage_pool.rb b/src/app/models/storage_pool.rb
> index aed2902..9c550b8 100644
> --- a/src/app/models/storage_pool.rb
> +++ b/src/app/models/storage_pool.rb
> @@ -40,7 +40,8 @@ class StoragePool < ActiveRecord::Base
> validates_presence_of :hardware_pool_id
>
> acts_as_xapian :texts => [ :ip_addr, :target, :export_path, :type ],
> - :terms => [ [ :search_users, 'U', "search_users" ] ]
> + :terms => [ [ :search_users, 'U', "search_users" ] ],
> + :eager_load => :smart_pools
> ISCSI = "iSCSI"
> NFS = "NFS"
> LVM = "LVM"
> diff --git a/src/app/models/vm.rb b/src/app/models/vm.rb
> index 2eff87a..61c407c 100644
> --- a/src/app/models/vm.rb
> +++ b/src/app/models/vm.rb
> @@ -37,7 +37,8 @@ class Vm < ActiveRecord::Base
> :memory_allocated, :vnic_mac_addr
>
> acts_as_xapian :texts => [ :uuid, :description, :vnic_mac_addr, :state ],
> - :terms => [ [ :search_users, 'U', "search_users" ] ]
> + :terms => [ [ :search_users, 'U', "search_users" ] ],
> + :eager_load => :smart_pools
>
> BOOT_DEV_HD = "hd"
> BOOT_DEV_NETWORK = "network"
> diff --git a/src/app/views/hardware/show_hosts.rhtml b/src/app/views/hardware/show_hosts.rhtml
> index d33c920..2fd29bc 100644
> --- a/src/app/views/hardware/show_hosts.rhtml
> +++ b/src/app/views/hardware/show_hosts.rhtml
> @@ -5,6 +5,21 @@
> <a id="move_link" href="#" onClick="return validate_for_move();"><%= image_tag "icon_move.png", :style=>"vertical-align:middle;" %> Move</a>
> <a id="move_link_hidden" href="<%= url_for :controller => 'hardware', :action => 'move', :id => @pool, :resource_type=>'hosts' %>" rel="facebox[.bolder]" style="display:none" ></a>
> </li>
> + <li>
> + <%= image_tag "icon_smartpool.png", :style => "vertical-align:middle;" %> Add to Smart Pool <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %>
> + <ul>
> + <% smart_pools = SmartPool.smart_pools_for_user(@user) %>
> + <% smart_pools.each_index { |index| %>
> + <li onClick="add_hosts_to_smart_pool(<%=smart_pools[index][1]%>)"
> + <% if (index == smart_pools.length - 1) or smart_pools[index].length == 3 %>
> + style="border-bottom: 1px solid #CCCCCC;"
> + <% end %>
> + >
> + <%=smart_pools[index][0]%>
> + </li>
> + <% } %>
> + </ul>
> + </li>
> <% if @pool.id != HardwarePool.get_default_pool.id %>
> <li><a href="#" onClick="remove_hosts()"><%= image_tag "icon_remove.png" %> Remove</a></li>
> <% end %>
> @@ -22,6 +37,20 @@
> $('#move_link_hidden').click();
> }
> }
> + function add_hosts_to_smart_pool(smart_pool)
> + {
> + var hosts = get_selected_hosts();
> + if (validate_selected(hosts, "host")) {
> + $.post('<%= url_for :controller => "smart_pools", :action => "add_hosts" %>',
> + { resource_ids: hosts.toString(), id: smart_pool },
> + function(data,status){
> + $('#hosts_grid').flexReload();
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> + }
> function remove_hosts()
> {
> var hosts = get_selected_hosts();
> diff --git a/src/app/views/hardware/show_storage.rhtml b/src/app/views/hardware/show_storage.rhtml
> index 6466f9b..5ade456 100644
> --- a/src/app/views/hardware/show_storage.rhtml
> +++ b/src/app/views/hardware/show_storage.rhtml
> @@ -6,6 +6,21 @@
> <a id="move_link_hidden" href="<%= url_for :controller => 'hardware', :action => 'move', :id => @pool, :resource_type=>'storage' %>" rel="facebox[.bolder]" style="display:none" ></a>
> </li>
> <li>
> + <%= image_tag "icon_smartpool.png", :style => "vertical-align:middle;" %> Add to Smart Pool <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %>
> + <ul>
> + <% smart_pools = SmartPool.smart_pools_for_user(@user) %>
> + <% smart_pools.each_index { |index| %>
> + <li onClick="add_storage_to_smart_pool(<%=smart_pools[index][1]%>)"
> + <% if (index == smart_pools.length - 1) or smart_pools[index].length == 3 %>
> + style="border-bottom: 1px solid #CCCCCC;"
> + <% end %>
> + >
> + <%=smart_pools[index][0]%>
> + </li>
> + <% } %>
> + </ul>
> + </li>
> + <li>
> <a href="#" onClick="return validate_storage_for_remove();" ><%= image_tag "icon_remove.png", :style=>"vertical-align:middle;" %> Remove</a>
> <a id="remove_link_hidden" href="<%= url_for :controller => 'hardware', :action => 'removestorage', :id => @pool %>" rel="facebox[.bolder]" style="display:none" ></a>
> </li>
> @@ -13,6 +28,20 @@
> </div>
>
> <script type="text/javascript">
> + function add_storage_to_smart_pool(smart_pool)
> + {
> + var storage = get_selected_storage();
> + if (validate_selected(storage, "storage pool")) {
> + $.post('<%= url_for :controller => "smart_pools", :action => "add_storage" %>',
> + { resource_ids: storage.toString(), id: smart_pool },
> + function(data,status){
> + $('#storage_grid').flexReload();
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> + }
> function remove_storage()
> {
> var storage = get_selected_storage();
> diff --git a/src/app/views/hardware/show_vms.rhtml b/src/app/views/hardware/show_vms.rhtml
> index ee14758..6a8ded5 100644
> --- a/src/app/views/hardware/show_vms.rhtml
> +++ b/src/app/views/hardware/show_vms.rhtml
> @@ -1,6 +1,21 @@
> <div id="toolbar_nav">
> <ul>
> <li><a href="<%= url_for :controller => 'resources', :action => 'new', :parent_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_add_vmpool.png", :style => "vertical-align:middle;" %> New Virtual Machine Pool</a></li>
> + <li>
> + <%= image_tag "icon_smartpool.png", :style => "vertical-align:middle;" %> Add to Smart Pool <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %>
> + <ul>
> + <% smart_pools = SmartPool.smart_pools_for_user(@user) %>
> + <% smart_pools.each_index { |index| %>
> + <li onClick="add_vm_pools_to_smart_pool(<%=smart_pools[index][1]%>)"
> + <% if (index == smart_pools.length - 1) or smart_pools[index].length == 3 %>
> + style="border-bottom: 1px solid #CCCCCC;"
> + <% end %>
> + >
> + <%=smart_pools[index][0]%>
> + </li>
> + <% } %>
> + </ul>
> + </li>
> <li><a href="#" onClick="delete_vm_pools()"><%= image_tag "icon_delete_white.png", :style => "vertical-align:middle;" %> Delete</a></li>
> </ul>
> </div>
> @@ -9,6 +24,20 @@
> {
> return get_selected_checkboxes("vmpools_grid_form");
> }
> + function add_vm_pools_to_smart_pool(smart_pool)
> + {
> + var vm_pools = get_selected_vm_pools();
> + if (validate_selected(vm_pools, "vm pool")) {
> + $.post('<%= url_for :controller => "smart_pools", :action => "add_pools" %>',
> + { resource_ids: vm_pools.toString(), id: smart_pool },
> + function(data,status){
> + $('#vmpools_grid').flexReload();
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> + }
> function delete_vm_pools()
> {
> var vm_pools = get_selected_vm_pools();
> diff --git a/src/app/views/resources/show_vms.rhtml b/src/app/views/resources/show_vms.rhtml
> index beca048..6f757f9 100644
> --- a/src/app/views/resources/show_vms.rhtml
> +++ b/src/app/views/resources/show_vms.rhtml
> @@ -16,6 +16,21 @@
> <% } %>
> </ul>
> </li>
> + <li>
> + <%= image_tag "icon_smartpool.png", :style => "vertical-align:middle;" %> Add to Smart Pool <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %>
> + <ul>
> + <% smart_pools = SmartPool.smart_pools_for_user(@user) %>
> + <% smart_pools.each_index { |index| %>
> + <li onClick="add_vms_to_smart_pool(<%=smart_pools[index][1]%>)"
> + <% if (index == smart_pools.length - 1) or smart_pools[index].length == 3 %>
> + style="border-bottom: 1px solid #CCCCCC;"
> + <% end %>
> + >
> + <%=smart_pools[index][0]%>
> + </li>
> + <% } %>
> + </ul>
> + </li>
> <li><a href="#" onClick="delete_vms()"><%= image_tag "icon_delete_white.png", :style => "vertical-align:middle;" %> Delete</a></li>
> </ul>
> </div>
> @@ -24,6 +39,20 @@
> {
> return get_selected_checkboxes("vms_grid_form");
> }
> + function add_vms_to_smart_pool(smart_pool)
> + {
> + var vms = get_selected_vms();
> + if (validate_selected(vms, "vm")) {
> + $.post('<%= url_for :controller => "smart_pools", :action => "add_vms" %>',
> + { resource_ids: vms.toString(), id: smart_pool },
> + function(data,status){
> + $('#vms_grid').flexReload();
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> + }
> function delete_vms()
> {
> var vms = get_selected_vms();
> diff --git a/src/app/views/search/_grid.rhtml b/src/app/views/search/_grid.rhtml
> index 2e60646..fca1ba0 100644
> --- a/src/app/views/search/_grid.rhtml
> +++ b/src/app/views/search/_grid.rhtml
> @@ -18,7 +18,8 @@
> <%= "{display: '', width : 20, align: 'left', process: #{table_id}checkbox}," if checkboxes %>
> {display: 'Name', width : 200, align: 'left'},
> {display: 'Type', width : 120, align: 'left'},
> - {display: '% Match', width : 60, align: 'left'}
> + {display: '% Match', width : 60, align: 'left'},
> + {display: 'Smart Pools', width : 200, align: 'left'}
> ],
> //sortname: "hostname",
> //sortorder: "asc",
> diff --git a/src/app/views/search/results.rhtml b/src/app/views/search/results.rhtml
> index a7641b7..1989054 100644
> --- a/src/app/views/search/results.rhtml
> +++ b/src/app/views/search/results.rhtml
> @@ -5,9 +5,25 @@
> <input id="searchform-field" name="terms" value="<%=@terms%>" onkeypress="" type="text">
> <input id="searchform-button" src="<%= image_path "icon_search.png"%>" title="Search" type="image">
> <input id="searchform-model" type="hidden" name="model" value="<%=@model_param%>">
> + Search
> </li>
> <li>
> - <%= image_tag "icon_move.png", :style => "vertical-align:middle;" %> Actions <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %>
> + <%= image_tag "icon_smartpool.png", :style => "vertical-align:middle;" %> Add to Smart Pool <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %>
> + <ul>
> + <% smart_pools = SmartPool.smart_pools_for_user(@user) %>
> + <% smart_pools.each_index { |index| %>
> + <li onClick="add_results_to_smart_pool(<%=smart_pools[index][1]%>)"
> + <% if (index == smart_pools.length - 1) or smart_pools[index].length == 3 %>
> + style="border-bottom: 1px solid #CCCCCC;"
> + <% end %>
> + >
> + <%=smart_pools[index][0]%>
> + </li>
> + <% } %>
> + </ul>
> + </li>
> + <li>
> + Show All <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %>
> <ul>
> <% @types.each_index { |index| %>
> <!-- for each button we need to submit current form with "model" set to @types[index][1] --!>
> @@ -40,6 +56,24 @@
> { class_and_id: selected_ids[0].substring(3)})
> }
> }
Not for this patch, but I would like to see us consolidate all these
get_selected_* functions into one that takes the id, seems like we have
a lot of functions doing almost the same thing now.
/me puts that on his cleanup todo list..
> + function get_selected_results()
> + {
> + return get_selected_checkboxes("search_grid_form")
> + }
> + function add_results_to_smart_pool(smart_pool)
> + {
> + var results = get_selected_results();
> + if (validate_selected(results, "search result")) {
> + $.post('<%= url_for :controller => "smart_pools", :action => "add_items" %>',
> + { class_and_ids: results.toString(), id: smart_pool },
> + function(data,status){
> + $('#search_grid').flexReload();
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> + }
> </script>
>
> <div class="panel_header"></div>
> @@ -48,7 +82,7 @@
> <%= render :partial => "/search/grid", :locals => { :table_id => "search_grid",
> :terms => @terms,
> :model => @model_param,
> - :checkboxes => false,
> + :checkboxes => true,
> :on_select => "results_select" } %>
> </div>
> <div class="selection_detail" id="results_selection">
> diff --git a/src/app/views/vm/_grid.rhtml b/src/app/views/vm/_grid.rhtml
> index 85bf094..b137de6 100644
> --- a/src/app/views/vm/_grid.rhtml
> +++ b/src/app/views/vm/_grid.rhtml
> @@ -29,7 +29,7 @@
> {display: '', name : 'id', width : 20, sortable : false, align: 'left', process: <%= table_id %>checkbox},
> {display: 'Description', name : 'description', width : 180, sortable : true, align: 'left'},
> {display: 'UUID', name : 'uuid', width : 180, sortable : true, align: 'left'},
> - <% if @pool.get_hardware_pool.can_view(@user) %>
> + <% if (pool.is_a? VmResourcePool) and pool.get_hardware_pool.can_view(@user) %>
> {display: 'Host', name : 'host', width: 180, sortable : true, align: 'left' },
> <% end %>
> {display: 'CPUs', name : 'num_vcpus_allocated', width : 40, sortable : true, align: 'left'},
>
ACK, pending the change mentioned above. All functionality works for me.
More information about the ovirt-devel
mailing list