[Ovirt-devel] [PATCH server 01/10] converted storage volume controller to use the service layer
Scott Seago
sseago at redhat.com
Tue May 19 14:23:08 UTC 2009
Signed-off-by: Scott Seago <sseago at redhat.com>
---
src/app/controllers/storage_volume_controller.rb | 164 +++++-----------------
src/app/models/lvm_storage_volume.rb | 8 +
src/app/services/storage_volume_service.rb | 145 +++++++++++++++++++
3 files changed, 187 insertions(+), 130 deletions(-)
create mode 100644 src/app/services/storage_volume_service.rb
diff --git a/src/app/controllers/storage_volume_controller.rb b/src/app/controllers/storage_volume_controller.rb
index 6bdbbdc..b87f9b6 100644
--- a/src/app/controllers/storage_volume_controller.rb
+++ b/src/app/controllers/storage_volume_controller.rb
@@ -18,156 +18,60 @@
# also available at http://www.gnu.org/copyleft/gpl.html.
class StorageVolumeController < ApplicationController
+ include StorageVolumeService
def new
+ svc_new(params[:storage_pool_id], params[:source_volume_id])
@return_to_workflow = params[:return_to_workflow] || false
- if params[:storage_pool_id]
- unless @storage_pool.user_subdividable
- html_error_page("User-created storage volumes are not supported on this pool")
- return
- end
- @storage_volume = StorageVolume.factory(@storage_pool.get_type_label,
- { :storage_pool_id =>
- params[:storage_pool_id]})
- else
- unless @source_volume.supports_lvm_subdivision
- html_error_page("LVM is not supported for this storage volume")
- return
- end
- lvm_pool = @source_volume.lvm_storage_pool
- unless lvm_pool
- # FIXME: what should we do about VG/LV names?
- # for now auto-create VG name as ovirt_vg_#{@source_volume.id}
- new_params = { :vg_name => "ovirt_vg_#{@source_volume.id}",
- :hardware_pool_id => @source_volume.storage_pool.hardware_pool_id}
- lvm_pool = StoragePool.factory(StoragePool::LVM, new_params)
- lvm_pool.source_volumes << @source_volume
- lvm_pool.save!
- end
- @storage_volume = StorageVolume.factory(lvm_pool.get_type_label,
- { :storage_pool_id => lvm_pool.id})
- @storage_volume.lv_owner_perms='0744'
- @storage_volume.lv_group_perms='0744'
- @storage_volume.lv_mode_perms='0744'
- end
render :layout => 'popup'
end
def create
- begin
- StorageVolume.transaction do
- @storage_volume.save!
- @task = StorageVolumeTask.new({ :user => @user,
- :task_target => @storage_volume,
- :action => StorageVolumeTask::ACTION_CREATE_VOLUME,
- :state => Task::STATE_QUEUED})
- @task.save!
- end
- respond_to do |format|
- format.json { render :json => { :object => "storage_volume",
- :success => true,
- :alert => "Storage Volume was successfully created." ,
- :new_volume => @storage_volume.storage_tree_element({:filter_unavailable => false, :state => 'new'})} }
- format.xml { render :xml => @storage_volume,
- :status => :created,
- # FIXME: create storage_volume_url method if relevant
- :location => storage_pool_url(@storage_volume)
- }
- end
- rescue => ex
- # FIXME: need to distinguish volume vs. task save errors
- respond_to do |format|
- format.json {
- json_hash = { :object => "storage_volume", :success => false,
- :errors => @storage_volume.errors.localize_error_messages.to_a }
- json_hash[:message] = ex.message if json_hash[:errors].empty?
- render :json => json_hash }
- format.xml { render :xml => @storage_volume.errors,
- :status => :unprocessable_entity }
- end
+ volume = params[:storage_volume]
+ unless type = params[:storage_type]
+ type = volume.delete(:storage_type)
+ end
+ alert = svc_create(type, volume)
+ respond_to do |format|
+ format.json { render :json => { :object => "storage_volume",
+ :success => true, :alert => alert,
+ :new_volume => @storage_volume.storage_tree_element(
+ {:filter_unavailable => false, :state => 'new'})} }
+ format.xml { render :xml => @storage_volume,
+ :status => :created,
+ :location => storage_pool_url(@storage_volume)
+ }
end
end
def show
- @storage_volume = StorageVolume.find(params[:id])
- set_perms(@storage_volume.storage_pool.hardware_pool)
- @storage_pool = @storage_volume.storage_pool
- if authorize_view
- respond_to do |format|
- format.html { render :layout => 'selection' }
- format.json do
- attr_list = []
- attr_list << :id if (@storage_pool.user_subdividable and authorized?(Privilege::MODIFY))
- attr_list += [:display_name, :size_in_gb, :get_type_label]
- json_list(@storage_pool.storage_volumes, attr_list)
- end
- format.xml { render :xml => @storage_volume.to_xml }
+ svc_show(params[:id])
+ respond_to do |format|
+ format.html { render :layout => 'selection' }
+ format.json do
+ attr_list = []
+ attr_list << :id if (@storage_pool.user_subdividable and authorized?(Privilege::MODIFY))
+ attr_list += [:display_name, :size_in_gb, :get_type_label]
+ json_list(@storage_pool.storage_volumes, attr_list)
end
+ format.xml { render :xml => @storage_volume.to_xml }
end
end
def destroy
- unless authorized?(Privilege::MODIFY) and @storage_volume.storage_pool.user_subdividable
- handle_error(:message =>
- "You do not have permission to delete this storage volume.",
- :status => :forbidden,
- :title => "Access Denied")
- else
- alert, success = delete_volume_internal(@storage_volume)
- respond_to do |format|
- format.json { render :json => { :object => "storage_volume",
- :success => success, :alert => alert } }
- format.xml { head(success ? :ok : :method_not_allowed) }
- end
+ alert = svc_destroy(params[:id])
+ respond_to do |format|
+ format.json { render :json => { :object => "storage_volume",
+ :success => true, :alert => alert } }
+ format.xml { head(:ok) }
end
end
- def pre_new
- if params[:storage_pool_id]
- @storage_pool = StoragePool.find(params[:storage_pool_id])
- set_perms(@storage_pool.hardware_pool)
- else
- @source_volume = StorageVolume.find(params[:source_volume_id])
- set_perms(@source_volume.storage_pool.hardware_pool)
- end
+ # FIXME: remove these when service transition is complete. these are here
+ # to keep from running permissions checks and other setup steps twice
+ def tmp_pre_update
end
-
- def pre_create
- volume = params[:storage_volume]
- unless type = params[:storage_type]
- type = volume.delete(:storage_type)
- end
- @storage_volume = StorageVolume.factory(type, volume)
- set_perms(@storage_volume.storage_pool.hardware_pool)
- authorize_admin
- end
- # will go away w/ svc layer
- def pre_edit
- @storage_volume = StorageVolume.find(params[:id])
- set_perms(@storage_volume.storage_pool.hardware_pool)
- end
-
- private
- def delete_volume_internal(volume)
- begin
- name = volume.display_name
- if !volume.vms.empty?
- vm_list = volume.vms.collect {|vm| vm.description}.join(", ")
- ["Storage Volume #{name} must be unattached from VMs (#{vm_list}) before deleting it.",
- false]
- else
- volume.state=StorageVolume::STATE_PENDING_DELETION
- volume.save!
- @task = StorageVolumeTask.new({ :user => @user,
- :task_target => volume,
- :action => StorageVolumeTask::ACTION_DELETE_VOLUME,
- :state => Task::STATE_QUEUED})
- @task.save!
- ["Storage Volume #{name} deletion was successfully queued.", true]
- end
- rescue => ex
- ["Failed to delete storage volume #{name} (#{ex.message}.",false]
- end
+ def tmp_authorize_admin
end
end
diff --git a/src/app/models/lvm_storage_volume.rb b/src/app/models/lvm_storage_volume.rb
index 5b6177b..8fd1bac 100644
--- a/src/app/models/lvm_storage_volume.rb
+++ b/src/app/models/lvm_storage_volume.rb
@@ -18,6 +18,14 @@
# also available at http://www.gnu.org/copyleft/gpl.html.
class LvmStorageVolume < StorageVolume
+
+ def initialize(params)
+ super
+ self.lv_owner_perms='0744' unless self.lv_owner_perms
+ self.lv_group_perms='0744' unless self.lv_group_perms
+ self.lv_mode_perms='0744' unless self.lv_mode_perms
+ end
+
def display_name
"#{get_type_label}: #{storage_pool.vg_name}:#{lv_name}"
end
diff --git a/src/app/services/storage_volume_service.rb b/src/app/services/storage_volume_service.rb
new file mode 100644
index 0000000..6d338a5
--- /dev/null
+++ b/src/app/services/storage_volume_service.rb
@@ -0,0 +1,145 @@
+#
+# Copyright (C) 2009 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.
+# Mid-level API: Business logic around storage volumes
+module StorageVolumeService
+
+ include ApplicationService
+
+ # Load the StorageVolume with +id+ for viewing
+ #
+ # === Instance variables
+ # [<tt>@storage_volume</tt>] stores the Storage Volume with +id+
+ # [<tt>@storage_pool</tt>] stores the Storage Volume's Storage Pool
+ # === Required permissions
+ # [<tt>Privilege::VIEW</tt>] on StorageVolume's HardwarePool
+ def svc_show(id)
+ lookup(id,Privilege::VIEW)
+ end
+
+ # Load the StorageVolume with +id+ for editing
+ #
+ # === Instance variables
+ # [<tt>@storage_volume</tt>] stores the Storage Volume with +id+
+ # [<tt>@storage_pool</tt>] stores the Storage Volume's Storage Pool
+ # === Required permissions
+ # [<tt>Privilege::MODIFY</tt>] on StorageVolume's HardwarePool
+ def svc_modify(id)
+ lookup(id,Privilege::MODIFY)
+ end
+
+ # Load a new StorageVolume for creating
+ #
+ # === Instance variables
+ # [<tt>@storage_volume</tt>] loads a new StorageVolume object into memory
+ # [<tt>@storage_pool</tt>] Storage pool containing <tt>@storage_volume</tt>
+ # [<tt>@source_volume</tt>] Storage volume containing the LVM
+ # <tt>@storage_pool</tt> if storage type is LVM
+ # === Required permissions
+ # [<tt>Privilege::MODIFY</tt>] for the storage volume's HardwarePool
+ def svc_new(storage_pool_id, source_volume_id)
+ if storage_pool_id
+ @storage_pool = StoragePool.find(storage_pool_id)
+ unless @storage_pool.user_subdividable
+ raise ActionError.new("Unsupported action for " +
+ "#{@storage_pool.get_type_label} volumes.")
+ end
+ else
+ @source_volume = StorageVolume.find(source_volume_id)
+ @storage_pool = @source_volume.storage_pool
+ unless @source_volume.supports_lvm_subdivision
+ raise ActionError.new("LVM is not supported for this storage volume")
+ end
+ end
+ authorized!(Privilege::MODIFY, at storage_pool.hardware_pool)
+
+ if source_volume_id
+ @storage_pool = @source_volume.lvm_storage_pool
+ unless @storage_pool
+ # FIXME: what should we do about VG/LV names?
+ # for now auto-create VG name as ovirt_vg_#{@source_volume.id}
+ new_params = { :vg_name => "ovirt_vg_#{@source_volume.id}",
+ :hardware_pool_id => @source_volume.storage_pool.hardware_pool_id}
+ @storage_pool = StoragePool.factory(StoragePool::LVM, new_params)
+ @storage_pool.source_volumes << @source_volume
+ @storage_pool.save!
+ end
+ end
+ @storage_volume = StorageVolume.factory(@storage_pool.get_type_label,
+ { :storage_pool_id =>
+ @storage_pool.id})
+ end
+
+ # Create a new StorageVolume
+ #
+ # === Instance variables
+ # [<tt>@storage_volume</tt>] the newly-created StorageVolume
+ # === Required permissions
+ # [<tt>Privilege::MODIFY</tt>] for the storage volume's HardwarePool
+ def svc_create(storage_type, storage_volume_hash)
+ @storage_volume = StorageVolume.factory(storage_type, storage_volume_hash)
+ authorized!(Privilege::MODIFY, at storage_volume.storage_pool.hardware_pool)
+ StorageVolume.transaction do
+ @storage_volume.save!
+ @task = StorageVolumeTask.new({ :user => @user,
+ :task_target => @storage_volume,
+ :action => StorageVolumeTask::ACTION_CREATE_VOLUME,
+ :state => Task::STATE_QUEUED})
+ @task.save!
+ end
+ return "Storage Volume was successfully created."
+ end
+
+ # Queues StorageVolume with +id+ for deletion
+ #
+ # === Instance variables
+ # [<tt>@storage_volume</tt>] stores the Storage Volume with +id+
+ # [<tt>@storage_pool</tt>] stores the Storage Volume's Storage Pool
+ # === Required permissions
+ # [<tt>Privilege::MODIFY</tt>] on StorageVolume's HardwarePool
+ def svc_destroy(id)
+ lookup(id, Privilege::MODIFY)
+ unless @storage_pool.user_subdividable
+ raise ActionError.new("Unsupported action for " +
+ "#{@storage_volume.get_type_label} volumes.")
+ end
+ unless @storage_volume.vms.empty?
+ vms = @storage_volume.vms.collect {|vm| vm.description}.join(", ")
+ raise ActionError.new("Cannot delete storage assigned to VMs (#{vms})")
+ end
+ name = @storage_volume.display_name
+ StorageVolume.transaction do
+ @storage_volume.state=StorageVolume::STATE_PENDING_DELETION
+ @storage_volume.save!
+ @task = StorageVolumeTask.new({ :user => @user,
+ :task_target => @storage_volume,
+ :action => StorageVolumeTask::ACTION_DELETE_VOLUME,
+ :state => Task::STATE_QUEUED})
+ @task.save!
+ end
+ return "Storage Volume #{name} deletion was successfully queued."
+ end
+
+ private
+ def lookup(id, priv)
+ @storage_volume = StorageVolume.find(id)
+ @storage_pool = @storage_volume.storage_pool
+ authorized!(priv, at storage_pool.hardware_pool)
+ end
+
+end
--
1.6.0.6
More information about the ovirt-devel
mailing list