[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