This isn't complete, but I want to get it committed before the repo refactoring. This patch includes the controller refactoring needed for adding the new smart pool controllers, but I have not yet added any code to the new controllers. The models are in place for smart pools, but they aren't used anywhere yet. In addition, I've added a new DirectoryPool pool type that is used solely as a placeholder -- so that we can have a common root for all hardware and smart pools, and that we can organize smart pools by user. Since we need this pushed before the repo refactoring, this patch should be acked if it doesn't break anything. Separate review comments are, of course, welcome -- but anything that doesn't break the WUI will be fixed in a subsequent (post-repo-reorg) patch) Signed-off-by: Scott Seago <sseago at redhat.com> --- wui/src/app/controllers/application.rb | 3 +- wui/src/app/controllers/hardware_controller.rb | 111 ++-------------- wui/src/app/controllers/pool_controller.rb | 132 ++++++++++++++++++++ wui/src/app/controllers/resources_controller.rb | 128 ++++--------------- wui/src/app/controllers/smart_pool_controller.rb | 22 ++++ wui/src/app/controllers/tree_controller.rb | 4 +- wui/src/app/models/directory_pool.rb | 60 +++++++++ wui/src/app/models/hardware_pool.rb | 18 +-- wui/src/app/models/host.rb | 3 + wui/src/app/models/pool.rb | 21 +++ wui/src/app/models/smart_pool.rb | 47 +++++++ wui/src/app/models/smart_pool_tag.rb | 37 ++++++ wui/src/app/models/storage_pool.rb | 3 + wui/src/app/models/vm.rb | 4 + wui/src/app/views/hardware/show_hosts.rhtml | 2 +- wui/src/app/views/hardware/show_storage.rhtml | 2 +- wui/src/app/views/layouts/_navigation_tabs.rhtml | 10 +- wui/src/app/views/resources/edit.rhtml | 4 +- wui/src/app/views/resources/quick_summary.rhtml | 20 ++-- wui/src/app/views/resources/show.rhtml | 12 +- wui/src/app/views/resources/show_tasks.rhtml | 4 +- wui/src/app/views/resources/show_users.rhtml | 2 +- wui/src/app/views/resources/show_vms.rhtml | 12 +- wui/src/db/migrate/017_add_smart_pools.rb | 62 +++++++++ wui/src/dutils/active_record_env.rb | 4 + wui/src/script/grant_admin_privileges | 4 +- .../betternestedset/lib/better_nested_set.rb | 37 ++++-- 27 files changed, 503 insertions(+), 265 deletions(-) create mode 100644 wui/src/app/controllers/pool_controller.rb create mode 100644 wui/src/app/controllers/smart_pool_controller.rb create mode 100644 wui/src/app/models/directory_pool.rb create mode 100644 wui/src/app/models/smart_pool.rb create mode 100644 wui/src/app/models/smart_pool_tag.rb create mode 100644 wui/src/db/migrate/017_add_smart_pools.rb diff --git a/wui/src/app/controllers/application.rb b/wui/src/app/controllers/application.rb index b95577a..3126748 100644 --- a/wui/src/app/controllers/application.rb +++ b/wui/src/app/controllers/application.rb @@ -29,8 +29,7 @@ class ApplicationController < ActionController::Base before_filter :pre_new, :only => [:new] before_filter :pre_create, :only => [:create] before_filter :pre_edit, :only => [:edit, :update, :destroy] - before_filter :pre_show, :only => [:show, :show_vms, :show_users, - :show_hosts, :show_storage] + before_filter :pre_show, :only => [:show] before_filter :authorize_admin, :only => [:new, :create, :edit, :update, :destroy] before_filter :is_logged_in diff --git a/wui/src/app/controllers/hardware_controller.rb b/wui/src/app/controllers/hardware_controller.rb index 7c1d916..091ce97 100644 --- a/wui/src/app/controllers/hardware_controller.rb +++ b/wui/src/app/controllers/hardware_controller.rb @@ -18,7 +18,7 @@ # also available at http://www.gnu.org/copyleft/gpl.html. # -class HardwareController < ApplicationController +class HardwareController < PoolController XML_OPTS = { :include => [ :storage_pools, :hosts, :quota ] @@ -31,10 +31,8 @@ class HardwareController < ApplicationController verify :method => [:post, :delete], :only => :destroy, :redirect_to => { :action => :list } - before_filter :pre_json, :only => [:vm_pools_json, :users_json, - :storage_volumes_json, :show_tasks, :tasks] - before_filter :pre_modify, :only => [:add_hosts, :move_hosts, - :add_storage, :move_storage, + before_filter :pre_modify, :only => [:add_hosts, :move_hosts, + :add_storage, :move_storage, :create_storage, :delete_storage] def index @@ -60,27 +58,6 @@ class HardwareController < ApplicationController end end - def show - set_perms(@perm_obj) - unless @can_view - flash[:notice] = 'You do not have permission to view this hardware pool: redirecting to top level' - respond_to do |format| - format.html { redirect_to :controller => "dashboard" } - format.xml { head :forbidden } - end - return - end - respond_to do |format| - format.html { - render :layout => 'tabs-and-content' if params[:ajax] - render :layout => false if params[:nolayout] - } - format.xml { - render :xml => @pool.to_xml(XML_OPTS) - } - end - end - def json_view_tree json_tree_internal(Permission::PRIV_VIEW, false) end @@ -121,11 +98,6 @@ class HardwareController < ApplicationController show end - def show_users - @roles = Permission::ROLES.keys - show - end - def show_hosts @hardware_pools = HardwarePool.find :all show @@ -145,53 +117,23 @@ class HardwareController < ApplicationController ["Host Task", "HostTask"], ["Storage Task", "StorageTask", "break"], ["Show All", ""]] - @task_states = [["Queued", Task::STATE_QUEUED], - ["Running", Task::STATE_RUNNING], - ["Paused", Task::STATE_PAUSED], - ["Finished", Task::STATE_FINISHED], - ["Failed", Task::STATE_FAILED], - ["Canceled", Task::STATE_CANCELED, "break"], - ["Show All", ""]] - params[:page]=1 - params[:sortname]="tasks.created_at" - params[:sortorder]="desc" - @tasks = tasks_internal - show - end - - def tasks - render :json => tasks_internal.to_json + super end def tasks_internal @task_type = params[:task_type] @task_type ||="" - @task_state = params[:task_state] - @task_state ||=Task::STATE_QUEUED - conditions = {} - conditions[:type] = @task_type unless @task_type.empty? - conditions[:state] = @task_state unless @task_state.empty? - find_opts = {:include => [:storage_pool, :host, :vm]} - find_opts[:conditions] = conditions unless conditions.empty? - attr_list = [] - attr_list << :id if params[:checkboxes] - attr_list += [:type_label, :task_obj, :action, :state, :user, :created_at, :args, :message] - json_hash(@pool.tasks, attr_list, [:all], find_opts) - end - - def quick_summary - pre_show - render :layout => 'selection' + super end def hosts_json if params[:exclude_host] - pre_json + pre_show hosts = @pool.hosts find_opts = {:conditions => ["id != ?", params[:exclude_host]]} include_pool = false elsif params[:id] - pre_json + pre_show hosts = @pool.hosts find_opts = {} include_pool = false @@ -219,14 +161,9 @@ class HardwareController < ApplicationController {:finder => 'call_finder', :conditions => ["type = 'VmResourcePool'"]}) end - def users_json - json_list(@pool.permissions, - [:grid_id, :uid, :user_role, :source]) - end - def storage_pools_json if params[:id] - pre_json + pre_show storage_pools = @pool.storage_pools find_opts = {} include_pool = false @@ -258,7 +195,7 @@ class HardwareController < ApplicationController def new @resource_type = params[:resource_type] @resource_ids = params[:resource_ids] - render :layout => 'popup' + super end def create @@ -293,10 +230,6 @@ class HardwareController < ApplicationController end end - def edit - render :layout => 'popup' - end - def update if params[:hardware_pool] # FIXME: For the REST API, we allow moving hosts/storage through @@ -455,28 +388,23 @@ class HardwareController < ApplicationController :alert => alert } } format.xml { head status } end - end + end - private + protected #filter methods def pre_new @pool = HardwarePool.new - @parent = Pool.find(params[:parent_id]) - @perm_obj = @parent - @current_pool_id=@parent.id + super end def pre_create # FIXME: REST and browsers send params differently. Should be fixed # in the views if params[:pool] @pool = HardwarePool.new(params[:pool]) - @parent = Pool.find(params[:parent_id]) else @pool = HardwarePool.new(params[:hardware_pool]) - @parent = Pool.find(params[:hardware_pool][:parent_id]) end - @perm_obj = @parent - @current_pool_id=@parent.id + super end def pre_edit @pool = HardwarePool.find(params[:id]) @@ -486,18 +414,7 @@ class HardwareController < ApplicationController end def pre_show @pool = HardwarePool.find(params[:id]) - @perm_obj = @pool - @current_pool_id=@pool.id - set_perms(@perm_obj) - unless @can_view - flash[:notice] = 'You do not have permission to view this Hardware Pool: redirecting to top level' - # FIXME: figure out the return type and render appropriately - redirect_to :action => 'list' - return - end - end - def pre_json - pre_show + super end def pre_modify pre_edit diff --git a/wui/src/app/controllers/pool_controller.rb b/wui/src/app/controllers/pool_controller.rb new file mode 100644 index 0000000..ce41701 --- /dev/null +++ b/wui/src/app/controllers/pool_controller.rb @@ -0,0 +1,132 @@ +# +# 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 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, + :storage_volumes_json, :quick_summary] + + def show + respond_to do |format| + format.html { + render :layout => 'tabs-and-content' if params[:ajax] + render :layout => false if params[:nolayout] + } + format.xml { + render :xml => @pool.to_xml(XML_OPTS) + } + end + end + + def quick_summary + render :layout => 'selection' + end + + # resource's users list page + def show_users + @roles = Permission::ROLES.keys + show + end + + def users_json + json_list(@pool.permissions, + [:grid_id, :uid, :user_role, :source]) + end + + def show_tasks + @task_states = [["Queued", Task::STATE_QUEUED], + ["Running", Task::STATE_RUNNING], + ["Paused", Task::STATE_PAUSED], + ["Finished", Task::STATE_FINISHED], + ["Failed", Task::STATE_FAILED], + ["Canceled", Task::STATE_CANCELED, "break"], + ["Show All", ""]] + params[:page]=1 + params[:sortname]="tasks.created_at" + params[:sortorder]="desc" + @tasks = tasks_internal + show + end + + def tasks + render :json => tasks_internal.to_json + end + + def tasks_internal + @task_state = params[:task_state] + @task_state ||=Task::STATE_QUEUED + conditions = {} + conditions[:type] = @task_type unless @task_type.empty? + conditions[:state] = @task_state unless @task_state.empty? + find_opts = {:include => [:storage_pool, :host, :vm]} + find_opts[:conditions] = conditions unless conditions.empty? + attr_list = [] + attr_list << :id if params[:checkboxes] + attr_list += [:type_label, :task_obj, :action, :state, :user, :created_at, :args, :message] + json_hash(@pool.tasks, attr_list, [:all], find_opts) + end + + def new + render :layout => 'popup' + end + + def edit + render :layout => 'popup' + end + + protected + def pre_new + @parent = Pool.find(params[:parent_id]) + @perm_obj = @parent + @redir_controller = @perm_obj.get_controller + @current_pool_id=@parent.id + end + def pre_create + #this is currently only true for the rest API for hardware pools + if params[:hardware_pool] + @parent = Pool.find(params[:hardware_pool][:parent_id]) + else + @parent = Pool.find(params[:parent_id]) + end + @perm_obj = @parent + @redir_controller = @perm_obj.get_controller + @current_pool_id=@parent.id + end + def pre_show_pool + pre_show + end + def pre_show + @perm_obj = @pool + @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' + respond_to do |format| + format.html { redirect_to :controller => "dashboard" } + format.xml { head :forbidden } + end + return + end + end + +end diff --git a/wui/src/app/controllers/resources_controller.rb b/wui/src/app/controllers/resources_controller.rb index 5a8276c..a0a65a6 100644 --- a/wui/src/app/controllers/resources_controller.rb +++ b/wui/src/app/controllers/resources_controller.rb @@ -17,14 +17,12 @@ # MA 02110-1301, USA. A copy of the GNU General Public License is # also available at http://www.gnu.org/copyleft/gpl.html. -class ResourcesController < ApplicationController +class ResourcesController < PoolController def index list render :action => 'list' end - before_filter :pre_json, :only => [:vms_json, :users_json, - :show_tasks, :tasks] before_filter :pre_vm_actions, :only => [:vm_actions] # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) @@ -49,17 +47,7 @@ class ResourcesController < ApplicationController ["Resume", VmTask::ACTION_RESUME_VM], ["Save", VmTask::ACTION_SAVE_VM], ["Restore", VmTask::ACTION_RESTORE_VM]] - if params[:ajax] - render :layout => 'tabs-and-content' - end - if params[:nolayout] - render :layout => false - end - end - - def quick_summary - pre_show - render :layout => 'selection' + super end # resource's vms list page @@ -73,81 +61,36 @@ class ResourcesController < ApplicationController show end - # resource's users list page - def show_users - @roles = Permission::ROLES.keys - show - end - - def show_tasks - @task_states = [["Queued", Task::STATE_QUEUED], - ["Running", Task::STATE_RUNNING], - ["Paused", Task::STATE_PAUSED], - ["Finished", Task::STATE_FINISHED], - ["Failed", Task::STATE_FAILED], - ["Canceled", Task::STATE_CANCELED, "break"], - ["Show All", ""]] - params[:page]=1 - params[:sortname]="tasks.created_at" - params[:sortorder]="desc" - @tasks = tasks_internal - show - end - - def tasks - render :json => tasks_internal.to_json - end - def tasks_internal + @task_type = "" @task_state = params[:task_state] - @task_state ||=Task::STATE_QUEUED - conditions = {} - conditions[:state] = @task_state unless @task_state.empty? - find_opts = {:include => [:storage_pool, :host, :vm]} - find_opts[:conditions] = conditions unless conditions.empty? - attr_list = [] - attr_list << :id if params[:checkboxes] - attr_list += [:type_label, :task_obj, :action, :state, :user, :created_at, :args, :message] - json_hash(@vm_resource_pool.tasks, attr_list, [:all], find_opts) + super end def vms_json - json_list(@vm_resource_pool.vms, + json_list(@pool.vms, [:id, :description, :uuid, :num_vcpus_allocated, :memory_allocated_in_mb, :vnic_mac_addr, :state, :id]) end - def users_json - json_list(@vm_resource_pool.permissions, - [:grid_id, :uid, :user_role, :source]) - end - - def new - render :layout => 'popup' - end - def create begin - @vm_resource_pool.create_with_parent(@parent) + @pool.create_with_parent(@parent) render :json => { :object => "vm_resource_pool", :success => true, :alert => "Virtual Machine Pool was successfully created." } rescue render :json => { :object => "vm_resource_pool", :success => false, - :errors => @vm_resource_pool.errors.localize_error_messages.to_a} + :errors => @pool.errors.localize_error_messages.to_a} end end - def edit - render :layout => 'popup' - end - def update begin - @vm_resource_pool.update_attributes!(params[:vm_resource_pool]) + @pool.update_attributes!(params[:vm_resource_pool]) render :json => { :object => "vm_resource_pool", :success => true, :alert => "Virtual Machine Pool was successfully modified." } rescue render :json => { :object => "vm_resource_pool", :success => false, - :errors => @vm_resource_pool.errors.localize_error_messages.to_a} + :errors => @pool.errors.localize_error_messages.to_a} end end @@ -174,7 +117,7 @@ class ResourcesController < ApplicationController end def destroy - if @vm_resource_pool.destroy + if @pool.destroy alert="Virtual Machine Pool was successfully deleted." success=true else @@ -192,7 +135,7 @@ class ResourcesController < ApplicationController @success_list = [] @failure_list = [] begin - @vm_resource_pool.transaction do + @pool.transaction do @vms.each do |vm| if vm.queue_action(@user, @action) @success_list << vm @@ -212,45 +155,30 @@ class ResourcesController < ApplicationController protected def pre_new - @vm_resource_pool = VmResourcePool.new - @parent = Pool.find(params[:parent_id]) - @perm_obj = @parent - @redir_controller = @perm_obj.get_controller - @current_pool_id=@parent.id + @pool = VmResourcePool.new + super end def pre_create - @vm_resource_pool = VmResourcePool.new(params[:vm_resource_pool]) - @parent = Pool.find(params[:parent_id]) - @perm_obj = @parent - @redir_controller = @perm_obj.get_controller - @current_pool_id=@parent.id - end - def pre_show - @vm_resource_pool = VmResourcePool.find(params[:id]) - @perm_obj = @vm_resource_pool - @current_pool_id=@vm_resource_pool.id - set_perms(@perm_obj) - @is_hwpool_admin = @vm_resource_pool.parent.can_modify(@user) - unless @can_view - flash[:notice] = 'You do not have permission to view this VM Resource Pool: redirecting to top level' - redirect_to :action => 'dashboard' - end + @pool = VmResourcePool.new(params[:vm_resource_pool]) + super end def pre_edit - @vm_resource_pool = VmResourcePool.find(params[:id]) - @parent = @vm_resource_pool.parent - @perm_obj = @vm_resource_pool.parent - @redir_obj = @vm_resource_pool - @current_pool_id=@vm_resource_pool.id + @pool = VmResourcePool.find(params[:id]) + @parent = @pool.parent + @perm_obj = @pool.parent + @redir_obj = @pool + @current_pool_id=@pool.id end - def pre_json - pre_show + def pre_show + @pool = VmResourcePool.find(params[:id]) + @is_hwpool_admin = @pool.parent.can_modify(@user) + super end def pre_vm_actions - @vm_resource_pool = VmResourcePool.find(params[:id]) - @parent = @vm_resource_pool.parent - @perm_obj = @vm_resource_pool - @redir_obj = @vm_resource_pool + @pool = VmResourcePool.find(params[:id]) + @parent = @pool.parent + @perm_obj = @pool + @redir_obj = @pool authorize_user end diff --git a/wui/src/app/controllers/smart_pool_controller.rb b/wui/src/app/controllers/smart_pool_controller.rb new file mode 100644 index 0000000..eb087a6 --- /dev/null +++ b/wui/src/app/controllers/smart_pool_controller.rb @@ -0,0 +1,22 @@ +# +# 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/wui/src/app/controllers/tree_controller.rb b/wui/src/app/controllers/tree_controller.rb index c7dbe35..5ad8426 100644 --- a/wui/src/app/controllers/tree_controller.rb +++ b/wui/src/app/controllers/tree_controller.rb @@ -1,10 +1,10 @@ class TreeController < ApplicationController def fetch_nav - @pools = Pool.root.full_set_nested(:method => :json_hash_element) + @pools = HardwarePool.get_default_pool.full_set_nested(:method => :json_hash_element) end def fetch_json - render :json => Pool.root.full_set_nested(:method => :json_hash_element).to_json + render :json => HardwarePool.get_default_pool.full_set_nested(:method => :json_hash_element).to_json end end diff --git a/wui/src/app/models/directory_pool.rb b/wui/src/app/models/directory_pool.rb new file mode 100644 index 0000000..f62d980 --- /dev/null +++ b/wui/src/app/models/directory_pool.rb @@ -0,0 +1,60 @@ +# +# 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 DirectoryPool < Pool + + ROOT_NAME = "root" + HARDWARE_ROOT = "hardware" + SMART_ROOT = "users" + + def self.get_directory_root + self.root(:conditions=>"type='DirectoryPool'") + end + + def self.get_hardware_root + dir_root = get_directory_root + dir_root ? dir_root.named_child(HARDWARE_ROOT) : nil + end + + def self.get_smart_root + dir_root = get_directory_root + dir_root ? dir_root.named_child(SMART_ROOT) : nil + end + + def self.get_user_root(user) + smart_root = get_smart_root + smart_root ? smart_root.named_child(user) : nil + end + + def self.get_or_create_user_root(user) + user_root = get_user_root(user) + unless user_root + DirectoryPool.transaction do + user_root = DirectoryPool.new(:name => user) + user_root.create_with_parent(get_smart_root) + permission = Permission.new({:pool_id => user_root.id, + :uid => user, + :user_role => Permission::ROLE_SUPER_ADMIN}) + #we don't need save_with_new_children here since there are no children yet + permission.save! + end + end + end + +end diff --git a/wui/src/app/models/hardware_pool.rb b/wui/src/app/models/hardware_pool.rb index 5409862..160f663 100644 --- a/wui/src/app/models/hardware_pool.rb +++ b/wui/src/app/models/hardware_pool.rb @@ -19,6 +19,8 @@ class HardwarePool < Pool + DEFAULT_POOL_NAME = "default" + has_many :tasks, :dependent => :nullify def all_storage_volumes StorageVolume.find(:all, :include => {:storage_pool => :hardware_pool}, :conditions => "pools.id = #{id}") @@ -34,7 +36,8 @@ class HardwarePool < Pool # note: doesn't currently join w/ permissions def self.get_default_pool - self.root + hw_root = DirectoryPool.get_hardware_root + hw_root ? hw_root.named_child(DEFAULT_POOL_NAME) : nil end def create_with_resources(parent, resource_type= nil, resource_ids=[]) @@ -98,17 +101,4 @@ class HardwarePool < Pool return {:total => total, :labels => labels} end - def self.find_by_path(path) - segs = path.split("/") - unless segs.shift.empty? - raise "Path must be absolute, but is #{path}" - end - default_pool = get_default_pool - if segs.shift == default_pool.name - segs.inject(default_pool) do |pool, seg| - pool.sub_hardware_pools.find { |p| p.name == seg } if pool - end - end - end - end diff --git a/wui/src/app/models/host.rb b/wui/src/app/models/host.rb index 5b32653..3fc3abb 100644 --- a/wui/src/app/models/host.rb +++ b/wui/src/app/models/host.rb @@ -40,6 +40,9 @@ class Host < ActiveRecord::Base end end + has_many :smart_pool_tags, :as => :tagged, :dependent => :destroy + has_many :smart_pools, :through => :smart_pool_tags + acts_as_xapian :texts => [ :hostname, :uuid, :hypervisor_type, :arch ], :values => [ [ :created_at, 0, "created_at", :date ], [ :updated_at, 1, "updated_at", :date ] ], diff --git a/wui/src/app/models/pool.rb b/wui/src/app/models/pool.rb index 6599c72..9d71fa5 100644 --- a/wui/src/app/models/pool.rb +++ b/wui/src/app/models/pool.rb @@ -42,12 +42,15 @@ class Pool < ActiveRecord::Base end end + has_many :smart_pool_tags, :as => :tagged, :dependent => :destroy + has_many :smart_pools, :through => :smart_pool_tags # used to allow parent traversal before obj is saved to the db # (needed for view code 'create' form) attr_accessor :tmp_parent validates_presence_of :name + validates_uniqueness_of :name, :scope => :parent_id # overloading this method such that we can use permissions.admins to get all the admins for an object has_many :permissions, :dependent => :destroy, :order => "id ASC" do @@ -125,6 +128,11 @@ class Pool < ActiveRecord::Base self_and_siblings.select {|pool| pool[:type] == self.class.name} end + def named_child(child_name) + matches = children(:conditions=>"name='#{child_name}'") + matches ? matches[0] : nil + end + def can_view(user) has_privilege(user, Permission::PRIV_VIEW) end @@ -252,6 +260,19 @@ class Pool < ActiveRecord::Base permissions.collect {|perm| perm.uid} end + def self.find_by_path(path) + segs = path.split("/") + unless segs.shift.empty? + raise "Path must be absolute, but is #{path}" + end + default_pool = DirectoryPool.get_directory_root + if segs.shift == default_pool.name + segs.inject(default_pool) do |pool, seg| + pool.children.find { |p| p.name == seg } if pool + end + end + end + protected def traverse_parents if id diff --git a/wui/src/app/models/smart_pool.rb b/wui/src/app/models/smart_pool.rb new file mode 100644 index 0000000..e672c5b --- /dev/null +++ b/wui/src/app/models/smart_pool.rb @@ -0,0 +1,47 @@ +# +# 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 SmartPool < Pool + has_many :smart_pool_tags, :dependent => :destroy + has_many :tagged_pools, :through => :smart_pool_tags, :source => :pool, + :conditions => "smart_pool_tags.tagged_type = 'Pool'" + has_many :tagged_storage_pools, :through => :smart_pool_tags, + :source => :storage_pool, + :conditions => "smart_pool_tags.tagged_type = 'StoragePool'" + has_many :tagged_hosts, :through => :smart_pool_tags, :source => :host, + :conditions => "smart_pool_tags.tagged_type = 'Host'" + has_many :tagged_vms, :through => :smart_pool_tags, :source => :vm, + :conditions => "smart_pool_tags.tagged_type = 'Vm'" + + + def create_for_user(user) + create_with_parent(DirectoryPool.get_or_create_user_root(user)) + end + + def add_item(item) + tag = SmartPoolTag.new(:smart_pool => self, :tagged => item) + tag.save! + end + def remove_item(item) + smart_pool_tags.find(:first, :conditions=> { + :tagged_type=>item.class.base_class.to_s, + :tagged_id=>item.id}).destroy + end + +end diff --git a/wui/src/app/models/smart_pool_tag.rb b/wui/src/app/models/smart_pool_tag.rb new file mode 100644 index 0000000..e135ddf --- /dev/null +++ b/wui/src/app/models/smart_pool_tag.rb @@ -0,0 +1,37 @@ +# +# 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 SmartPoolTag < ActiveRecord::Base + belongs_to :smart_pool + belongs_to :tagged, :polymorphic => true + belongs_to :pool, :class_name => "Pool", + :foreign_key => "tagged_id" + belongs_to :storage_pool, :class_name => "StoragePool", + :foreign_key => "tagged_id" + belongs_to :host, :class_name => "Host", + :foreign_key => "tagged_id" + belongs_to :vm, :class_name => "Vm", + :foreign_key => "tagged_id" + + validates_uniqueness_of :smart_pool_id, :scope => [:tagged_id, :tagged_type] + + def tagged_type=(sType) + super(sType.to_s.classify.constantize.base_class.to_s) + end +end diff --git a/wui/src/app/models/storage_pool.rb b/wui/src/app/models/storage_pool.rb index 460b49d..bc98f8e 100644 --- a/wui/src/app/models/storage_pool.rb +++ b/wui/src/app/models/storage_pool.rb @@ -30,6 +30,9 @@ class StoragePool < ActiveRecord::Base end end + has_many :smart_pool_tags, :as => :tagged, :dependent => :destroy + has_many :smart_pools, :through => :smart_pool_tags + validates_presence_of :ip_addr, :hardware_pool_id acts_as_xapian :texts => [ :ip_addr, :target, :export_path, :type ], diff --git a/wui/src/app/models/vm.rb b/wui/src/app/models/vm.rb index 80c7efb..cde28af 100644 --- a/wui/src/app/models/vm.rb +++ b/wui/src/app/models/vm.rb @@ -28,6 +28,10 @@ class Vm < ActiveRecord::Base end end has_and_belongs_to_many :storage_volumes + + has_many :smart_pool_tags, :as => :tagged, :dependent => :destroy + has_many :smart_pools, :through => :smart_pool_tags + validates_presence_of :uuid, :description, :num_vcpus_allocated, :memory_allocated_in_mb, :memory_allocated, :vnic_mac_addr diff --git a/wui/src/app/views/hardware/show_hosts.rhtml b/wui/src/app/views/hardware/show_hosts.rhtml index f88c64b..31c575d 100644 --- a/wui/src/app/views/hardware/show_hosts.rhtml +++ b/wui/src/app/views/hardware/show_hosts.rhtml @@ -27,7 +27,7 @@ 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: <%= Pool.root.id %> }, + { resource_ids: hosts.toString(), target_pool_id: <%= HardwarePool.get_default_pool.id %> }, function(data,status){ $tabs.tabs("load",$tabs.data('selected.tabs')); if (data.alert) { diff --git a/wui/src/app/views/hardware/show_storage.rhtml b/wui/src/app/views/hardware/show_storage.rhtml index 02b5180..564b9ed 100644 --- a/wui/src/app/views/hardware/show_storage.rhtml +++ b/wui/src/app/views/hardware/show_storage.rhtml @@ -18,7 +18,7 @@ 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: <%= Pool.root.id %> }, + { resource_ids: storage.toString(), target_pool_id: <%= HardwarePool.get_default_pool.id %> }, function(data,status){ $tabs.tabs("load",$tabs.data('selected.tabs')); if (data.alert) { diff --git a/wui/src/app/views/layouts/_navigation_tabs.rhtml b/wui/src/app/views/layouts/_navigation_tabs.rhtml index 629ab93..4b0f18d 100644 --- a/wui/src/app/views/layouts/_navigation_tabs.rhtml +++ b/wui/src/app/views/layouts/_navigation_tabs.rhtml @@ -15,7 +15,7 @@ <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 == "resources" and @vm_resource_pool != nil %> +<% elsif controller.controller_name == "resources" and @pool != nil %> <script> $(document).ready(function(){ $tabs = $("#resources_nav_tabs").tabs({ @@ -25,10 +25,10 @@ }); </script> <ul id="resources_nav_tabs" class="ui-tabs-nav"> - <li id="nav_summary" class="ui-tabs-selected"><%= link_to "Summary", {:action => 'show', :id => @vm_resource_pool.id, :nolayout => :true}, :title => "content area" %></li> - <li id="nav_vmpool"> <%= link_to "Virtual Machines", {:action => 'show_vms', :id => @vm_resource_pool.id, :nolayout => :true}, :title => "content area" %></li> - <li id="nav_access"> <%= link_to "User Access", {:action => 'show_users', :id => @vm_resource_pool.id, :nolayout => :true}, :title => "content area" %></li> - <li id="nav_tasks"> <%= link_to "Tasks", {:action => 'show_tasks', :id => @vm_resource_pool.id, :nolayout => :true}, :title => "content area" %></li> + <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_vmpool"> <%= 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> + <li id="nav_tasks"> <%= link_to "Tasks", {:action => 'show_tasks', :id => @pool.id, :nolayout => :true}, :title => "content area" %></li> </ul> <% elsif controller.controller_name == "search" %> <ul id="resources_nav_tabs" class="ui-tabs-nav"> diff --git a/wui/src/app/views/resources/edit.rhtml b/wui/src/app/views/resources/edit.rhtml index a101247..c6fd264 100644 --- a/wui/src/app/views/resources/edit.rhtml +++ b/wui/src/app/views/resources/edit.rhtml @@ -7,7 +7,7 @@ <form method="POST" action="<%= url_for :action => 'update' %>" id="vm_pool_form" > <div class="dialog_form"> - <%= hidden_field_tag 'id', @vm_resource_pool.id %> + <%= hidden_field_tag 'id', @pool.id %> <%= render :partial => 'form' %> </div> <%= popup_footer("$('#vm_pool_form').submit()", "Edit Virtual Machine Pool") %> @@ -26,7 +26,7 @@ $(function() { refresh_summary('vmpool_selection', '<%= url_for :controller => "resources", :action => "quick_summary" %>', - <%= @vm_resource_pool.id %>) + <%= @pool.id %>) } } }; diff --git a/wui/src/app/views/resources/quick_summary.rhtml b/wui/src/app/views/resources/quick_summary.rhtml index 60d0df7..31c4033 100644 --- a/wui/src/app/views/resources/quick_summary.rhtml +++ b/wui/src/app/views/resources/quick_summary.rhtml @@ -1,21 +1,21 @@ <%- content_for :title do -%> - <%=h @vm_resource_pool.name %> quota + <%=h @pool.name %> quota <%- end -%> <%- content_for :action_links do -%> <%if @is_hwpool_admin -%> <%= link_to image_tag("icon_edit.png") + " Edit", - {:controller => 'resources', :action => 'edit', :id => @vm_resource_pool}, + {:controller => 'resources', :action => 'edit', :id => @pool}, :rel=>"facebox[.bolder]", :class=>"selection_facebox" %> - <%if @vm_resource_pool.quota -%> + <%if @pool.quota -%> <%= link_to image_tag("icon_edit.png") + " Edit Quota", - {:controller => 'quota', :action => 'edit', :id => @vm_resource_pool.quota}, + {:controller => 'quota', :action => 'edit', :id => @pool.quota}, :rel=>"facebox[.bolder]", :class=>"selection_facebox" %> <a href="#confirm_delete_quota" rel="facebox[.bolder]"> <%= image_tag "icon_x.png" %> Revert to Default Quota </a> <% else -%> <%= link_to image_tag("icon_edit.png") + " Edit Quota", - {:controller => 'quota', :action => 'new', :pool_id => @vm_resource_pool }, + {:controller => 'quota', :action => 'new', :pool_id => @pool }, :rel=>"facebox[.bolder]", :class=>"selection_facebox" %> <% end -%> <% end -%> @@ -25,13 +25,13 @@ function delete_vm_quota() { $(document).trigger('close.facebox'); - $.post('<%= url_for :controller => "quota", :action => "destroy", :id => @vm_resource_pool.quota %>', + $.post('<%= url_for :controller => "quota", :action => "destroy", :id => @pool.quota %>', {x: 1}, function(data,status){ refresh_summary('vmpool_selection', '<%= url_for :controller => "resources", :action => "quick_summary" %>', - <%= @vm_resource_pool.id %>); + <%= @pool.id %>); if (data.alert) { $.jGrowl(data.alert); } @@ -39,8 +39,8 @@ } </script> - <div id="vmpool_selection_id" style="display:none"><%= @vm_resource_pool.id %></div> - <% resources = @vm_resource_pool.full_resources %> + <div id="vmpool_selection_id" style="display:none"><%= @pool.id %></div> + <% resources = @pool.full_resources %> <div class="selection_key"> <br/> <% for item in resources[:labels] %> @@ -60,5 +60,5 @@ </div> </div> <div class="selection_right"> - <%= render_component :controller=> 'graph', :action => 'snapshot_graph', :id => @vm_resource_pool.id, :target => 'resource' %> + <%= render_component :controller=> 'graph', :action => 'snapshot_graph', :id => @pool.id, :target => 'resource' %> </div> diff --git a/wui/src/app/views/resources/show.rhtml b/wui/src/app/views/resources/show.rhtml index 0db3a1b..789465b 100644 --- a/wui/src/app/views/resources/show.rhtml +++ b/wui/src/app/views/resources/show.rhtml @@ -1,18 +1,18 @@ <div class="data_section_summary"> - <div class="summary_title"><%= image_tag "icon_vmpool.png", :style=>"vertical-align:middle;" %> <%= @vm_resource_pool.name %></div><br/><br/> + <div class="summary_title"><%= image_tag "icon_vmpool.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"> - <%= render_component :controller=> 'graph', :action => 'availability_graph', :id => @vm_resource_pool.id, :params => { :target => 'vcpu' } %> - <%= render_component :controller=> 'graph', :action => 'availability_graph', :id => @vm_resource_pool.id, :params => { :target => 'vram' } %> + <%= render_component :controller=> 'graph', :action => 'availability_graph', :id => @pool.id, :params => { :target => 'vcpu' } %> + <%= render_component :controller=> 'graph', :action => 'availability_graph', :id => @pool.id, :params => { :target => 'vram' } %> </div> <br/><br/> <div class="summary_subtitle"><%= image_tag "icon_smry_his.png", :style=>"vertical-align:middle;" %> History</div><br/> - <%= render_component :controller=> 'graph', :action => 'history_graphs', :id => @vm_resource_pool.id, :params => { :poolType => 'vm' } %> + <%= render_component :controller=> 'graph', :action => 'history_graphs', :id => @pool.id, :params => { :poolType => 'vm' } %> <div class="summary_subtitle"><%= image_tag "icon_smry_perf.png", :style=>"vertical-align:middle;" %> Performance</div><br/> - <%= render_component :controller=> 'graph', :action => 'snapshot_graph', :id => @vm_resource_pool.id, :params => { :poolType => 'vm' } %> + <%= render_component :controller=> 'graph', :action => 'snapshot_graph', :id => @pool.id, :params => { :poolType => 'vm' } %> </div> <div class="selection_detail" id="vmpool_selection"> @@ -23,6 +23,6 @@ refresh_summary('vmpool_selection', '<%= url_for :controller => "resources", :action => "quick_summary" %>', - <%= @vm_resource_pool.id %>) + <%= @pool.id %>) </script> diff --git a/wui/src/app/views/resources/show_tasks.rhtml b/wui/src/app/views/resources/show_tasks.rhtml index 493264b..6c92779 100644 --- a/wui/src/app/views/resources/show_tasks.rhtml +++ b/wui/src/app/views/resources/show_tasks.rhtml @@ -24,7 +24,7 @@ function apply_task_state_filter(task_state) { $tabs.tabs("url", $tabs.data("selected.tabs"), - "<%= url_for :action => 'show_tasks', :id => @vm_resource_pool.id, + "<%= url_for :action => 'show_tasks', :id => @pool.id, :nolayout => :true %>" + "&task_state=" + task_state); $tabs.tabs("load", $tabs.data("selected.tabs")); @@ -37,7 +37,7 @@ <%= render :partial => "/task/grid", :locals => { :table_id => "vm_tasks_grid", :task_type => nil, :task_state => @task_state, - :pool => @vm_resource_pool, + :pool => @pool, :checkboxes => false, :on_select => "vm_tasks_grid_select" } %> </div> diff --git a/wui/src/app/views/resources/show_users.rhtml b/wui/src/app/views/resources/show_users.rhtml index 7e2538d..f23018c 100644 --- a/wui/src/app/views/resources/show_users.rhtml +++ b/wui/src/app/views/resources/show_users.rhtml @@ -1,2 +1,2 @@ <%= render :partial => "/user/show", :locals => { :parent_controller => "resources", - :pool => @vm_resource_pool } %> + :pool => @pool } %> diff --git a/wui/src/app/views/resources/show_vms.rhtml b/wui/src/app/views/resources/show_vms.rhtml index 45e0089..857f56b 100644 --- a/wui/src/app/views/resources/show_vms.rhtml +++ b/wui/src/app/views/resources/show_vms.rhtml @@ -1,6 +1,6 @@ <div id="toolbar_nav"> <ul> - <li><a href="<%= url_for :controller => 'vm', :action => 'new', :vm_resource_pool_id => @vm_resource_pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addhost.png", :style => "vertical-align:middle;" %> Add Virtual Machine</a></li> + <li><a href="<%= url_for :controller => 'vm', :action => 'new', :vm_resource_pool_id => @pool %>" rel="facebox[.bolder]"><%= image_tag "icon_addhost.png", :style => "vertical-align:middle;" %> Add Virtual Machine</a></li> <li> <%= image_tag "icon_move.png", :style => "vertical-align:middle;" %> Actions <%= image_tag "icon_toolbar_arrow.gif", :style => "vertical-align:middle;" %> <ul> @@ -28,7 +28,7 @@ { vms = get_selected_vms() if (validate_selected(vms, "vm")) { - $.post('<%= url_for :controller => "vm", :action => "delete", :id => @vm_resource_pool %>', + $.post('<%= url_for :controller => "vm", :action => "delete", :id => @pool %>', { vm_ids: vms.toString() }, function(data,status){ $tabs.tabs("load",$tabs.data('selected.tabs')); @@ -47,7 +47,7 @@ if (validate_selected(vms, "vm")) { jQuery.facebox('<div id="vm_action_results">'); $('#vm_action_results').load('<%= url_for :controller => "resources", - :action => "vm_actions", :id => @vm_resource_pool %>', + :action => "vm_actions", :id => @pool %>', { vm_ids: vms.toString(), vm_action: action }); } } @@ -66,10 +66,10 @@ </script> <div class="panel_header"></div> -<% if @vm_resource_pool.vms.size != 0 %> +<% if @pool.vms.size != 0 %> <div class="data_section"> <%= render :partial => "/vm/grid", :locals => { :table_id => "vms_grid", - :pool => @vm_resource_pool, + :pool => @pool, :on_select => "vms_select", :on_deselect => "load_widget_deselect", :on_hover => "load_widget_hover", @@ -88,7 +88,7 @@ <div class="no-grid-items-text"> No vms found in this pool. <br/><br/> <%= image_tag "icon_addhost.png", :style => "vertical-align:middle;" %> - <a href="<%= url_for :controller => 'vm', :action => 'new', :vm_resource_pool_id => @vm_resource_pool %>" rel="facebox[.bolder]">Add first virtual machine to resource pool</a></li> + <a href="<%= url_for :controller => 'vm', :action => 'new', :vm_resource_pool_id => @pool %>" rel="facebox[.bolder]">Add first virtual machine to resource pool</a></li> </div> </div> </div> diff --git a/wui/src/db/migrate/017_add_smart_pools.rb b/wui/src/db/migrate/017_add_smart_pools.rb new file mode 100644 index 0000000..6d83c02 --- /dev/null +++ b/wui/src/db/migrate/017_add_smart_pools.rb @@ -0,0 +1,62 @@ +# +# 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 AddSmartPools < ActiveRecord::Migration + def self.up + create_table :smart_pool_tags do |t| + t.integer :smart_pool_id, :null => false + t.integer :tagged_id, :null => false + t.string :tagged_type, :null => false + end + execute "alter table smart_pool_tags add constraint + fk_smart_pool_tags_pool_id + foreign key (smart_pool_id) references pools(id)" + execute "alter table smart_pool_tags add constraint + unique_smart_pool_tags + unique (smart_pool_id, tagged_id, tagged_type)" + + begin + dir_root = DirectoryPool.get_directory_root + unless dir_root + Pool.transaction do + dir_root = DirectoryPool.create(:name=>DirectoryPool::ROOT_NAME) + hw_root = DirectoryPool.new(:name=>DirectoryPool::HARDWARE_ROOT) + hw_root.create_with_parent(dir_root) + smart_root = DirectoryPool.new(:name=>DirectoryPool::SMART_ROOT) + smart_root.create_with_parent(dir_root) + default_pool = Pool.root(:conditions=>"type='HardwarePool'") + default_pool = HardwarePool.create( :name=>'default') unless default_pool + default_pool.move_to_child_of(hw_root) + default_pool.permissions.each do |permission| + new_permission = Permission.new({:pool_id => dir_root.id, + :uid => permission.uid, + :user_role => permission.user_role}) + new_permission.save! + end + end + end + rescue + puts "Could not create DirectoryPool hierarchy..." + end + end + + def self.down + drop_table :smart_pool_tags + end +end diff --git a/wui/src/dutils/active_record_env.rb b/wui/src/dutils/active_record_env.rb index 9b7b416..14593f7 100644 --- a/wui/src/dutils/active_record_env.rb +++ b/wui/src/dutils/active_record_env.rb @@ -58,6 +58,8 @@ require 'models/permission.rb' require 'models/quota.rb' require 'models/hardware_pool.rb' +require 'models/directory_pool.rb' +require 'models/smart_pool.rb' require 'models/host.rb' require 'models/cpu.rb' require 'models/nic.rb' @@ -77,4 +79,6 @@ require 'models/nfs_storage_pool.rb' require 'models/storage_volume.rb' require 'models/iscsi_storage_volume.rb' require 'models/nfs_storage_volume.rb' +require 'models/smart_pool.rb' +require 'models/smart_pool_tag.rb' diff --git a/wui/src/script/grant_admin_privileges b/wui/src/script/grant_admin_privileges index 82595cb..c263b9c 100755 --- a/wui/src/script/grant_admin_privileges +++ b/wui/src/script/grant_admin_privileges @@ -13,10 +13,10 @@ ActiveLdap::Base.establish_connection :base => base, :host => host, :try_sasl => if Account.exists?("uid=#{uid}") puts "Creating an admin account for #{uid}..." - $hwpool = HardwarePool.get_default_pool + $pool = DirectoryPool.get_directory_root permission = Permission.create(:user_role => Permission::ROLE_SUPER_ADMIN, :uid => uid, - :pool_id => $hwpool.id) + :pool_id => $pool.id) else puts "Unable to verify user: uid=#{uid}" end diff --git a/wui/src/vendor/plugins/betternestedset/lib/better_nested_set.rb b/wui/src/vendor/plugins/betternestedset/lib/better_nested_set.rb index cdcf0c6..e91ca93 100644 --- a/wui/src/vendor/plugins/betternestedset/lib/better_nested_set.rb +++ b/wui/src/vendor/plugins/betternestedset/lib/better_nested_set.rb @@ -81,13 +81,22 @@ module SymetrieCom # Returns the single root for the class (or just the first root, if there are several). # Deprecation note: the original acts_as_nested_set allowed roots to have parent_id = 0, # so we currently do the same. This silliness will not be tolerated in future versions, however. - def root - acts_as_nested_set_options[:class].find(:first, :conditions => "(#{acts_as_nested_set_options[:parent_column]} IS NULL OR #{acts_as_nested_set_options[:parent_column]} = 0)") + def root(find_opts={}) + roots_internal(:first, find_opts) end # Returns the roots and/or virtual roots of all trees. See the explanation of virtual roots in the README. - def roots - acts_as_nested_set_options[:class].find(:all, :conditions => "(#{acts_as_nested_set_options[:parent_column]} IS NULL OR #{acts_as_nested_set_options[:parent_column]} = 0)", :order => "#{acts_as_nested_set_options[:left_column]}") + def roots(find_opts={}) + roots_internal(:all, find_opts) + end + def roots_internal(all_or_one, find_opts={}) + conditions = "(#{acts_as_nested_set_options[:parent_column]} IS NULL" + conditions += " OR #{acts_as_nested_set_options[:parent_column]} = 0)" + order_col = "#{acts_as_nested_set_options[:left_column]}" + opts = merge_incoming_opts({:conditions => conditions, + :order => order_col}, + find_opts) + acts_as_nested_set_options[:class].find(all_or_one, opts) end # Checks the left/right indexes of all records, @@ -128,6 +137,14 @@ module SymetrieCom items.map! {|e| "(#{acts_as_nested_set_options[:left_column]} BETWEEN #{e[acts_as_nested_set_options[:left_column]]} AND #{e[acts_as_nested_set_options[:right_column]]})" } "(#{items.join(' OR ')})" end + + # accept incoming opts to allow filtering of results. + # So far only tested in limited use cases encountered in oVirt devel. + def merge_incoming_opts(set_opts, incoming_opts) + new_conditions = incoming_opts.delete(:conditions) + set_opts[:conditions] = "(#{set_opts[:conditions]}) AND (#{new_conditions})" if new_conditions + set_opts.merge(incoming_opts) + end end @@ -255,7 +272,7 @@ module SymetrieCom elsif new_record? || self[right_col_name] - self[left_col_name] == 1 return [self] end - opts = merge_incoming_opts({:conditions => "#{scope_condition} #{exclude_str} AND (#{left_col_name} BETWEEN #{self[left_col_name]} AND #{self[right_col_name]})", + opts = base_set_class.merge_incoming_opts({:conditions => "#{scope_condition} #{exclude_str} AND (#{left_col_name} BETWEEN #{self[left_col_name]} AND #{self[right_col_name]})", :order => left_col_name}, find_opts) base_set_class.find(:all, opts) @@ -270,7 +287,7 @@ module SymetrieCom # Returns this record's immediate children. def children(find_opts={}) - opts = merge_incoming_opts({:conditions => "#{scope_condition} AND #{parent_col_name} = #{self.id}", + opts = base_set_class.merge_incoming_opts({:conditions => "#{scope_condition} AND #{parent_col_name} = #{self.id}", :order => left_col_name}, find_opts) base_set_class.find(:all, opts) @@ -585,14 +602,6 @@ module SymetrieCom self.class.connection.quote(value, column) end - # accept incoming opts to allow filtering of results. - # So far only tested in limited use cases encountered in oVirt devel. - def merge_incoming_opts(set_opts, incoming_opts) - new_conditions = incoming_opts.delete(:conditions) - set_opts[:conditions] = "(#{set_opts[:conditions]}) AND (#{new_conditions})" if new_conditions - set_opts.merge(incoming_opts) - end - end end end -- 1.5.5.1