[Ovirt-devel] [PATCH] added smart pool UI bits to search results and other flexigrids

Scott Seago sseago at redhat.com
Wed Oct 22 22:16:46 UTC 2008


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
@@ -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)})
     }
   }
+  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'},
-- 
1.5.5.1




More information about the ovirt-devel mailing list