[Ovirt-devel] [PATCH] finished smart pools implementation. (revised)
Jason Guiditta
jguiditt at redhat.com
Fri Sep 19 15:56:32 UTC 2008
This works for me, AYE(ACK for non-pirates). However, I noted some
occasional weirdness with refresh from no grid to having a grid. If you
go to a different tab after adding an item and then come back, it works
fine. This is not a functional problem though, so it might just be some
odd behaviour by my browser. If not, we can address as a bug.
-j
On Thu, 2008-09-18 at 17:06 -0400, Scott Seago wrote:
> Nav now works for smart pools (but Jay's going to do some tweaking). All of the smart pool tabs work properly with add/remove functions, although summary is stubbed out.
> search results are not yet integrated with smart pools.
>
> Signed-off-by: Scott Seago <sseago at redhat.com>
> ---
> src/app/controllers/application.rb | 13 +-
> src/app/controllers/hardware_controller.rb | 122 +++--------
> src/app/controllers/host_controller.rb | 5 +
> src/app/controllers/pool_controller.rb | 31 +++-
> src/app/controllers/resources_controller.rb | 4 +-
> src/app/controllers/smart_pool_controller.rb | 22 --
> src/app/controllers/smart_pools_controller.rb | 239 ++++++++++++++++++++
> src/app/controllers/storage_controller.rb | 5 +
> src/app/controllers/tree_controller.rb | 14 +-
> src/app/controllers/vm_controller.rb | 5 +
> src/app/models/directory_pool.rb | 1 +
> src/app/models/pool.rb | 42 +++-
> src/app/models/smart_pool.rb | 23 ++
> src/app/views/hardware/_move_menu.rhtml | 17 --
> src/app/views/hardware/show_hosts.rhtml | 20 +-
> src/app/views/hardware/show_storage.rhtml | 14 +-
> src/app/views/hardware/show_vms.rhtml | 2 +-
> src/app/views/host/_grid.rhtml | 14 +-
> src/app/views/host/add_to_smart_pool.rhtml | 28 +++
> src/app/views/host/addhost.html.erb | 2 +-
> src/app/views/layouts/_navigation_tabs.rhtml | 17 ++
> src/app/views/layouts/_side_toolbar.rhtml | 45 +++--
> src/app/views/layouts/_tree.rhtml | 6 +-
> src/app/views/layouts/redux.rhtml | 26 --
> src/app/views/resources/show_vms.rhtml | 8 +-
> src/app/views/smart_pools/_form.rhtml | 6 +
> src/app/views/smart_pools/_pools_grid.rhtml | 39 ++++
> src/app/views/smart_pools/add_pool_dialog.rhtml | 52 +++++
> src/app/views/smart_pools/new.rhtml | 26 ++
> src/app/views/smart_pools/show.rhtml | 17 ++
> .../{hardware => smart_pools}/show_hosts.rhtml | 64 ++---
> src/app/views/smart_pools/show_pools.rhtml | 74 ++++++
> src/app/views/smart_pools/show_storage.rhtml | 72 ++++++
> src/app/views/smart_pools/show_users.rhtml | 2 +
> src/app/views/smart_pools/show_vms.rhtml | 77 +++++++
> src/app/views/storage/_grid.rhtml | 19 ++-
> src/app/views/storage/add_to_smart_pool.rhtml | 22 ++
> src/app/views/user/_show.rhtml | 4 +-
> src/app/views/vm/_grid.rhtml | 70 ++++---
> src/app/views/vm/add_to_smart_pool.rhtml | 27 +++
> src/db/migrate/017_add_smart_pools.rb | 2 +-
> .../jquery-treeview/jquery.treeview.async.js | 2 +-
> src/public/javascripts/jquery.ovirt.treeview.js | 12 +-
> src/public/javascripts/ovirt.js | 98 ++++++++-
> 44 files changed, 1112 insertions(+), 298 deletions(-)
> delete mode 100644 src/app/controllers/smart_pool_controller.rb
> create mode 100644 src/app/controllers/smart_pools_controller.rb
> delete mode 100644 src/app/views/hardware/_move_menu.rhtml
> create mode 100644 src/app/views/host/add_to_smart_pool.rhtml
> create mode 100644 src/app/views/smart_pools/_form.rhtml
> create mode 100644 src/app/views/smart_pools/_pools_grid.rhtml
> create mode 100644 src/app/views/smart_pools/add_pool_dialog.rhtml
> create mode 100644 src/app/views/smart_pools/new.rhtml
> create mode 100644 src/app/views/smart_pools/show.rhtml
> copy src/app/views/{hardware => smart_pools}/show_hosts.rhtml (50%)
> create mode 100644 src/app/views/smart_pools/show_pools.rhtml
> create mode 100644 src/app/views/smart_pools/show_storage.rhtml
> create mode 100644 src/app/views/smart_pools/show_users.rhtml
> create mode 100644 src/app/views/smart_pools/show_vms.rhtml
> create mode 100644 src/app/views/storage/add_to_smart_pool.rhtml
> create mode 100644 src/app/views/vm/add_to_smart_pool.rhtml
>
> diff --git a/src/app/controllers/application.rb b/src/app/controllers/application.rb
> index 3126748..6dcf6f8 100644
> --- a/src/app/controllers/application.rb
> +++ b/src/app/controllers/application.rb
> @@ -89,7 +89,7 @@ class ApplicationController < ActionController::Base
> end
>
> # don't define find_opts for array inputs
> - def json_hash(full_items, attributes, arg_list=[], find_opts={})
> + def json_hash(full_items, attributes, arg_list=[], find_opts={}, id_method=:id)
> page = params[:page].to_i
> paginate_opts = {:page => page,
> :order => "#{params[:sortname]} #{params[:sortorder]}",
> @@ -101,7 +101,7 @@ class ApplicationController < ActionController::Base
> json_hash[:total] = item_list.total_entries
> json_hash[:rows] = item_list.collect do |item|
> item_hash = {}
> - item_hash[:id] = item.id
> + item_hash[:id] = item.send(id_method)
> item_hash[:cell] = attributes.collect do |attr|
> if attr.is_a? Array
> value = item
> @@ -115,9 +115,12 @@ class ApplicationController < ActionController::Base
> end
> json_hash
> end
> - # don't define find_opts for array inputs
> - def json_list(full_items, attributes, arg_list=[], find_opts={})
> - render :json => json_hash(full_items, attributes, arg_list, find_opts).to_json
> +
> + # json_list is a helper method used to format data for paginated flexigrid tables
> + #
> + # FIXME: what is the intent of this comment? don't define find_opts for array inputs
> + def json_list(full_items, attributes, arg_list=[], find_opts={}, id_method=:id)
> + render :json => json_hash(full_items, attributes, arg_list, find_opts, id_method).to_json
> end
>
>
> diff --git a/src/app/controllers/hardware_controller.rb b/src/app/controllers/hardware_controller.rb
> index a366e4c..42ff9cb 100644
> --- a/src/app/controllers/hardware_controller.rb
> +++ b/src/app/controllers/hardware_controller.rb
> @@ -1,4 +1,4 @@
> -#
> +#
> # Copyright (C) 2008 Red Hat, Inc.
> # Written by Scott Seago <sseago at redhat.com>
> #
> @@ -20,10 +20,6 @@
>
> class HardwareController < PoolController
>
> - XML_OPTS = {
> - :include => [ :storage_pools, :hosts, :quota ]
> - }
> -
> EQ_ATTRIBUTES = [ :name, :parent_id ]
>
> verify :method => [:post, :put], :only => [ :create, :update ],
> @@ -59,12 +55,12 @@ class HardwareController < PoolController
> end
>
> def json_view_tree
> - json_tree_internal(Permission::PRIV_VIEW, false)
> + json_tree_internal(Permission::PRIV_VIEW, :select_hardware_and_vm_pools)
> end
> def json_move_tree
> - json_tree_internal(Permission::PRIV_MODIFY, true)
> + json_tree_internal(Permission::PRIV_MODIFY, :select_hardware_pools)
> end
> - def json_tree_internal(privilege, filter_vm_pools)
> + def json_tree_internal(privilege, filter_method)
> id = params[:id]
> if id
> @pool = Pool.find(id)
> @@ -77,11 +73,9 @@ class HardwareController < PoolController
> end
> if @pool
> pools = @pool.children
> - pools = Pool.select_hardware_pools(pools) if filter_vm_pools
> open_list = []
> else
> pools = Pool.list_for_user(get_login_user,Permission::PRIV_VIEW)
> - pools = Pool.select_hardware_pools(pools) if filter_vm_pools
> current_id = params[:current_id]
> if current_id
> current_pool = Pool.find(current_id)
> @@ -90,26 +84,26 @@ class HardwareController < PoolController
> open_list = []
> end
> end
> + pools = Pool.send(filter_method, pools)
>
> - render :json => Pool.nav_json(pools, open_list, filter_vm_pools)
> + render :json => Pool.nav_json(pools, open_list,
> + (filter_method==:select_hardware_pools))
> end
>
> def show_vms
> show
> end
>
> - def show_hosts
> - @hardware_pools = HardwarePool.find :all
> + def show_hosts
> show
> end
> -
> +
> def show_graphs
> show
> end
>
> def show_storage
> show
> - @hardware_pools = HardwarePool.find :all
> end
>
> def show_tasks
> @@ -142,21 +136,16 @@ class HardwareController < PoolController
> # filtering on which pool to exclude
> id = params[:exclude_pool]
> hosts = Host
> - find_opts = {:include => :hardware_pool,
> + find_opts = {:include => :hardware_pool,
> :conditions => ["pools.id != ?", id]}
> include_pool = true
> end
> - attr_list = []
> - attr_list << :id if params[:checkboxes]
> - attr_list << :hostname
> - attr_list << [:hardware_pool, :name] if include_pool
> - attr_list += [:uuid, :hypervisor_type, :num_cpus, :cpu_speed, :arch, :memory_in_mb, :status_str, :load_average]
> - json_list(hosts, attr_list, [:all], find_opts)
> + super(:full_items => hosts,:include_pool => include_pool,:find_opts => find_opts)
> end
>
> def vm_pools_json
> - json_list(Pool,
> - [:id, :name, :id],
> + json_list(Pool,
> + [:id, :name, :id],
> [@pool, :children],
> {:finder => 'call_finder', :conditions => ["type = 'VmResourcePool'"]})
> end
> @@ -172,24 +161,22 @@ class HardwareController < PoolController
> # filtering on which pool to exclude
> id = params[:exclude_pool]
> storage_pools = StoragePool
> - find_opts = {:include => :hardware_pool,
> + find_opts = {:include => :hardware_pool,
> :conditions => ["pools.id != ?", id]}
> include_pool = true
> end
> - attr_list = [:id, :display_name, :ip_addr, :get_type_label]
> - attr_list.insert(2, [:hardware_pool, :name]) if include_pool
> - json_list(storage_pools, attr_list, [:all], find_opts)
> + super(:full_items => storage_pools,:include_pool => include_pool,:find_opts => find_opts)
> end
>
> def storage_volumes_json
> - json_list(@pool.all_storage_volumes,
> + json_list(@pool.all_storage_volumes,
> [:display_name, :size_in_gb, :get_type_label])
> end
>
> def move
> pre_modify
> @resource_type = params[:resource_type]
> - render :layout => 'popup'
> + render :layout => 'popup'
> end
>
> def new
> @@ -279,87 +266,44 @@ class HardwareController < PoolController
> end
> end
>
> - #FIXME: we need permissions checks. user must have permission on src pool
> - # in addition to the current pool (which is checked). We also need to fail
> - # for hosts that aren't currently empty
> def add_hosts
> - host_ids_str = params[:resource_ids]
> - host_ids = host_ids_str.split(",").collect {|x| x.to_i}
> -
> - begin
> - @pool.transaction do
> - @pool.move_hosts(host_ids, @pool.id)
> - end
> - render :json => { :object => "host", :success => true,
> - :alert => "Hosts were successfully added to this Hardware pool." }
> - rescue
> - render :json => { :object => "host", :success => false,
> - :alert => "Error adding Hosts to this Hardware pool." }
> - end
> + edit_items(Host, :move_hosts, @pool.id, :add)
> end
>
> - #FIXME: we need permissions checks. user must have permission on src pool
> - # in addition to the current pool (which is checked). We also need to fail
> - # for hosts that aren't currently empty
> def move_hosts
> - target_pool_id = params[:target_pool_id]
> - host_ids_str = params[:resource_ids]
> - host_ids = host_ids_str.split(",").collect {|x| x.to_i}
> -
> - begin
> - @pool.transaction do
> - @pool.move_hosts(host_ids, target_pool_id)
> - end
> - render :json => { :object => "host", :success => true,
> - :alert => "Hosts were successfully moved." }
> - rescue
> - render :json => { :object => "host", :success => false,
> - :alert => "Error moving hosts." }
> - end
> + edit_items(Host, :move_hosts, params[:target_pool_id], :move)
> end
>
> - #FIXME: we need permissions checks. user must have permission on src pool
> - # in addition to the current pool (which is checked). We also need to fail
> - # for storage that aren't currently empty
> def add_storage
> - storage_pool_ids_str = params[:resource_ids]
> - storage_pool_ids = storage_pool_ids_str.split(",").collect {|x| x.to_i}
> -
> - begin
> - @pool.transaction do
> - @pool.move_storage(storage_pool_ids, @pool.id)
> - end
> - render :json => { :object => "storage_pool", :success => true,
> - :alert => "Storage Pools were successfully added to this Hardware pool." }
> - rescue
> - render :json => { :object => "storage_pool", :success => false,
> - :alert => "Error adding storage pools to this Hardware pool." }
> - end
> + edit_items(StoragePool, :move_storage, @pool.id, :add)
> + end
> +
> + def move_storage
> + edit_items(StoragePool, :move_storage, params[:target_pool_id], :move)
> end
>
> #FIXME: we need permissions checks. user must have permission on src pool
> # in addition to the current pool (which is checked). We also need to fail
> # for storage that aren't currently empty
> - def move_storage
> - target_pool_id = params[:target_pool_id]
> - storage_pool_ids_str = params[:resource_ids]
> - storage_pool_ids = storage_pool_ids_str.split(",").collect {|x| x.to_i}
> + def edit_items(item_class, item_method, target_pool_id, item_action)
> + resource_ids_str = params[:resource_ids]
> + resource_ids = resource_ids_str.split(",").collect {|x| x.to_i}
>
> begin
> @pool.transaction do
> - @pool.move_storage(storage_pool_ids, target_pool_id)
> + @pool.send(item_method, resource_ids, target_pool_id)
> end
> - render :json => { :object => "storage_pool", :success => true,
> - :alert => "Storage Pools were successfully moved." }
> + render :json => { :success => true,
> + :alert => "#{item_action.to_s} #{item_class.table_name.humanize} successful." }
> rescue
> - render :json => { :object => "storage_pool", :success => false,
> - :alert => "Error moving storage pools." }
> + render :json => { :success => false,
> + :alert => "#{item_action.to_s} #{item_class.table_name.humanize} failed." }
> end
> end
>
> def removestorage
> pre_modify
> - render :layout => 'popup'
> + render :layout => 'popup'
> end
>
> def destroy
> diff --git a/src/app/controllers/host_controller.rb b/src/app/controllers/host_controller.rb
> index 5174c88..417d11f 100644
> --- a/src/app/controllers/host_controller.rb
> +++ b/src/app/controllers/host_controller.rb
> @@ -84,6 +84,11 @@ class HostController < ApplicationController
> render :layout => 'popup'
> end
>
> + def add_to_smart_pool
> + @pool = SmartPool.find(params[:smart_pool_id])
> + render :layout => 'popup'
> + end
> +
> def new
> end
>
> diff --git a/src/app/controllers/pool_controller.rb b/src/app/controllers/pool_controller.rb
> index ce41701..02ef290 100644
> --- a/src/app/controllers/pool_controller.rb
> +++ b/src/app/controllers/pool_controller.rb
> @@ -23,9 +23,14 @@ class PoolController < ApplicationController
> before_filter :pre_show_pool, :only => [:show_vms, :show_users,
> :show_hosts, :show_storage,
> :users_json, :show_tasks, :tasks,
> - :vms_json, :vm_pools_json,
> + :vm_pools_json,
> + :pools_json, :show_pools,
> :storage_volumes_json, :quick_summary]
>
> + XML_OPTS = {
> + :include => [ :storage_pools, :hosts, :quota ]
> + }
> +
> def show
> respond_to do |format|
> format.html {
> @@ -86,6 +91,28 @@ class PoolController < ApplicationController
> json_hash(@pool.tasks, attr_list, [:all], find_opts)
> end
>
> + def hosts_json(args)
> + attr_list = []
> + attr_list << :id if params[:checkboxes]
> + attr_list << :hostname
> + attr_list << [:hardware_pool, :name] if args[:include_pool]
> + attr_list += [:uuid, :hypervisor_type, :num_cpus, :cpu_speed, :arch, :memory_in_mb, :status_str, :load_average]
> + json_list(args[:full_items], attr_list, [:all], args[:find_opts])
> + end
> +
> + def storage_pools_json(args)
> + attr_list = [:id, :display_name, :ip_addr, :get_type_label]
> + attr_list.insert(2, [:hardware_pool, :name]) if args[:include_pool]
> + json_list(args[:full_items], attr_list, [:all], args[:find_opts])
> + end
> +
> + def vms_json(args)
> + attr_list = [:id, :description, :uuid,
> + :num_vcpus_allocated, :memory_allocated_in_mb,
> + :vnic_mac_addr, :state, :id]
> + json_list(args[:full_items], attr_list, [:all], args[:find_opts])
> + end
> +
> def new
> render :layout => 'popup'
> end
> @@ -120,7 +147,7 @@ class PoolController < ApplicationController
> @current_pool_id=@pool.id
> set_perms(@perm_obj)
> unless @can_view
> - flash[:notice] = 'You do not have permission to view this pool pool: redirecting to top level'
> + flash[:notice] = 'You do not have permission to view this pool: redirecting to top level'
> respond_to do |format|
> format.html { redirect_to :controller => "dashboard" }
> format.xml { head :forbidden }
> diff --git a/src/app/controllers/resources_controller.rb b/src/app/controllers/resources_controller.rb
> index a0a65a6..2c54ccc 100644
> --- a/src/app/controllers/resources_controller.rb
> +++ b/src/app/controllers/resources_controller.rb
> @@ -68,8 +68,8 @@ class ResourcesController < PoolController
> end
>
> def vms_json
> - json_list(@pool.vms,
> - [:id, :description, :uuid, :num_vcpus_allocated, :memory_allocated_in_mb, :vnic_mac_addr, :state, :id])
> + pre_show
> + super(:full_items => @pool.vms, :find_opts => {}, :include_pool => :true)
> end
>
> def create
> diff --git a/src/app/controllers/smart_pool_controller.rb b/src/app/controllers/smart_pool_controller.rb
> deleted file mode 100644
> index eb087a6..0000000
> --- a/src/app/controllers/smart_pool_controller.rb
> +++ /dev/null
> @@ -1,22 +0,0 @@
> -#
> -# Copyright (C) 2008 Red Hat, Inc.
> -# Written by Scott Seago <sseago at redhat.com>
> -#
> -# This program is free software; you can redistribute it and/or modify
> -# it under the terms of the GNU General Public License as published by
> -# the Free Software Foundation; version 2 of the License.
> -#
> -# This program is distributed in the hope that it will be useful,
> -# but WITHOUT ANY WARRANTY; without even the implied warranty of
> -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> -# GNU General Public License for more details.
> -#
> -# You should have received a copy of the GNU General Public License
> -# along with this program; if not, write to the Free Software
> -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> -# MA 02110-1301, USA. A copy of the GNU General Public License is
> -# also available at http://www.gnu.org/copyleft/gpl.html.
> -#
> -
> -class SmartPoolController < ApplicationController
> -end
> diff --git a/src/app/controllers/smart_pools_controller.rb b/src/app/controllers/smart_pools_controller.rb
> new file mode 100644
> index 0000000..99ae8b8
> --- /dev/null
> +++ b/src/app/controllers/smart_pools_controller.rb
> @@ -0,0 +1,239 @@
> +#
> +# Copyright (C) 2008 Red Hat, Inc.
> +# Written by Scott Seago <sseago at redhat.com>
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; version 2 of the License.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> +# MA 02110-1301, USA. A copy of the GNU General Public License is
> +# also available at http://www.gnu.org/copyleft/gpl.html.
> +#
> +
> +class SmartPoolsController < PoolController
> +
> + before_filter :pre_modify, :only => [:add_hosts, :remove_hosts,
> + :add_storage, :remove_storage,
> + :add_vms, :remove_vms,
> + :add_pools, :remove_pools]
> + def show_vms
> + show
> + end
> +
> + def show_hosts
> + show
> + end
> +
> + def show_pools
> + show
> + end
> +
> + def show_storage
> + show
> + end
> +
> + def create
> + begin
> + @pool.create_with_parent(@parent)
> + render :json => { :object => "smart_pool", :success => true,
> + :alert => "Smart Pool was successfully created." }
> + rescue
> + render :json => { :object => "smart_pool", :success => false,
> + :errors => @pool.errors.localize_error_messages.to_a}
> + end
> + end
> +
> + def update
> + begin
> + @pool.update_attributes!(params[:smart_pool])
> + render :json => { :object => "smart_pool", :success => true,
> + :alert => "Smart Pool was successfully modified." }
> + rescue
> + render :json => { :object => "smart_pool", :success => false,
> + :errors => @pool.errors.localize_error_messages.to_a}
> + end
> + end
> +
> + def add_pool_dialog
> + pre_modify
> + @selected_pools = @pool.tagged_pools.collect {|pool| pool.id}
> + render :layout => 'popup'
> + end
> +
> + def hosts_json
> + super(items_json_internal(Host, :tagged_hosts))
> + end
> +
> + def storage_pools_json
> + super(items_json_internal(StoragePool, :tagged_storage_pools))
> + end
> +
> + def vms_json
> + super(items_json_internal(Vm, :tagged_vms))
> + end
> +
> + def pools_json
> + args = items_json_internal(Pool, :tagged_pools)
> + attr_list = [:id, :name, :get_type_label]
> + json_list(args[:full_items], attr_list, [:all], args[:find_opts], :class_and_id)
> +
> + end
> +
> + def items_json_internal(item_class, item_assoc)
> + if params[:id]
> + pre_show
> + full_items = @pool.send(item_assoc)
> + find_opts = {}
> + else
> + # FIXME: no permissions or usage checks here yet
> + # filtering on which pool to exclude
> + id = params[:exclude_pool]
> + full_items = item_class
> + pool_items = SmartPool.find(id,
> + :include => item_assoc).send(item_assoc).collect {|x| x.id}
> + if pool_items.empty?
> + conditions = []
> + else
> + conditions = ["#{item_class.table_name}.id not in (?)", pool_items]
> + end
> + find_opts = {:conditions => conditions}
> + end
> + { :full_items => full_items, :find_opts => find_opts, :include_pool => :true}
> + end
> +
> + def add_hosts
> + edit_items(Host, :add_items, :add)
> + end
> +
> + def remove_hosts
> + edit_items(Host, :remove_items, :remove)
> + end
> +
> + def add_storage
> + edit_items(StoragePool, :add_items, :add)
> + end
> +
> + def remove_storage
> + edit_items(StoragePool, :remove_items, :remove)
> + end
> +
> + def add_vms
> + edit_items(Vm, :add_items, :add)
> + end
> +
> + def remove_vms
> + edit_items(Vm, :remove_items, :remove)
> + end
> +
> + def add_pools
> + edit_items(Pool, :add_items, :add)
> + end
> +
> + def remove_pools
> + edit_items(Pool, :remove_items, :remove)
> + end
> +
> + def edit_items(item_class, item_method, item_action)
> + resource_ids_str = params[:resource_ids]
> + resource_ids = resource_ids_str.split(",").collect {|x| x.to_i}
> + begin
> + @pool.send(item_method,item_class, resource_ids)
> + render :json => { :success => true,
> + :alert => "#{item_action.to_s} #{item_class.table_name.humanize} successful." }
> + rescue
> + render :json => { :success => false,
> + :alert => "#{item_action.to_s} #{item_class.table_name.humanize} failed." }
> + end
> + end
> +
> + def destroy
> + if @pool.destroy
> + alert="Smart Pool was successfully deleted."
> + success=true
> + else
> + alert="Failed to delete Smart pool."
> + success=false
> + end
> + render :json => { :object => "smart_pool", :success => success, :alert => alert }
> + end
> +
> + # handled
> + # show_hosts
> + # show_graphs
> + # show_storage
> + # show
> + # show_vms
> + # show_tasks
> + # new xxx
> + # create xxx
> + # hosts_json
> + # storage_pools_json
> + # add_hosts
> + # move_hosts
> + # add_storage
> + # move_storage
> + # removestorage
> +
> + #HW only
> + # json_view_tree
> + # json_move_tree
> + # vm_pools_json
> + # move
> + #VM only
> + # vms_json
> + # delete
> + # vm_actions
> + #both
> + # move
> + # update
> + # destroy
> +
> + #inherited
> + # used
> + # new
> + # edit
> + # show_users
> + # users_json
> + # unneeded
> + # tasks
> + # show_tasks
> + # quick_summary
> +
> + protected
> + #filter methods
> + def pre_new
> + @pool = SmartPool.new
> + @parent = DirectoryPool.get_or_create_user_root(get_login_user)
> + @perm_obj = @parent
> + @current_pool_id=@parent.id
> + end
> + def pre_create
> + @pool = SmartPool.new(params[:smart_pool])
> + @parent = DirectoryPool.get_or_create_user_root(get_login_user)
> + @perm_obj = @parent
> + @current_pool_id=@parent.id
> + end
> + def pre_edit
> + @pool = SmartPool.find(params[:id])
> + @parent = @pool.parent
> + @perm_obj = @pool
> + @current_pool_id=@pool.id
> + end
> + def pre_show
> + @pool = SmartPool.find(params[:id])
> + super
> + end
> + def pre_modify
> + pre_edit
> + authorize_admin
> + end
> +
> +end
> diff --git a/src/app/controllers/storage_controller.rb b/src/app/controllers/storage_controller.rb
> index 7e97764..7eec618 100644
> --- a/src/app/controllers/storage_controller.rb
> +++ b/src/app/controllers/storage_controller.rb
> @@ -199,6 +199,11 @@ class StorageController < ApplicationController
> render :layout => false
> end
>
> + def add_to_smart_pool
> + @pool = SmartPool.find(params[:smart_pool_id])
> + render :layout => 'popup'
> + end
> +
> #FIXME: we need permissions checks. user must have permission on src pool
> # in addition to the current pool (which is checked). We also need to fail
> # for storage that aren't currently empty
> diff --git a/src/app/controllers/tree_controller.rb b/src/app/controllers/tree_controller.rb
> index 5ad8426..1aed544 100644
> --- a/src/app/controllers/tree_controller.rb
> +++ b/src/app/controllers/tree_controller.rb
> @@ -1,10 +1,18 @@
> class TreeController < ApplicationController
> -
> +
> + def get_pools
> + # TODO: split these into separate hash elements for HW and smart pools
> + pools = HardwarePool.get_default_pool.full_set_nested(:method => :json_hash_element,
> + :privilege => Permission::PRIV_VIEW, :user => get_login_user)
> + pools += DirectoryPool.get_smart_root.full_set_nested(:method => :json_hash_element,
> + :privilege => Permission::PRIV_VIEW, :user => get_login_user,
> + :smart_pool_set => true)
> + end
> def fetch_nav
> - @pools = HardwarePool.get_default_pool.full_set_nested(:method => :json_hash_element)
> + @pools = get_pools
> end
>
> def fetch_json
> - render :json => HardwarePool.get_default_pool.full_set_nested(:method => :json_hash_element).to_json
> + render :json => get_pools.to_json
> end
> end
> diff --git a/src/app/controllers/vm_controller.rb b/src/app/controllers/vm_controller.rb
> index d3f16b6..6d06b48 100644
> --- a/src/app/controllers/vm_controller.rb
> +++ b/src/app/controllers/vm_controller.rb
> @@ -35,6 +35,11 @@ class VmController < ApplicationController
> render :layout => 'selection'
> end
>
> + def add_to_smart_pool
> + @pool = SmartPool.find(params[:smart_pool_id])
> + render :layout => 'popup'
> + end
> +
> def new
> render :layout => 'popup'
> end
> diff --git a/src/app/models/directory_pool.rb b/src/app/models/directory_pool.rb
> index f62d980..82486af 100644
> --- a/src/app/models/directory_pool.rb
> +++ b/src/app/models/directory_pool.rb
> @@ -55,6 +55,7 @@ class DirectoryPool < Pool
> permission.save!
> end
> end
> + user_root
> end
>
> end
> diff --git a/src/app/models/pool.rb b/src/app/models/pool.rb
> index 9d71fa5..eb71be8 100644
> --- a/src/app/models/pool.rb
> +++ b/src/app/models/pool.rb
> @@ -111,6 +111,9 @@ class Pool < ActiveRecord::Base
> def self.select_vm_pools(pools)
> pools.select {|pool| pool[:type] == "VmResourcePool"}
> end
> + def self.select_hardware_and_vm_pools(pools)
> + pools.select {|pool| ["HardwarePool", "VmResourcePool"].include?(pool[:type])}
> + end
>
> def sub_hardware_pools
> children({:conditions => "type='HardwarePool'"})
> @@ -225,22 +228,44 @@ class Pool < ActiveRecord::Base
> # or :current_id to specify which pool gets ":selected => true" set
> def full_set_nested(opts={})
> method = opts.delete(:method) {:hash_element}
> + privilege = opts.delete(:privilege)
> + user = opts.delete(:user)
> + smart_pool_set = opts.delete(:smart_pool_set)
> + if privilege and user
> + opts[:include] = "permissions"
> + opts[:conditions] = "permissions.uid='#{user}' and
> + permissions.user_role in
> + ('#{Permission.roles_for_privilege(privilege).join("', '")}')"
> + end
> current_id = opts.delete(:current_id)
> opts.delete(:order)
> subtree_list = full_set(opts)
> - return_tree = send(method)
> - ref_hash = { id => return_tree}
> + subtree_list -= [self] if smart_pool_set
> + return_tree_list = []
> + ref_hash = {}
> subtree_list.each do |pool|
> - unless pool.id==return_tree[:id]
> - new_element = pool.send(method)
> - ref_hash[pool.id] = new_element
> - parent = ref_hash[pool.parent_id]
> + new_element = pool.send(method)
> + ref_hash[pool.id] = new_element
> + parent = ref_hash[pool.parent_id]
> + if parent
> parent[:children] ||= []
> parent[:children] << new_element
> + else
> + # for smart pools include the parent DirectoryPool
> + if smart_pool_set and pool[:type]=="SmartPool"
> + pool_parent = pool.parent
> + parent_element = pool_parent.send(method)
> + ref_hash[pool_parent.id] = parent_element
> + return_tree_list << parent_element
> + parent_element[:children] ||= []
> + parent_element[:children] << new_element
> + else
> + return_tree_list << new_element
> + end
> end
> end
> ref_hash[current_id][:selected] = true if current_id
> - return_tree
> + return_tree_list
> end
>
> def self.call_finder(*args)
> @@ -273,6 +298,9 @@ class Pool < ActiveRecord::Base
> end
> end
>
> + def class_and_id
> + self.class.name + "_" + self.id.to_s
> + end
> protected
> def traverse_parents
> if id
> diff --git a/src/app/models/smart_pool.rb b/src/app/models/smart_pool.rb
> index e672c5b..9104ee5 100644
> --- a/src/app/models/smart_pool.rb
> +++ b/src/app/models/smart_pool.rb
> @@ -30,6 +30,10 @@ class SmartPool < Pool
> :conditions => "smart_pool_tags.tagged_type = 'Vm'"
>
>
> + def get_type_label
> + "Smart Pool"
> + end
> +
> def create_for_user(user)
> create_with_parent(DirectoryPool.get_or_create_user_root(user))
> end
> @@ -44,4 +48,23 @@ class SmartPool < Pool
> :tagged_id=>item.id}).destroy
> end
>
> + def add_items(item_class, item_ids)
> + items = item_class.find(:all, :conditions => "id in (#{item_ids.join(', ')})")
> + transaction do
> + items.each { |item| add_item(item)}
> + end
> + end
> +
> + def remove_items(item_class, item_ids)
> + tags = smart_pool_tags.find(:all,
> + :conditions => "tagged_id in
> + (#{item_ids.join(', ')})
> + and tagged_type='#{item_class.name}'")
> + transaction do
> + tags.each do |tag|
> + tag.destroy
> + end
> + end
> + end
> +
> end
> diff --git a/src/app/views/hardware/_move_menu.rhtml b/src/app/views/hardware/_move_menu.rhtml
> deleted file mode 100644
> index cc7ed73..0000000
> --- a/src/app/views/hardware/_move_menu.rhtml
> +++ /dev/null
> @@ -1,17 +0,0 @@
> -<%= image_tag "icon_move.png", :style => "vertical-align:middle;" %> Move <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %>
> -<ul>
> - <% @hardware_pools.each { |hw_pool| %>
> - <% if @pool.parent_id != hw_pool.id and @pool.id != hw_pool.id %>
> - <li onclick="window.location='<%= url_for :controller => :hardware, :action => 'foobar' %>'"> <!-- FIXME point me at the right place -->
> - <% else %>
> - <li style="color: #CCCCCC; cursor: default;">
> - <% end %>
> - <%= image_tag "icon_hdwarepool.png" %>
> - <%= hw_pool.name %></a>
> - </li>
> - <% } %>
> -
> - <li style="border-top: 1px solid black; border-bottom: 1px solid black;">
> - Move to New Resource Group...
> - </li>
> -</ul>
> diff --git a/src/app/views/hardware/show_hosts.rhtml b/src/app/views/hardware/show_hosts.rhtml
> index 31c575d..d33c920 100644
> --- a/src/app/views/hardware/show_hosts.rhtml
> +++ b/src/app/views/hardware/show_hosts.rhtml
> @@ -14,17 +14,17 @@
> <script type="text/javascript">
> function get_selected_hosts()
> {
> - return get_selected_checkboxes("hosts_grid_form")
> + return get_selected_checkboxes("hosts_grid_form");
> }
> function validate_for_move()
> {
> if (validate_selected(get_selected_hosts(), 'host')) {
> - $('#move_link_hidden').click()
> + $('#move_link_hidden').click();
> }
> }
> function remove_hosts()
> {
> - hosts = get_selected_hosts()
> + var hosts = get_selected_hosts();
> if (validate_selected(hosts, "host")) {
> $.post('<%= url_for :controller => "hardware", :action => "move_hosts", :id => @pool %>',
> { resource_ids: hosts.toString(), target_pool_id: <%= HardwarePool.get_default_pool.id %> },
> @@ -34,22 +34,22 @@
> $.jGrowl(data.alert);
> }
> if (hosts.indexOf($('#hosts_selection_id').html()) != -1){
> - empty_summary('hosts_selection', 'Host')
> - }
> + empty_summary('hosts_selection', 'Host');
> + }
>
> }, 'json');
> }
> }
> function hosts_select(selected_rows)
> {
> - var selected_ids = new Array()
> - for(i=0; i<selected_rows.length; i++) {
> + var selected_ids = new Array();
> + for(i=0; i<selected_rows.length; i++) {
> load_widget_select(selected_rows[i]);
> selected_ids[i] = selected_rows[i].id;
> }
> if (selected_ids.length == 1)
> {
> - $('#hosts_selection').load('<%= url_for :controller => "host", :action => "show", :id => nil %>/' + parseInt(selected_ids[0].substring(3)))
> + $('#hosts_selection').load('<%= url_for :controller => "host", :action => "show", :id => nil %>/' + parseInt(selected_ids[0].substring(3)));
> }
> }
> </script>
> @@ -63,7 +63,7 @@
> :exclude_host => nil,
> :show_pool => false,
> :checkboxes => true,
> - :on_select => "hosts_select",
> + :on_select => "hosts_select",
> :on_deselect => "load_widget_deselect",
> :on_hover => "load_widget_hover",
> :on_unhover => "load_widget_unhover",
> @@ -79,7 +79,7 @@
> <div class="data_section">
> <div class="no-grid-items">
> <%= image_tag 'no-grid-items.png', :style => 'float: left;' %>
> -
> +
> <div class="no-grid-items-text">
> No hosts found in this pool. <br/><br/>
> <%= image_tag "icon_addhost.png", :style=>"vertical-align:middle;" %>
> diff --git a/src/app/views/hardware/show_storage.rhtml b/src/app/views/hardware/show_storage.rhtml
> index 564b9ed..6466f9b 100644
> --- a/src/app/views/hardware/show_storage.rhtml
> +++ b/src/app/views/hardware/show_storage.rhtml
> @@ -15,7 +15,7 @@
> <script type="text/javascript">
> function remove_storage()
> {
> - storage = get_selected_storage()
> + var storage = get_selected_storage();
> if (validate_selected(storage, "storage pool")) {
> $.post('<%= url_for :controller => "hardware", :action => "move_storage", :id => @pool %>',
> { resource_ids: storage.toString(), target_pool_id: <%= HardwarePool.get_default_pool.id %> },
> @@ -25,14 +25,14 @@
> $.jGrowl(data.alert);
> }
> if (storage.indexOf($('#storage_selection_id').html()) != -1){
> - empty_summary('storage_selection', 'Storage Pool')
> + empty_summary('storage_selection', 'Storage Pool');
> }
> }, 'json');
> }
> }
> function delete_storage()
> {
> - storage = get_selected_storage()
> + var storage = get_selected_storage();
> if (validate_selected(storage, "storage pool")) {
> $.post('<%= url_for :controller => "storage", :action => "delete_pools", :id => @pool %>',
> { storage_pool_ids: storage.toString() },
> @@ -42,15 +42,15 @@
> $.jGrowl(data.alert);
> }
> if (storage.indexOf($('#storage_selection_id').html()) != -1){
> - empty_summary('storage_selection', 'Storage Pool')
> + empty_summary('storage_selection', 'Storage Pool');
> }
> }, 'json');
> }
> }
> function storage_select(selected_rows)
> {
> - var selected_ids = new Array() ;
> - for(i=0; i<selected_rows.length; i++) {
> + var selected_ids = new Array();
> + for(i=0; i<selected_rows.length; i++) {
> selected_ids[i] = selected_rows[i].id;
> }
> if (selected_ids.length == 1)
> @@ -80,7 +80,7 @@
> <div class="data_section">
> <div class="no-grid-items">
> <%= image_tag 'no-grid-items.png', :style => 'float: left;' %>
> -
> +
> <div class="no-grid-items-text">
> No storage Volumes found in this pool. <br/><br/>
> <%= image_tag "icon_addhost.png", :style=>"vertical-align:middle;" %>
> diff --git a/src/app/views/hardware/show_vms.rhtml b/src/app/views/hardware/show_vms.rhtml
> index 5ff5cc9..ee14758 100644
> --- a/src/app/views/hardware/show_vms.rhtml
> +++ b/src/app/views/hardware/show_vms.rhtml
> @@ -11,7 +11,7 @@
> }
> function delete_vm_pools()
> {
> - vm_pools = get_selected_vm_pools()
> + var vm_pools = get_selected_vm_pools();
> if (validate_selected(vm_pools, "vm_pool")) {
> $.post('<%= url_for :controller => "resources", :action => "delete", :id => @pool %>',
> { vm_pool_ids: vm_pools.toString() },
> diff --git a/src/app/views/host/_grid.rhtml b/src/app/views/host/_grid.rhtml
> index 553adf9..21b563e 100644
> --- a/src/app/views/host/_grid.rhtml
> +++ b/src/app/views/host/_grid.rhtml
> @@ -1,6 +1,14 @@
> <%= render :partial => 'graph/load_graph.rhtml' %>
> +<% pool_controller = 'hardware' unless (defined? pool_controller) and !(pool_controller.nil?) %>
>
> <% hosts_per_page.nil? ? hosts_per_page = 40: hosts_per_page = hosts_per_page %>
> +<% if (hwpool.nil? or
> + ((hwpool.is_a? HardwarePool) and (hwpool.hosts.size > hosts_per_page)) or
> + ((hwpool.is_a? SmartPool) and (hwpool.tagged_hosts.size > hosts_per_page)))
> + usepager = 'true'
> + else
> + usepager = 'false'
> + end %>
> <div id="<%= table_id %>_div">
> <%= "<form id=\"#{table_id}_form\">" if checkboxes %>
> <table id="<%= table_id %>" style="display:none"></table>
> @@ -10,7 +18,7 @@
> $("#<%= table_id %>").flexigrid
> (
> {
> - url: '<%= url_for :controller => "hardware",
> + url: '<%= url_for :controller => pool_controller,
> :action => "hosts_json",
> :escape => false,
> :id => (hwpool.nil? ? nil : hwpool.id),
> @@ -38,8 +46,8 @@
> ],
> sortname: "hostname",
> sortorder: "asc",
> - usepager: <%= (hwpool.nil? or hwpool.hosts.size > hosts_per_page) ? 'true' : 'false' %>,
> - useRp: <%= (hwpool.nil? or hwpool.hosts.size > hosts_per_page) ? 'true' : 'false' %>,
> + usepager: <%= usepager %>,
> + useRp: <%= usepager %>,
> rp: <%= hosts_per_page %>,
> showTableToggleBtn: true,
> onSelect: <%= on_select %>,
> diff --git a/src/app/views/host/add_to_smart_pool.rhtml b/src/app/views/host/add_to_smart_pool.rhtml
> new file mode 100644
> index 0000000..a89f8de
> --- /dev/null
> +++ b/src/app/views/host/add_to_smart_pool.rhtml
> @@ -0,0 +1,28 @@
> +<%- content_for :title do -%>
> + <%= _("Add Host to Smart Pool") %>
> +<%- end -%>
> +<%- content_for :description do -%>
> + Select hosts from the list below to add to the <%= @pool.name %> smart pool.</a>
> +<%- end -%>
> +<div id="dialog-content-area">
> +<div class="dialog_body_small">
> +<div class="panel_header"></div>
> + <%= render :partial => "/host/grid", :locals => { :table_id => "add_smart_hosts_grid",
> + :hwpool => nil,
> + :pool_controller => "smart_pools",
> + :exclude_pool => @pool.id,
> + :exclude_host => nil,
> + :checkboxes => true,
> + :on_select => false,
> + :on_deselect => false,
> + :on_hover => false,
> + :on_unhover => false,
> + :is_popup => true,
> + :hosts_per_page => 10} %>
> +</div>
> +
> +<%= popup_footer("add_hosts_to_smart_pool('#{url_for :controller => "smart_pools",
> + :action => "add_hosts",
> + :id => @pool}')",
> + "Add Hosts") %>
> +</div>
> diff --git a/src/app/views/host/addhost.html.erb b/src/app/views/host/addhost.html.erb
> index 7edd4c5..967643e 100644
> --- a/src/app/views/host/addhost.html.erb
> +++ b/src/app/views/host/addhost.html.erb
> @@ -24,4 +24,4 @@
> :action => "add_hosts",
> :id => @hardware_pool}')",
> "Add Hosts") %>
> -</div>
> \ No newline at end of file
> +</div>
> diff --git a/src/app/views/layouts/_navigation_tabs.rhtml b/src/app/views/layouts/_navigation_tabs.rhtml
> index 4b0f18d..af3fa61 100644
> --- a/src/app/views/layouts/_navigation_tabs.rhtml
> +++ b/src/app/views/layouts/_navigation_tabs.rhtml
> @@ -30,6 +30,23 @@
> <li id="nav_access"> <%= link_to "User Access", {:action => 'show_users', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li>
> <li id="nav_tasks"> <%= link_to "Tasks", {:action => 'show_tasks', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li>
> </ul>
> +<% elsif controller.controller_name == "smart_pools" %>
> + <script>
> + $(document).ready(function(){
> + $tabs = $("#smart_pools_nav_tabs").tabs({
> + pool_type: "smart_pools",
> + selected: <%if params[:tab]%><%=params[:tab]%><%else%>1<%end%>
> + });
> + });
> + </script>
> + <ul id="smart_pools_nav_tabs" class="ui-tabs-nav">
> + <li id="nav_summary" class="ui-tabs-selected"><%= link_to "Summary", {:action => 'show', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li>
> + <li id="nav_hosts"> <%= link_to "Hosts", {:action => 'show_hosts', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li>
> + <li id="nav_storage"><%= link_to "Storage", {:action => 'show_storage', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li>
> + <li id="nav_pools"> <%= link_to "Pools", {:action => 'show_pools', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li>
> + <li id="nav_vms"> <%= link_to "Virtual Machines", {:action => 'show_vms', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li>
> + <li id="nav_access"> <%= link_to "User Access", {:action => 'show_users', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li>
> + </ul>
> <% elsif controller.controller_name == "search" %>
> <ul id="resources_nav_tabs" class="ui-tabs-nav">
> <li id="nav_search" class="ui-tabs-selected"><a href="#">Search Results</a></li>
> diff --git a/src/app/views/layouts/_side_toolbar.rhtml b/src/app/views/layouts/_side_toolbar.rhtml
> index 763f4a2..e1958f1 100644
> --- a/src/app/views/layouts/_side_toolbar.rhtml
> +++ b/src/app/views/layouts/_side_toolbar.rhtml
> @@ -1,24 +1,41 @@
> <% pool = @current_pool_id ? Pool.find(@current_pool_id) : nil %>
> +<% if pool and pool[:type]=="HardwarePool"
> + delete_url = url_for(:controller => "hardware", :action => "destroy")
> + elsif pool and pool[:type]=="VmResourcePool"
> + delete_url = url_for(:controller => "resources", :action => "destroy")
> + elsif pool and pool[:type]=="SmartPool"
> + delete_url = url_for(:controller => "smart_pools", :action => "destroy")
> + else
> + delete_url = ""
> + end %>
> +
> <%if pool -%>
> -<%if pool[:type]=="HardwarePool" -%>
> -<div class="toolbar" style="float:left;">
> - <a href="<%= url_for :controller => :hardware, :action => 'new', :parent_id => pool %>" rel="facebox[.bolder]">
> - <%=image_tag "icon_add_hardwarepool.png", :title=>"Add Hardware Pool" %>
> - </a>
> -</div>
> + <%if pool[:type]=="HardwarePool" -%>
> + <div class="toolbar" style="float:left;">
> + <a href="<%= url_for :controller => :hardware, :action => 'new', :parent_id => pool %>" rel="facebox[.bolder]">
> + <%=image_tag "icon_add_hardwarepool.png", :title=>"Add Hardware Pool" %>
> + </a>
> + </div>
> + <div class="toolbar" style="float:left;">
> + <a href="<%= url_for :controller => 'resources', :action => 'new', :parent_id => pool %>" rel="facebox[.bolder]">
> + <%= image_tag "icon_add_vmpool.png", :title=>"Add Virtual Machine Pool" %>
> + </a>
> + </div>
> + <% end -%>
> +<% end -%>
> <div class="toolbar" style="float:left;">
> - <a href="<%= url_for :controller => 'resources', :action => 'new', :parent_id => pool %>" rel="facebox[.bolder]">
> - <%= image_tag "icon_add_vmpool.png", :title=>"Add Virtual Machine Pool" %>
> + <a href="<%= url_for :controller => :smart_pools, :action => 'new' %>" rel="facebox[.bolder]">
> + <%=image_tag "icon_add_hardwarepool.png", :title=>"Add Smart Pool" %>
> </a>
> </div>
> -<% end -%>
> -<div class="toolbar" style="float:left;">
> +<%if pool -%>
> + <div class="toolbar" style="float:left;">
> <a href="#conf_nav_delete_pool" rel="facebox[.bolder]">
> <%= image_tag "icon_delete.gif", :title=>"Delete Selected Pool" %>
> </a>
> -</div>
> -<div class="toolbar" style="display:none;">
> - <%= confirmation_dialog("conf_nav_delete_pool", "Are you sure?", "delete_#{pool[:type]=='HardwarePool' ? 'hw' : 'vm'}_pool(#{pool.id})") %>
> -</div>
> + </div>
> + <div class="toolbar" style="display:none;">
> + <%= confirmation_dialog("conf_nav_delete_pool", "Are you sure?", "delete_pool('#{delete_url}', #{pool.id})") %>
> + </div>
> <% end -%>
> <div class="toolbar"></div>
> diff --git a/src/app/views/layouts/_tree.rhtml b/src/app/views/layouts/_tree.rhtml
> index eb15676..0e6e138 100644
> --- a/src/app/views/layouts/_tree.rhtml
> +++ b/src/app/views/layouts/_tree.rhtml
> @@ -12,12 +12,14 @@
> //animated: "normal",
> url: "<%= url_for :controller =>'/tree', :action => 'fetch_json' %>",
> hardware_url: "<%= url_for :controller =>'/hardware', :action => 'show' %>",
> - resource_url: "<%= url_for :controller =>'/resources', :action => 'show' %>"
> + resource_url: "<%= url_for :controller =>'/resources', :action => 'show' %>",
> + smart_url: "<%= url_for :controller =>'/smart_pools', :action => 'show' %>"
> });
> var tree_reload = {
> url: "<%= url_for :controller =>'/tree', :action => 'fetch_json' %>",
> hardware_url: "<%= url_for :controller =>'/hardware', :action => 'show' %>",
> - resource_url: "<%= url_for :controller =>'/resources', :action => 'show' %>"
> + resource_url: "<%= url_for :controller =>'/resources', :action => 'show' %>",
> + smart_url: "<%= url_for :controller =>'/smart_pools', :action => 'show' %>"
> }
> $('#test-tree').everyTime(15000,function(){
> load(tree_reload, {}, this, this);
> diff --git a/src/app/views/layouts/redux.rhtml b/src/app/views/layouts/redux.rhtml
> index d6cfe24..01540d4 100644
> --- a/src/app/views/layouts/redux.rhtml
> +++ b/src/app/views/layouts/redux.rhtml
> @@ -90,32 +90,6 @@
> });
> return false;})},function(){});
> });
> -
> - function delete_vm_pool(id, parent)
> - {
> - $(document).trigger('close.facebox');
> - $.post('<%= url_for :controller => "resources", :action => "destroy" %>',
> - {id: id},
> - function(data,status){
> - // need to redirect to the parent using the new ajax reload stuff
> - $("#vmpools_grid").flexReload();
> - if (data.alert) {
> - $.jGrowl(data.alert);
> - }
> - }, 'json');
> - }
> - function delete_hw_pool(id, parent)
> - {
> - $(document).trigger('close.facebox');
> - $.post('<%= url_for :controller => "hardware", :action => "destroy" %>',
> - {id: id},
> - function(data,status){
> - // need to redirect to the parent using the new ajax reload stuff
> - if (data.alert) {
> - $.jGrowl(data.alert);
> - }
> - }, 'json');
> - }
> </script>
> <%= yield :scripts -%>
> </head>
> diff --git a/src/app/views/resources/show_vms.rhtml b/src/app/views/resources/show_vms.rhtml
> index 857f56b..beca048 100644
> --- a/src/app/views/resources/show_vms.rhtml
> +++ b/src/app/views/resources/show_vms.rhtml
> @@ -26,7 +26,7 @@
> }
> function delete_vms()
> {
> - vms = get_selected_vms()
> + var vms = get_selected_vms();
> if (validate_selected(vms, "vm")) {
> $.post('<%= url_for :controller => "vm", :action => "delete", :id => @pool %>',
> { vm_ids: vms.toString() },
> @@ -43,7 +43,7 @@
> }
> function vm_actions(action)
> {
> - vms = get_selected_vms()
> + var vms = get_selected_vms();
> if (validate_selected(vms, "vm")) {
> jQuery.facebox('<div id="vm_action_results">');
> $('#vm_action_results').load('<%= url_for :controller => "resources",
> @@ -70,10 +70,12 @@
> <div class="data_section">
> <%= render :partial => "/vm/grid", :locals => { :table_id => "vms_grid",
> :pool => @pool,
> + :exclude_pool => nil,
> :on_select => "vms_select",
> :on_deselect => "load_widget_deselect",
> :on_hover => "load_widget_hover",
> - :on_unhover => "load_widget_unhover" } %>
> + :on_unhover => "load_widget_unhover",
> + :is_popup => false } %>
> </div>
> <div class="selection_detail" id="vms_selection">
> <div class="selection_left">
> diff --git a/src/app/views/smart_pools/_form.rhtml b/src/app/views/smart_pools/_form.rhtml
> new file mode 100644
> index 0000000..2f2156a
> --- /dev/null
> +++ b/src/app/views/smart_pools/_form.rhtml
> @@ -0,0 +1,6 @@
> +<%= error_messages_for 'vm_resource_pool' %>
> +
> +<!--[form:vm_resource_pool]-->
> +<%= text_field_with_label "Name", 'smart_pool', 'name' %>
> +<!--[eoform:vm_resource_pool]-->
> +
> diff --git a/src/app/views/smart_pools/_pools_grid.rhtml b/src/app/views/smart_pools/_pools_grid.rhtml
> new file mode 100644
> index 0000000..a5f1a99
> --- /dev/null
> +++ b/src/app/views/smart_pools/_pools_grid.rhtml
> @@ -0,0 +1,39 @@
> +<% resources_per_page = 40 %>
> +<div id="<%= table_id %>_div">
> +<form id="<%= table_id %>_form">
> +<table id="<%= table_id %>" style="display:none"></table>
> +</form>
> +</div>
> +<script type="text/javascript">
> + $("#<%= table_id %>").flexigrid
> + (
> + {
> + url: '<%= url_for :controller => "smart_pools", :action => "pools_json", :id => pool.id %>',
> + dataType: 'json',
> + colModel : [
> + {display: '', name : 'id', width : 20, sortable : false, align: 'left', process: <%= table_id %>checkbox},
> + {display: 'Name', name : 'name', width : 160, sortable : true, align: 'left'},
> + {display: 'Type', width : 160, sortable : true, align: 'left'}
> + ],
> + sortname: "name",
> + sortorder: "asc",
> + usepager: <%= pool.tagged_pools.size > resources_per_page ? 'true' : 'false' %>,
> + useRp: <%= pool.tagged_pools.size > resources_per_page ? 'true' : 'false' %>,
> + rp: <%= resources_per_page %>,
> + showTableToggleBtn: true,
> + onSelect: <%= on_select %>,
> + onDeselect: <%= on_deselect %>,
> + onHover: <%= on_hover %>,
> + onUnhover: <%= on_unhover %>
> + }
> + );
> + function <%= table_id %>checkbox(celDiv)
> + {
> + $(celDiv).html('<input type="checkbox" name="grid_checkbox'+$(celDiv).html()+'" class="grid_checkbox" value="'+$(celDiv).html()+'"/>');
> + }
> + function <%= table_id %>_load_widget(celDiv)
> + {
> + load_widget(celDiv, "resource");
> + };
> +
> +</script>
> diff --git a/src/app/views/smart_pools/add_pool_dialog.rhtml b/src/app/views/smart_pools/add_pool_dialog.rhtml
> new file mode 100644
> index 0000000..0d8cea6
> --- /dev/null
> +++ b/src/app/views/smart_pools/add_pool_dialog.rhtml
> @@ -0,0 +1,52 @@
> +<%- content_for :title do -%>
> + Add a Hardware or Virtual Machine Pool
> +<%- end -%>
> +<%- content_for :description do -%>
> + Choose a Hardware or Virtual Machine Pool to add to this Smart Pool
> +<%- end -%>
> +
> +<script type="text/javascript">
> + $(document).ready(function(){
> + $("#add_tree").asynch_treeview({
> + //animated: "normal",
> + current_pool_id: <%=@current_pool_id%>,
> + disabled_pools: [<%=@selected_pools.join(',')%>],
> + url: "<%= url_for :controller =>'/hardware', :action => 'json_view_tree' %>",
> + current: "disabled",
> + hardware_url: "#",
> + resource_url: "#",
> + onclick: "add_pool_to_smart_pool",
> + action_type: "javascript"
> + })
> + });
> + function add_pool_to_smart_pool(added_pool_id)
> + {
> + $.post('<%= url_for :controller => "smart_pools", :action => "add_pools", :id => @pool %>',
> + { resource_ids: added_pool_id },
> + function(data,status){
> + grid = $("#smart_pools_grid");
> + if (grid.size()>0 && grid != null) {
> + grid.flexReload();
> + } else {
> + $tabs.tabs("load",$tabs.data('selected.tabs'));
> + }
> + $("smart_pools_grid").flexReload()
> + jQuery(document).trigger('close.facebox');
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> +</script>
> +
> +<div class="dialog_tree">
> + <ul id="add_tree" class="filetree treeview-famfamfam treeview"></ul>
> +</div>
> +
> +<div class="facebox_timfooter">
> + <div class="button">
> + <div class="button_left_grey"></div>
> + <div class="button_middle_grey"><a href="#" onclick="jQuery(document).trigger('close.facebox')">Cancel</a></div>
> + <div class="button_right_grey"></div>
> + </div>
> +</div>
> diff --git a/src/app/views/smart_pools/new.rhtml b/src/app/views/smart_pools/new.rhtml
> new file mode 100644
> index 0000000..7d488af
> --- /dev/null
> +++ b/src/app/views/smart_pools/new.rhtml
> @@ -0,0 +1,26 @@
> +<%- content_for :title do -%>
> + <%= _("Add New Smart Pool") %>
> +<%- end -%>
> +<%- content_for :description do -%>
> + Add a new Smart Pool.
> +<%- end -%>
> +
> +<form method="POST" action="<%= url_for :action => 'create' %>" id="smart_pool_form" >
> + <div class="dialog_form">
> + <%= render :partial => 'form' %>
> + </div>
> + <%= popup_footer("$('#smart_pool_form').submit()", "Create Smart Pool") %>
> +</form>
> +
> +<script type="text/javascript">
> +$(function() {
> + var hwpooloptions = {
> + target: '<%= url_for :action => 'create' %>', // target element to update
> + dataType: 'json',
> + success: afterSmartPool // post-submit callback
> + };
> +
> + // bind form using 'ajaxForm'
> + $('#smart_pool_form').ajaxForm(hwpooloptions);
> +});
> +</script>
> diff --git a/src/app/views/smart_pools/show.rhtml b/src/app/views/smart_pools/show.rhtml
> new file mode 100644
> index 0000000..45b1753
> --- /dev/null
> +++ b/src/app/views/smart_pools/show.rhtml
> @@ -0,0 +1,17 @@
> +<div class="data_section_summary">
> +
> + <div class="summary_title"><%= image_tag "icon_hdwarepool.png", :style=>"vertical-align:middle;" %> <%= @pool.name %></div><br/><br/>
> +
> + <div class="summary_subtitle"><%= image_tag "icon_smry_res.png", :style=>"vertical-align:middle;" %> Resources</div><br/>
> + <div id="availability_graphs">
> + What do we show here for Smart Pools?
> + </div>
> +
> + <br/><br/>
> + <div class="summary_subtitle"><%= image_tag "icon_smry_his.png", :style=>"vertical-align:middle;" %> History</div><br/>
> + What do we show here for Smart Pools?
> +
> + <div class="summary_subtitle"><%= image_tag "icon_smry_perf.png", :style=>"vertical-align:middle;" %> Performance</div><br/>
> + What do we show here for Smart Pools?
> +</div>
> +
> diff --git a/src/app/views/hardware/show_hosts.rhtml b/src/app/views/smart_pools/show_hosts.rhtml
> similarity index 50%
> copy from src/app/views/hardware/show_hosts.rhtml
> copy to src/app/views/smart_pools/show_hosts.rhtml
> index 31c575d..a4b6be7 100644
> --- a/src/app/views/hardware/show_hosts.rhtml
> +++ b/src/app/views/smart_pools/show_hosts.rhtml
> @@ -1,89 +1,77 @@
> <div id="toolbar_nav">
> <ul>
> - <li><a href="<%= url_for :controller => 'host', :action => 'addhost', :hardware_pool_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addhost.png", :style=>"vertical-align:middle;" %> Add Host</a></li>
> - <li>
> - <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>
> - <% if @pool.id != HardwarePool.get_default_pool.id %>
> - <li><a href="#" onClick="remove_hosts()"><%= image_tag "icon_remove.png" %> Remove</a></li>
> - <% end %>
> + <li><a href="<%= url_for :controller => 'host', :action => 'add_to_smart_pool', :smart_pool_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addhost.png", :style=>"vertical-align:middle;" %> Add Host</a></li>
> + <li><a href="#" onClick="remove_hosts_from_smart_pool()"><%= image_tag "icon_remove.png" %> Remove</a></li>
> </ul>
> </div>
>
> <script type="text/javascript">
> - function get_selected_hosts()
> + function get_selected_hosts_for_smart_pool()
> {
> - return get_selected_checkboxes("hosts_grid_form")
> + return get_selected_checkboxes("smart_hosts_grid_form");
> }
> - function validate_for_move()
> + function remove_hosts_from_smart_pool()
> {
> - if (validate_selected(get_selected_hosts(), 'host')) {
> - $('#move_link_hidden').click()
> - }
> - }
> - function remove_hosts()
> - {
> - hosts = get_selected_hosts()
> + var hosts = get_selected_hosts_for_smart_pool();
> if (validate_selected(hosts, "host")) {
> - $.post('<%= url_for :controller => "hardware", :action => "move_hosts", :id => @pool %>',
> - { resource_ids: hosts.toString(), target_pool_id: <%= HardwarePool.get_default_pool.id %> },
> + $.post('<%= url_for :controller => "smart_pools", :action => "remove_hosts", :id => @pool %>',
> + { resource_ids: hosts.toString() },
> function(data,status){
> $tabs.tabs("load",$tabs.data('selected.tabs'));
> if (data.alert) {
> $.jGrowl(data.alert);
> }
> - if (hosts.indexOf($('#hosts_selection_id').html()) != -1){
> - empty_summary('hosts_selection', 'Host')
> - }
> + if (hosts.indexOf($('#smart_hosts_selection_id').html()) != -1){
> + empty_summary('smart_hosts_selection', 'Host');
> + }
>
> }, 'json');
> }
> }
> - function hosts_select(selected_rows)
> + function smart_hosts_select(selected_rows)
> {
> - var selected_ids = new Array()
> - for(i=0; i<selected_rows.length; i++) {
> - load_widget_select(selected_rows[i]);
> + var selected_ids = new Array();
> + for(i=0; i<selected_rows.length; i++) {
> selected_ids[i] = selected_rows[i].id;
> }
> if (selected_ids.length == 1)
> {
> - $('#hosts_selection').load('<%= url_for :controller => "host", :action => "show", :id => nil %>/' + parseInt(selected_ids[0].substring(3)))
> + $('#smart_hosts_selection').load('<%= url_for :controller => "host", :action => "show", :id => nil %>/' + parseInt(selected_ids[0].substring(3)));
> }
> }
> </script>
>
> <div class="panel_header"></div>
> -<% if @pool.hosts.size != 0 %>
> +<% if @pool.tagged_hosts.size != 0 %>
> <div class="data_section">
> - <%= render :partial => "/host/grid", :locals => { :table_id => "hosts_grid",
> + <%= render :partial => "/host/grid", :locals => { :table_id => "smart_hosts_grid",
> :hwpool => @pool,
> + :pool_controller => "smart_pools",
> :exclude_pool => nil,
> :exclude_host => nil,
> - :show_pool => false,
> + :show_pool => true,
> :checkboxes => true,
> - :on_select => "hosts_select",
> + :on_select => "smart_hosts_select",
> :on_deselect => "load_widget_deselect",
> :on_hover => "load_widget_hover",
> :on_unhover => "load_widget_unhover",
> :is_popup => false,
> :hosts_per_page => 40} %>
> </div>
> - <div class="selection_detail" id="hosts_selection">
> - <div class="selection_left">
> - <div>Select a host above.</div>
> - </div>
> + <div class="selection_detail" id="smart_hosts_selection">
> + <div class="selection_left">
> + <div>Select a host above.</div>
> + </div>
> </div>
> <% else %>
> <div class="data_section">
> <div class="no-grid-items">
> <%= image_tag 'no-grid-items.png', :style => 'float: left;' %>
> -
> +
> <div class="no-grid-items-text">
> No hosts found in this pool. <br/><br/>
> <%= image_tag "icon_addhost.png", :style=>"vertical-align:middle;" %>
> - <a href="<%= url_for :controller => 'host', :action => 'addhost', :hardware_pool_id => @pool %>" rel="facebox[.bolder]">Add first host to this hardware pool</a>
> + <a href="<%= url_for :controller => 'host', :action => 'add_to_smart_pool', :smart_pool_id => @pool %>" rel="facebox[.bolder]">Add first host to this smart pool</a>
> </div>
> </div>
> </div>
> diff --git a/src/app/views/smart_pools/show_pools.rhtml b/src/app/views/smart_pools/show_pools.rhtml
> new file mode 100644
> index 0000000..8e89701
> --- /dev/null
> +++ b/src/app/views/smart_pools/show_pools.rhtml
> @@ -0,0 +1,74 @@
> +<div id="toolbar_nav">
> + <ul>
> + <li><a href="<%= url_for :controller => 'smart_pools', :action => 'add_pool_dialog', :id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addhost.png", :style=>"vertical-align:middle;" %> Add Pool</a></li>
> + <li><a href="#" onClick="remove_pools_from_smart_pool()"><%= image_tag "icon_remove.png" %> Remove</a></li>
> + </ul>
> +</div>
> +
> +<script type="text/javascript">
> + function get_selected_pools_for_smart_pool()
> + {
> + return get_selected_checkboxes("smart_pools_grid_form");
> + }
> + function remove_pools_from_smart_pool()
> + {
> + var pools = get_selected_pools_for_smart_pool();
> + if (validate_selected(pools, "pool")) {
> + $.post('<%= url_for :controller => "smart_pools", :action => "remove_pools", :id => @pool %>',
> + { resource_ids: pools.toString() },
> + function(data,status){
> + $tabs.tabs("load",$tabs.data('selected.tabs'));
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + if (pools.indexOf($('#smart_pools_selection_id').html()) != -1){
> + empty_summary('smart_pools_selection', 'Pool');
> + }
> +
> + }, 'json');
> + }
> + }
> + function smart_pools_select(selected_rows)
> + {
> + var selected_ids = new Array();
> + for(i=0; i<selected_rows.length; i++) {
> + selected_ids[i] = selected_rows[i].id;
> + }
> + if (selected_ids.length == 1)
> + {
> + $('#smart_pools_selection').load('<%= url_for :controller => "search", :action => "single_result" %>',
> + { class_and_id: selected_ids[0].substring(3)});
> + }
> + }
> +</script>
> +
> +<div class="panel_header"></div>
> +<% if @pool.tagged_pools.size != 0 %>
> + <div class="data_section">
> + <%= render :partial => "/smart_pools/pools_grid", :locals => { :table_id => "smart_pools_grid",
> + :pool => @pool,
> + :pool_controller => "smart_pools",
> + :checkboxes => true,
> + :on_select => "smart_pools_select",
> + :on_deselect => false,
> + :on_hover => false,
> + :on_unhover => false} %>
> + </div>
> + <div class="selection_detail" id="smart_pools_selection">
> + <div class="selection_left">
> + <div>Select a pool above.</div>
> + </div>
> + </div>
> +<% else %>
> + <div class="data_section">
> + <div class="no-grid-items">
> + <%= image_tag 'no-grid-items.png', :style => 'float: left;' %>
> +
> + <div class="no-grid-items-text">
> + No pools found in this pool. <br/><br/>
> + <%= image_tag "icon_addpool.png", :style=>"vertical-align:middle;" %>
> + <a href="<%= url_for :controller => 'pool', :action => 'add_to_smart_pool', :smart_pool_id => @pool %>" rel="facebox[.bolder]">Add first Pool to this smart pool</a>
> + </div>
> + </div>
> + </div>
> +<% end %>
> diff --git a/src/app/views/smart_pools/show_storage.rhtml b/src/app/views/smart_pools/show_storage.rhtml
> new file mode 100644
> index 0000000..7cf425a
> --- /dev/null
> +++ b/src/app/views/smart_pools/show_storage.rhtml
> @@ -0,0 +1,72 @@
> +<div id="toolbar_nav">
> +<ul>
> + <li><a href="<%= url_for :controller => 'storage', :action => 'add_to_smart_pool', :smart_pool_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addstorage.png", :style=>"vertical-align:middle;" %> Add Storage Pool</a></li>
> + <li><a href="#" onClick="remove_storage_from_smart_pool()"><%= image_tag "icon_remove.png" %> Remove</a></li>
> + </ul>
> +</div>
> +
> +<script type="text/javascript">
> + function get_selected_storage_for_smart_pool()
> + {
> + return get_selected_checkboxes("smart_storage_grid_form");
> + }
> + function remove_storage_from_smart_pool()
> + {
> + var storage = get_selected_storage_for_smart_pool();
> + if (validate_selected(storage, "storage pool")) {
> + $.post('<%= url_for :controller => "smart_pools", :action => "remove_storage", :id => @pool %>',
> + { resource_ids: storage.toString() },
> + function(data,status){
> + $tabs.tabs("load",$tabs.data('selected.tabs'));
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + if (storage.indexOf($('#smart_storage_selection_id').html()) != -1){
> + empty_summary('smart_storage_selection', 'Storage Pool');
> + }
> + }, 'json');
> + }
> + }
> + function smart_storage_select(selected_rows)
> + {
> + var selected_ids = new Array() ;
> + for(i=0; i<selected_rows.length; i++) {
> + selected_ids[i] = selected_rows[i].id;
> + }
> + if (selected_ids.length == 1)
> + {
> + $('#smart_storage_selection').load('<%= url_for :controller => "storage", :action => "show" %>',
> + { id: parseInt(selected_ids[0].substring(3))});
> + }
> + }
> +
> +</script>
> +<div class="panel_header"></div>
> +<% if @pool.tagged_storage_pools.size != 0 %>
> + <div class="data_section">
> + <%= render :partial => "/storage/grid", :locals => { :table_id => "smart_storage_grid",
> + :hwpool => @pool,
> + :pool_controller => "smart_pools",
> + :exclude_pool => nil,
> + :on_select => "smart_storage_select",
> + :is_popup => false} %>
> + </div>
> +
> + <div class="selection_detail" id="smart_storage_selection">
> + <div class="selection_left">
> + <div>Select a storage pool.</div>
> + </div>
> + </div>
> +<% else %>
> + <div class="data_section">
> + <div class="no-grid-items">
> + <%= image_tag 'no-grid-items.png', :style => 'float: left;' %>
> +
> + <div class="no-grid-items-text">
> + No storage Pools found in this pool. <br/><br/>
> + <%= image_tag "icon_addstorage.png", :style=>"vertical-align:middle;" %>
> + <a href="<%= url_for :controller => 'storage', :action => 'add_to_smart_pool', :smart_pool_id => @pool %>" rel="facebox[.bolder]">Add first storage volume to this smart pool</a>
> + </div>
> + </div>
> + </div>
> +<% end %>
> diff --git a/src/app/views/smart_pools/show_users.rhtml b/src/app/views/smart_pools/show_users.rhtml
> new file mode 100644
> index 0000000..7d1efb8
> --- /dev/null
> +++ b/src/app/views/smart_pools/show_users.rhtml
> @@ -0,0 +1,2 @@
> + <%= render :partial => "/user/show", :locals => { :parent_controller => "smart_pools",
> + :pool => @pool } %>
> diff --git a/src/app/views/smart_pools/show_vms.rhtml b/src/app/views/smart_pools/show_vms.rhtml
> new file mode 100644
> index 0000000..e56600b
> --- /dev/null
> +++ b/src/app/views/smart_pools/show_vms.rhtml
> @@ -0,0 +1,77 @@
> +<div id="toolbar_nav">
> + <ul>
> + <li><a href="<%= url_for :controller => 'vm', :action => 'add_to_smart_pool', :smart_pool_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addhost.png", :style=>"vertical-align:middle;" %> Add Virtual Machine</a></li>
> + <li><a href="#" onClick="remove_vms_from_smart_pool()"><%= image_tag "icon_remove.png" %> Remove</a></li>
> + </ul>
> +</div>
> +
> +<script type="text/javascript">
> + function get_selected_vms_for_smart_pool()
> + {
> + return get_selected_checkboxes("smart_vms_grid_form");
> + }
> + function remove_vms_from_smart_pool()
> + {
> + var vms = get_selected_vms_for_smart_pool();
> + if (validate_selected(vms, "vm")) {
> + $.post('<%= url_for :controller => "smart_pools", :action => "remove_vms", :id => @pool %>',
> + { resource_ids: vms.toString() },
> + function(data,status){
> + $tabs.tabs("load",$tabs.data('selected.tabs'));
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + if (vms.indexOf($('#smart_vms_selection_id').html()) != -1){
> + empty_summary('smart_vms_selection', 'Vm');
> + }
> +
> + }, 'json');
> + }
> + }
> + function smart_vms_select(selected_rows)
> + {
> + var selected_ids = new Array();
> + for(i=0; i<selected_rows.length; i++) {
> + selected_ids[i] = selected_rows[i].id;
> + }
> + if (selected_ids.length == 1)
> + {
> + $('#smart_vms_selection').load('<%= url_for :controller => "vm", :action => "show", :id => nil %>/' + parseInt(selected_ids[0].substring(3)));
> + }
> + }
> +</script>
> +
> +<div class="panel_header"></div>
> +<% if @pool.tagged_vms.size != 0 %>
> + <div class="data_section">
> + <%= render :partial => "/vm/grid", :locals => { :table_id => "smart_vms_grid",
> + :pool => @pool,
> + :pool_controller => "smart_pools",
> + :exclude_pool => nil,
> + :show_pool => true,
> + :checkboxes => true,
> + :on_select => "smart_vms_select",
> + :on_deselect => "load_widget_deselect",
> + :on_hover => "load_widget_hover",
> + :on_unhover => "load_widget_unhover",
> + :is_popup => false,
> + :vms_per_page => 40} %>
> + </div>
> + <div class="selection_detail" id="smart_vms_selection">
> + <div class="selection_left">
> + <div>Select a vm above.</div>
> + </div>
> + </div>
> +<% else %>
> + <div class="data_section">
> + <div class="no-grid-items">
> + <%= image_tag 'no-grid-items.png', :style => 'float: left;' %>
> +
> + <div class="no-grid-items-text">
> + No vms found in this pool. <br/><br/>
> + <%= image_tag "icon_addvm.png", :style=>"vertical-align:middle;" %>
> + <a href="<%= url_for :controller => 'vm', :action => 'add_to_smart_pool', :smart_pool_id => @pool %>" rel="facebox[.bolder]">Add first VM to this smart pool</a>
> + </div>
> + </div>
> + </div>
> +<% end %>
> diff --git a/src/app/views/storage/_grid.rhtml b/src/app/views/storage/_grid.rhtml
> index c36f4d3..c8876bb 100644
> --- a/src/app/views/storage/_grid.rhtml
> +++ b/src/app/views/storage/_grid.rhtml
> @@ -1,4 +1,12 @@
> -<% storage_per_page = 40 %>
> +<% storage_per_page = 40 unless (defined? storage_per_page) and !(storage_per_page.nil?) %>
> +<% pool_controller = 'hardware' unless (defined? pool_controller) and !(pool_controller.nil?) %>
> +<% if (hwpool.nil? or
> + ((hwpool.is_a? HardwarePool) and (hwpool.storage_pools.size > storage_per_page)) or
> + ((hwpool.is_a? SmartPool) and (hwpool.tagged_storage_pools.size > storage_per_page)))
> + usepager = 'true'
> + else
> + usepager = 'false'
> + end %>
>
> <div id="<%= table_id %>_div">
> <form id="<%= table_id %>_form">
> @@ -9,7 +17,10 @@
> $("#<%= table_id %>").flexigrid
> (
> {
> - url: '<%= url_for :controller => "hardware", :action => "storage_pools_json", :id => (hwpool.nil? ? nil : hwpool.id), :exclude_pool => exclude_pool %>',
> + url: '<%= url_for :controller => pool_controller,
> + :action => "storage_pools_json",
> + :id => (hwpool.nil? ? nil : hwpool.id),
> + :exclude_pool => exclude_pool %>',
> dataType: 'json',
> <% if is_popup %>
> width: 700,
> @@ -23,8 +34,8 @@
> ],
> sortname: "ip_addr",
> sortorder: "asc",
> - usepager: <%= (hwpool.nil? or hwpool.storage_pools.size > storage_per_page) ? 'true' : 'false' %>,
> - useRp: <%= (hwpool.nil? or hwpool.storage_pools.size > storage_per_page) ? 'true' : 'false' %>,
> + usepager: <%= usepager %>,
> + useRp: <%= usepager %>,
> rp: <%= storage_per_page %>,
> showTableToggleBtn: true,
> onSelect: <%= on_select %>
> diff --git a/src/app/views/storage/add_to_smart_pool.rhtml b/src/app/views/storage/add_to_smart_pool.rhtml
> new file mode 100644
> index 0000000..2eedae3
> --- /dev/null
> +++ b/src/app/views/storage/add_to_smart_pool.rhtml
> @@ -0,0 +1,22 @@
> +<%- content_for :title do -%>
> + <%= _("Add Storage Pool to Smart Pool") %>
> +<%- end -%>
> +<%- content_for :description do -%>
> + Select storage pools from the list below to add to the <%= @pool.name %> smart pool.</a>
> +<%- end -%>
> +<div id="dialog-content-area">
> +<div class="dialog_body_small">
> +<div class="panel_header"></div>
> + <%= render :partial => "/storage/grid", :locals => { :table_id => "add_smart_storage_grid",
> + :hwpool => nil,
> + :pool_controller => "smart_pools",
> + :exclude_pool => @pool.id,
> + :on_select => false,
> + :is_popup => true} %>
> +</div>
> +
> +<%= popup_footer("add_storage_to_smart_pool('#{url_for :controller => "smart_pools",
> + :action => "add_storage",
> + :id => @pool}')",
> + "Add Storage Pools") %>
> +</div>
> diff --git a/src/app/views/user/_show.rhtml b/src/app/views/user/_show.rhtml
> index 916afe8..5b3ffb7 100644
> --- a/src/app/views/user/_show.rhtml
> +++ b/src/app/views/user/_show.rhtml
> @@ -12,7 +12,7 @@
> }
> function delete_users()
> {
> - permissions = get_selected_users();
> + var permissions = get_selected_users();
> if (validate_selected(permissions, "user")) {
> $.post('<%= url_for :controller => "permission", :action => "delete", :id => pool.id %>',
> { permission_ids: permissions.toString() },
> @@ -26,7 +26,7 @@
> }
> function update_users(role)
> {
> - permissions = get_selected_users()
> + var permissions = get_selected_users();
> if (validate_selected(permissions, "users")) {
> $.post('<%= url_for :controller => "permission", :action => "update_roles" %>',
> { permission_ids: permissions.toString(), user_role: role },
> diff --git a/src/app/views/vm/_grid.rhtml b/src/app/views/vm/_grid.rhtml
> index c56e6b8..a322ea3 100644
> --- a/src/app/views/vm/_grid.rhtml
> +++ b/src/app/views/vm/_grid.rhtml
> @@ -1,42 +1,56 @@
> <%= render :partial => 'graph/load_graph.rhtml' %>
> -<% vms_per_page = 10 %>
> +<% pool_controller = 'resources' unless (defined? pool_controller) and !(pool_controller.nil?) %>
> +<% vms_per_page = 40 unless (defined? vms_per_page) and !(vms_per_page.nil?) %>
> +<% if (pool.nil? or
> + ((pool.is_a? VmResourcePool) and (pool.vms.size > vms_per_page)) or
> + ((pool.is_a? SmartPool) and (pool.tagged_vms.size > vms_per_page)))
> + usepager = 'true'
> + else
> + usepager = 'false'
> + end %>
> <div id="<%= table_id %>_div">
> <form id="<%= table_id %>_form">
> <table id="<%= table_id %>" style="display:none"></table>
> </form>
> </div>
> <script type="text/javascript">
> - $("#<%= table_id %>").flexigrid
> - (
> - {
> - url: '<%= url_for :controller => "resources", :action => "vms_json", :id => pool.id %>',
> - dataType: 'json',
> - colModel : [
> - {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'},
> - {display: 'CPUs', name : 'num_vcpus_allocated', width : 40, sortable : true, align: 'left'},
> - {display: 'Memory (MB)', name : 'memory_allocated', width : 60, sortable : true, align: 'right'},
> - {display: 'vNIC Mac Addr', name : 'vnic_mac_addr', width : 60, sortable : true, align: 'right'},
> - {display: 'State', name : 'state', width : 50, sortable : true, align: 'right'},
> + $("#<%= table_id %>").flexigrid
> + (
> + {
> + url: '<%= url_for :controller => pool_controller,
> + :action => "vms_json",
> + :id => (pool.nil? ? nil : pool.id),
> + :exclude_pool => exclude_pool %>',
> + dataType: 'json',
> + <% if is_popup %>
> + width: 700,
> + <% end %>
> + colModel : [
> + {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'},
> + {display: 'CPUs', name : 'num_vcpus_allocated', width : 40, sortable : true, align: 'left'},
> + {display: 'Memory (MB)', name : 'memory_allocated', width : 60, sortable : true, align: 'right'},
> + {display: 'vNIC Mac Addr', name : 'vnic_mac_addr', width : 60, sortable : true, align: 'right'},
> + {display: 'State', name : 'state', width : 50, sortable : true, align: 'right'},
> {display: 'Load', name : 'load', width: 180, sortable : false, align: 'left', process: <%= table_id %>_load_widget }
> - ],
> - sortname: "description",
> - sortorder: "asc",
> - usepager: <%= pool.vms.size > vms_per_page ? 'true' : 'false' %>,
> - useRp: <%= pool.vms.size > vms_per_page ? 'true' : 'false' %>,
> - rp: <%= vms_per_page %>,
> - showTableToggleBtn: true,
> - onSelect: <%= on_select %>,
> + ],
> + sortname: "description",
> + sortorder: "asc",
> + usepager: <%= usepager %>,
> + useRp: <%= usepager %>,
> + rp: <%= vms_per_page %>,
> + showTableToggleBtn: true,
> + onSelect: <%= on_select %>,
> onDeselect: <%= on_deselect %>,
> onHover: <%= on_hover %>,
> onUnhover: <%= on_unhover %>
> - }
> - );
> - function <%= table_id %>checkbox(celDiv)
> - {
> - $(celDiv).html('<input type="checkbox" name="grid_checkbox'+$(celDiv).html()+'" class="grid_checkbox" value="'+$(celDiv).html()+'"/>');
> - }
> + }
> + );
> + function <%= table_id %>checkbox(celDiv)
> + {
> + $(celDiv).html('<input type="checkbox" name="grid_checkbox'+$(celDiv).html()+'" class="grid_checkbox" value="'+$(celDiv).html()+'"/>');
> + }
> function <%= table_id %>_load_widget(celDiv)
> {
> load_widget(celDiv, "vm");
> diff --git a/src/app/views/vm/add_to_smart_pool.rhtml b/src/app/views/vm/add_to_smart_pool.rhtml
> new file mode 100644
> index 0000000..cdfe92d
> --- /dev/null
> +++ b/src/app/views/vm/add_to_smart_pool.rhtml
> @@ -0,0 +1,27 @@
> +<%- content_for :title do -%>
> + <%= _("Add Vm to Smart Pool") %>
> +<%- end -%>
> +<%- content_for :description do -%>
> + Select vms from the list below to add to the <%= @pool.name %> smart pool.</a>
> +<%- end -%>
> +<div id="dialog-content-area">
> +<div class="dialog_body_small">
> +<div class="panel_header"></div>
> + <%= render :partial => "/vm/grid", :locals => { :table_id => "add_smart_vms_grid",
> + :pool => nil,
> + :pool_controller => "smart_pools",
> + :exclude_pool => @pool.id,
> + :checkboxes => true,
> + :on_select => false,
> + :on_deselect => false,
> + :on_hover => false,
> + :on_unhover => false,
> + :is_popup => true,
> + :vms_per_page => 40} %>
> +</div>
> +
> +<%= popup_footer("add_vms_to_smart_pool('#{url_for :controller => "smart_pools",
> + :action => "add_vms",
> + :id => @pool}')",
> + "Add Vms") %>
> +</div>
> diff --git a/src/db/migrate/017_add_smart_pools.rb b/src/db/migrate/017_add_smart_pools.rb
> index 6d83c02..5550a89 100644
> --- a/src/db/migrate/017_add_smart_pools.rb
> +++ b/src/db/migrate/017_add_smart_pools.rb
> @@ -47,7 +47,7 @@ class AddSmartPools < ActiveRecord::Migration
> new_permission = Permission.new({:pool_id => dir_root.id,
> :uid => permission.uid,
> :user_role => permission.user_role})
> - new_permission.save!
> + new_permission.save_with_new_children
> end
> end
> end
> diff --git a/src/public/javascripts/jquery-treeview/jquery.treeview.async.js b/src/public/javascripts/jquery-treeview/jquery.treeview.async.js
> index b10a130..4dacda6 100644
> --- a/src/public/javascripts/jquery-treeview/jquery.treeview.async.js
> +++ b/src/public/javascripts/jquery-treeview/jquery.treeview.async.js
> @@ -43,7 +43,7 @@ function load(settings, params, child, container) {
> } else {
> span_onclick = ""
> }
> - if (settings.current_pool_id==this.id) {
> + if (settings.current_pool_id==this.id || !((settings.disabled_pools == undefined) || ($.inArray(this.id,settings.disabled_pools)==-1))) {
> current.html("<span class=\"" + settings.current_class + ">" + this.text + "</span>")
> .appendTo(parent);
> } else {
> diff --git a/src/public/javascripts/jquery.ovirt.treeview.js b/src/public/javascripts/jquery.ovirt.treeview.js
> index 16cf260..bb41667 100644
> --- a/src/public/javascripts/jquery.ovirt.treeview.js
> +++ b/src/public/javascripts/jquery.ovirt.treeview.js
> @@ -21,10 +21,18 @@ function load(settings, params, child, container) {
> settings.link_to=settings.hardware_url
> settings.span_class="folder";
> settings.current_class = settings.current + "_folder";
> - } else {
> + } else if (this.type=="VmResourcePool") {
> settings.link_to=settings.resource_url;
> settings.span_class="file";
> settings.current_class = settings.current + "_file";
> + } else if (this.type=="SmartPool") {
> + settings.link_to=settings.smart_url;
> + settings.span_class="file";
> + settings.current_class = settings.current + "_file";
> + } else {
> + settings.link_to="";
> + settings.span_class="file";
> + settings.current_class = settings.current + "_file";
> }
> var span_onclick;
> var current = $("<li/>").attr("id", this.id || "");
> @@ -64,7 +72,7 @@ function load(settings, params, child, container) {
> }
> }
> $(container).find('li').remove();
> - createNode.call(response, child);
> + $.each(response, createNode, [child]);
> $(container).ovirt_treeview({add: child});
> for (var i = 0; i < selectedNodes.length; i++){
> $('#test-tree li#' + selectedNodes[i] +' > div').click();
> diff --git a/src/public/javascripts/ovirt.js b/src/public/javascripts/ovirt.js
> index af0b9f6..470a53a 100644
> --- a/src/public/javascripts/ovirt.js
> +++ b/src/public/javascripts/ovirt.js
> @@ -42,7 +42,7 @@ function add_hosts(url)
> $.post(url,
> { resource_ids: hosts.toString() },
> function(data,status){
> - jQuery(document).trigger('close.facebox');
> + $(document).trigger('close.facebox');
> grid = $("#hosts_grid");
> if (grid.size()>0 && grid != null) {
> grid.flexReload();
> @@ -62,7 +62,7 @@ function add_storage(url)
> $.post(url,
> { resource_ids: storage.toString() },
> function(data,status){;
> - jQuery(document).trigger('close.facebox');
> + $(document).trigger('close.facebox');
> grid = $("#storage_grid");
> if (grid.size()>0 && grid != null) {
> grid.flexReload();
> @@ -75,6 +75,66 @@ function add_storage(url)
> }, 'json');
> }
> }
> +function add_hosts_to_smart_pool(url)
> +{
> + hosts= get_selected_checkboxes("add_smart_hosts_grid_form");
> + if (validate_selected(hosts, "host")) {
> + $.post(url,
> + { resource_ids: hosts.toString() },
> + function(data,status){
> + $(document).trigger('close.facebox');
> + grid = $("#smart_hosts_grid");
> + if (grid.size()>0 && grid != null) {
> + grid.flexReload();
> + } else {
> + $tabs.tabs("load",$tabs.data('selected.tabs'));
> + }
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> +}
> +function add_storage_to_smart_pool(url)
> +{
> + storage= get_selected_checkboxes("add_smart_storage_grid_form");
> + if (validate_selected(storage, "storage pool")) {
> + $.post(url,
> + { resource_ids: storage.toString() },
> + function(data,status){
> + $(document).trigger('close.facebox');
> + grid = $("#smart_storage_grid");
> + if (grid.size()>0 && grid != null) {
> + grid.flexReload();
> + } else {
> + $tabs.tabs("load",$tabs.data('selected.tabs'));
> + }
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> +}
> +function add_vms_to_smart_pool(url)
> +{
> + vms= get_selected_checkboxes("add_smart_vms_grid_form");
> + if (validate_selected(vms, "vm")) {
> + $.post(url,
> + { resource_ids: vms.toString() },
> + function(data,status){
> + $(document).trigger('close.facebox');
> + grid = $("#smart_vms_grid");
> + if (grid.size()>0 && grid != null) {
> + grid.flexReload();
> + } else {
> + $tabs.tabs("load",$tabs.data('selected.tabs'));
> + }
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> + }
> +}
> // deal with ajax form response, filling in validation messages where required.
> function ajax_validation(response, status)
> {
> @@ -102,7 +162,7 @@ function ajax_validation(response, status)
> function afterHwPool(response, status){
> ajax_validation(response, status);
> if (response.success) {
> - jQuery(document).trigger('close.facebox');
> + $(document).trigger('close.facebox');
> // FIXME do we need to reload the tree here
>
> // this is for reloading the host/storage grid when
> @@ -128,7 +188,7 @@ function afterHwPool(response, status){
> function afterVmPool(response, status){
> ajax_validation(response, status);
> if (response.success) {
> - jQuery(document).trigger('close.facebox');
> + $(document).trigger('close.facebox');
> grid = $("#vmpools_grid");
> if (grid.size()>0 && grid != null) {
> grid.flexReload();
> @@ -137,10 +197,16 @@ function afterVmPool(response, status){
> }
> }
> }
> +function afterSmartPool(response, status){
> + ajax_validation(response, status);
> + if (response.success) {
> + $(document).trigger('close.facebox');
> + }
> +}
> function afterStoragePool(response, status){
> ajax_validation(response, status);
> if (response.success) {
> - jQuery(document).trigger('close.facebox');
> + $(document).trigger('close.facebox');
> grid = $("#storage_grid");
> if (grid.size()>0 && grid != null) {
> grid.flexReload();
> @@ -152,7 +218,7 @@ function afterStoragePool(response, status){
> function afterPermission(response, status){
> ajax_validation(response, status);
> if (response.success) {
> - jQuery(document).trigger('close.facebox');
> + $(document).trigger('close.facebox');
> grid = $("#users_grid");
> if (grid.size()>0 && grid!= null) {
> grid.flexReload();
> @@ -164,7 +230,7 @@ function afterPermission(response, status){
> function afterVm(response, status){
> ajax_validation(response, status);
> if (response.success) {
> - jQuery(document).trigger('close.facebox');
> + $(document).trigger('close.facebox');
> grid = $("#vms_grid");
> if (grid.size()>0 && grid != null) {
> grid.flexReload();
> @@ -212,7 +278,23 @@ function delete_or_remove_storage()
> } else if (selected[0].value == "delete") {
> delete_storage();
> }
> - jQuery(document).trigger('close.facebox');
> + $(document).trigger('close.facebox');
> +}
> +function delete_pool(delete_url, id)
> +{
> + $(document).trigger('close.facebox');
> +
> + if (delete_url==='') {
> + $.jGrowl("Invalid Pool Type");
> + return;
> + }
> + $.post(delete_url,
> + {id: id},
> + function(data,status){
> + if (data.alert) {
> + $.jGrowl(data.alert);
> + }
> + }, 'json');
> }
>
>
More information about the ovirt-devel
mailing list