[Ovirt-devel] [PATCH server] Revised attempt at refactoring the vm_controller using the service layer.

David Lutterkort lutter at redhat.com
Thu Apr 23 00:12:41 UTC 2009


On Mon, 2009-04-20 at 20:26 +0000, Scott Seago wrote:
> This code is based on David Lutterkort's proposal outlined in
> https://www.redhat.com/archives/ovirt-devel/2009-April/msg00086.html
> 
> I've included service-layer methods for show, create, update, destroy,
> vm_action, and cancel_queued_tasks. These are the concrete actions
> that make sense as part of the API. Most of the remaining
> vm_controller methods are pure-WUI actions -- for things such as
> generating the web form for a new VM (the subsequent 'create' action
> _is_ part of the API).

I really like that, and I also like that most controller methods are now
very short, and give you a much better impression what happens to set up
the view.

The one thing that sticks out is the 'delete' method - that should just
repeatedly call svc_destroy (wrapping the deletion in a txn is somewhat
bogus here, the user should be ok with having only part of the list of
VM's deleted)

I've given this some light testing, and as far as I can tell everything
works well; so ACK from me. The comments below are minor nits and some
ideas on further refactoring that should happen separately.

> diff --git a/src/app/controllers/application.rb b/src/app/controllers/application.rb
> index fa88773..e5f4d4b 100644
> --- a/src/app/controllers/application.rb
> +++ b/src/app/controllers/application.rb

> +  def authorize_view(msg=nil)
> +    authorize_action(Privilege::VIEW,msg)
> +  end

This is unrelated, but it seems odd that we both have authorize_view
here and Pool.can_view - I would argue that the Pool.can_XXX methods
should go away in favor of authorize_XXX and can_XXX methods in the
AppService module (see below)

I like though how authorize_view simplifies the places where we check
for view permissions.

> diff --git a/src/app/controllers/smart_pools_controller.rb b/src/app/controllers/smart_pools_controller.rb
> index f5f3c9d..93c81ee 100644
> --- a/src/app/controllers/smart_pools_controller.rb
> +++ b/src/app/controllers/smart_pools_controller.rb
> @@ -199,19 +199,19 @@ class SmartPoolsController < PoolController
>    def pre_new
>      @pool = SmartPool.new
>      @parent = DirectoryPool.get_or_create_user_root(get_login_user)
> -    @perm_obj = @parent
> +    set_perms(@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
> +    set_perms(@parent)
>      @current_pool_id=@parent.id
>    end
>    def pre_edit
>      @pool = SmartPool.find(params[:id])
>      @parent = @pool.parent
> -    @perm_obj = @pool
> +    set_perms(@pool)
>      @current_pool_id=@pool.id

This code is all over the place, i.e.
        @current_pool_id = some_pool.id
        set_perms(some_pool)

Why not pull setting @current_pool_id into set_perms ?

> diff --git a/src/app/models/vm.rb b/src/app/models/vm.rb
> index c62595a..4c7925c 100644
> --- a/src/app/models/vm.rb
> +++ b/src/app/models/vm.rb
> @@ -220,6 +220,7 @@ class Vm < ActiveRecord::Base
>        self[:boot_device]= BOOT_DEV_HD
>        self[:provisioning]= nil
>      else
> +      # FIXME: Should this case trigger an error instead?
>        self[:boot_device]= BOOT_DEV_NETWORK
>        self[:provisioning]= settings
>      end

Should probably be a separate patch

> diff --git a/src/app/services/application_service.rb b/src/app/services/application_service.rb
> new file mode 100644
> index 0000000..e2d0d38
> --- /dev/null
> +++ b/src/app/services/application_service.rb

> +module ApplicationService
> +  class PermissionError < RuntimeError; end
> +  class ActionError < RuntimeError; end
> +
> +  # Including class must provide a GET_LOGIN_USER
> +
> +  def set_perms(perm_obj)
> +    @perm_obj = perm_obj
> +    @user = get_login_user
> +    @can_view = @perm_obj.can_view(@user)
> +    @can_control_vms = @perm_obj.can_control_vms(@user)
> +    @can_modify = @perm_obj.can_modify(@user)
> +    @can_view_perms = @perm_obj.can_view_perms(@user)
> +    @can_set_perms = @perm_obj.can_set_perms(@user)
> +  end

As we talked about on IRC, longer term it would be better if the
@can_XXX attributes became methods on the service.

I also think the can_XXX methods on pool should be removed and we should
have something like the following in AppService:

        def user
          @user ||= get_login_user
        end
        
        def has_privilege(priv, perm_obj = nil)
          perm_obj ||= @perm_obj
          perm_obj.has_privilege(user, priv)
        end
          
        def can_view(perm_obj = nil)
          has_privilege(Privilege::VIEW, perm_obj)
        end

> diff --git a/src/app/views/vm/_form.rhtml b/src/app/views/vm/_form.rhtml
> index 58a3d61..610f2bc 100644
> --- a/src/app/views/vm/_form.rhtml
> +++ b/src/app/views/vm/_form.rhtml
> @@ -3,8 +3,7 @@
>  <%  start_resources = @vm.vm_resource_pool.available_resources_for_vm(@vm) %>
>  
>  <!--[form:vm]-->
> -<%= hidden_field 'vm', 'vm_resource_pool_id' unless @vm_resource_pool_name %>
> -<%= hidden_field_tag 'vm_resource_pool_name', @vm_resource_pool_name if @vm_resource_pool_name %>
> +<%= hidden_field 'vm', 'vm_resource_pool_id' %>
>  <%= hidden_field_tag 'hardware_pool_id', @hardware_pool.id if @hardware_pool %>
>  
>      <%= text_field_with_label "Name:", "vm", "description", {:style=>"width:250px;"}  %>

Could this go into a separate commit, too ?

David




More information about the ovirt-devel mailing list