[email protected] wrote: > From: martyntaylor <[email protected]> > > --- > src/app/controllers/quota_controller.rb | 134 > ++++++++++++++++++++++++ > src/app/views/pool/show.html.erb | 1 + > src/app/views/provider/accounts.html.erb | 1 + > src/app/views/quota/edit.html.erb | 21 ++++ > src/app/views/quota/new.html.erb | 21 ++++ > src/app/views/quota/show.html.erb | 58 ++++++++++ > src/db/migrate/20090802000000_create_quotas.rb | 15 ++- > src/features/pool.feature | 27 +++++ > src/features/step_definitions/pool_steps.rb | 10 ++ > 9 files changed, 283 insertions(+), 5 deletions(-) > create mode 100644 src/app/controllers/quota_controller.rb > create mode 100644 src/app/views/quota/edit.html.erb > create mode 100644 src/app/views/quota/new.html.erb > create mode 100644 src/app/views/quota/show.html.erb > > diff --git a/src/app/controllers/quota_controller.rb > b/src/app/controllers/quota_controller.rb > new file mode 100644 > index 0000000..cf84ee9 > --- /dev/null > +++ b/src/app/controllers/quota_controller.rb > @@ -0,0 +1,134 @@ > + > + > +class QuotaController < ApplicationController > + > I'm thinking for these quota controller methods, :id should refer to the quota ID. For show/edit you won't need parent_type since that can be inferred from the quota object -- and for new/create, there would be no id, but there'd be either a pool_id or cloud_account ID > + def show > + @parent = get_parent_object(params) > + @parent_type = params[:parent_type] > + if Quota.exists?(@parent.quota_id) > + @quota = Quota.find(@parent.quota_id) > + end > + require_privilege(Privilege::QUOTA_VIEW, @parent) > + end > + > + def new > + @parent = get_parent_object(params) > + @parent_type = params[:parent_type] > + @name = get_parent_name(@parent, @parent_type) > + require_privilege(Privilege::QUOTA_MODIFY, @parent) > + end > + > + def create > + #TODO Should be in Transaction > + @parent = get_parent_object(params) > + @parent_type = params[:parent_type] > + > + if !Quota.exists?(@parent.quota_id) > + require_privilege(Privilege::QUOTA_MODIFY, @parent) > + @quota = Quota.new(params[:quota]) > + > + # Populate Current Pool totals to Quota > > So if I'm understanding correctly, the updated model stores the defined quota as well as caching the current usage towards the quota in the same row. Although not part of this patch, we've got to resolve how we're going to keep this in sync, as it needs update every time an instance changes state. > + @parent.instances.each do |instance| > + hwp = HardwareProfile.find(instance.hardware_profile_id) > + if instance.state == Instance::STATE_RUNNING > + @quota.running_instances += 1 > + @quota.running_memory += hwp.memory > + #TODO Add CPUs > + end > + > + if InstanceObserver::ACTIVE_STATES.include?(instance.state) > Wherever we are aggregating current resource usage (which I don't think will be this form), ACTIVE_STATES should apply towards the running_* quota parameters, and _all_ instances, regardless of state should apply to the total_* parameters > + @quota.total_instances += 1 > + @quota.total_storage += hwp.storage > + end > + end > + > + if @quota.save > + flash[:notice] = "Quota Created!" > + @parent.quota_id = @quota.id > + @parent.save! > If @quota defines pool or cloud_account, then just saving the quota should also save the association (at least that's how I think it should work) > + redirect_to :action => 'show', :id => @parent, :parent_type => > @parent_type > + else > + render :action => :new > + end > + else > + @parent.errors.add("quota_id", "There already exists a quota for this > " + @parent_type) > + render :action => :new > + end > + end > + > + def edit > + @parent = get_parent_object(params) > + @parent_type = params[:parent_type] > + @name = get_parent_name(@parent, @parent_type) > + > + @quota = Quota.find(@parent.quota_id) > + > + require_privilege(Privilege::QUOTA_MODIFY, @parent) > + end > + > + def update > + @parent = @parent = get_parent_object(params) > + @parent_type = params[:parent_type] > + require_privilege(Privilege::QUOTA_MODIFY, @parent) > + > + @quota = Quota.find(@parent.quota_id) > + if @quota.update_attributes(params[:quota]) > + flash[:notice] = "Quota updated!" > + redirect_to :action => 'show', :id => @parent, :parent_type => > @parent_type > + else > + render :action => :edit > + end > + end > + > + def delete > + @parent = get_parent_object(params) > + @parent_type = params[:parent_type] > + @quota = Quota.find(@parent.quota_id) > + require_privilege(Privilege::QUOTA_MODIFY, @parent) > + if @quota.delete > + flash[:notice] = "Quota Deleted!" > + redirect_to :action => 'show', :id => @parent, :parent_type => > @parent_type > + end > + end > + > + private > + def get_parent_object(params) > + if params[:parent_type] == "pool" > + return Pool.find(params[:id]) > + elsif params[:parent_type] == "cloud_account" > + return CloudAccount.find(params[:id]) > + end > + #TODO Throw no match to pool or cloud account exception > + end > + > + def get_parent_name(parent, parent_type) > + if parent_type == "pool" > + return parent.name > + elsif parent_type == "cloud_account" > + return parent.username > + end > + #TODO Throw no match to pool or cloud account exception > + end > + > + > +end > diff --git a/src/app/views/pool/show.html.erb > b/src/app/views/pool/show.html.erb > index 1230c64..8fb8fb6 100644 > --- a/src/app/views/pool/show.html.erb > +++ b/src/app/views/pool/show.html.erb > @@ -39,3 +39,4 @@ > <%= link_to "User access", {:controller => "permissions", :action => > "list", :pool_id => @pool.id}, :class=>"actionlink" if has_view_perms? %> > <%= link_to "Hardware Profiles", {:action => "hardware_profiles", :id => > @pool.id}, :class=>"actionlink"%> > <%= link_to "Realms", {:action => "realms", :id => @pool.id}, > :class=>"actionlink"%> > +<%= link_to "Quota", {:controller => "quota", :action => "show", :id => > @pool, :parent_type => "pool"}, :class=>"actionlink"%> > Since you're going to the quota controller, and the action is 'show', I'd think the ID passed in should be the quota ID. This would need some logic around the link to only include 'show' links where one is defined -- with a 'create' link otherwise. In addition, the link should be filtered on permission -- i.e. 'show' link if the user has quota view permissions, etc. > diff --git a/src/app/views/provider/accounts.html.erb > b/src/app/views/provider/accounts.html.erb > index ddc8f27..8ce98a8 100644 > --- a/src/app/views/provider/accounts.html.erb > +++ b/src/app/views/provider/accounts.html.erb > @@ -15,6 +15,7 @@ > <td><%= acct.username %></td> > <td><%= link_to "Edit", {:controller => 'cloud_accounts', > :action => 'edit', :id => acct.id} if has_account_modify?(@provider) > %></td> > <td><%= link_to "Delete", {:controller => 'cloud_accounts', > :action => 'destroy', :id => acct.id} if has_account_modify?(@provider) && > acct.destroyable? %></td> > + <td><%= link_to "Quota", {:controller => 'quota', :action => > 'show', :id => acct.id, :parent_type => "cloud_account"} %></td> > Similar comments here to the link on the pool show view. > </tr> > <% } %> > </tbody> > diff --git a/src/app/views/quota/edit.html.erb > b/src/app/views/quota/edit.html.erb > new file mode 100644 > index 0000000..5e742bb > --- /dev/null > +++ b/src/app/views/quota/edit.html.erb > @@ -0,0 +1,21 @@ > +<div class="dcloud_form"> > + <%= error_messages_for @parent_type %> > + <%= error_messages_for 'quota' %> > + > + <h2>Edit Quota for <%= @parent_type + ": " + @name%></legend></h2><br /> > + > + <% form_tag :action => 'update' do -%> > + <%=hidden_field_tag 'id', @parent.id %> > + <%=hidden_field_tag 'parent_type', @parent_type %> > + > + <ul> > + <li><label>Max Running Instances</label><%= text_field :quota, > :maximum_running_instances %></li> > + <li><label>Max Running Memory</label><%= text_field :quota, > :maximum_running_memory %></li> > + <li><label>Max Running CPUs</label><%= text_field :quota, > :maximum_running_cpus %></li> > + <li><label>Max Total Instances</label><%= text_field :quota, > :maximum_total_instances %></li> > + <li><label>Max Total Storage</label><%= text_field :quota, > :maximum_total_storage %></li> > + </ul> > + </fieldset> > + <%= submit_tag "Save", :class => "submit" %> > + <% end %> > +</div> > \ No newline at end of file > diff --git a/src/app/views/quota/new.html.erb > b/src/app/views/quota/new.html.erb > new file mode 100644 > index 0000000..1f99bd9 > --- /dev/null > +++ b/src/app/views/quota/new.html.erb > @@ -0,0 +1,21 @@ > +<div class="dcloud_form"> > + <%= error_messages_for @parent_type %> > + <%= error_messages_for 'quota' %> > + > + <h2>Create Quota for <%= @parent_type + ": " + @name%></legend></h2><br /> > + > + <% form_tag :action => 'create' do -%> > + <%=hidden_field_tag 'id', @parent.id %> > + <%=hidden_field_tag 'parent_type', @parent_type %> > + > + <ul> > + <li><label>Max Running Instances</label><%= text_field :quota, > :maximum_running_instances %></li> > + <li><label>Max Running Memory</label><%= text_field :quota, > :maximum_running_memory %></li> > + <li><label>Max Running CPUs</label><%= text_field :quota, > :maximum_running_cpus %></li> > + <li><label>Max Total Instances</label><%= text_field :quota, > :maximum_total_instances %></li> > + <li><label>Max Total Storage</label><%= text_field :quota, > :maximum_total_storage %></li> > + </ul> > + </fieldset> > + <%= submit_tag "Save", :class => "submit" %> > + <% end %> > +</div> > \ No newline at end of file > diff --git a/src/app/views/quota/show.html.erb > b/src/app/views/quota/show.html.erb > new file mode 100644 > index 0000000..a3b6366 > --- /dev/null > +++ b/src/app/views/quota/show.html.erb > If we only render the 'show' link for pools/accounts with a quota defined ,we won't need to have the 'there is no quota/create one here' bits. > @@ -0,0 +1,58 @@ > +<% if !...@quota %> > +<h1>There is no Quota on this <%= @parent_type %></h1> > +<%= link_to "Create Quota", {:action => "new", :id => @parent, :parent_type > => @parent_type}, :class=>"actionlink"%> > +<% else %> > + <table> > + <thead> > + <tr> > + <th scope="col">Resource</th> > + <th scope="col">Max Capacity</th> > + <th scope="col">Used Capacity</th> > + <th scope="col">Free Capacity</th> > + <th scope="col">% Used</th> > + </tr> > + </thead> > + <tbody> > + <tr> > + <td>Running Instances</td> > + <td><%= @quota.maximum_running_instances %></td> > + <td><%= @quota.running_instances %></td> > + <td><%= @quota.maximum_running_instances - > @quota.running_instances %></td> > + <td><%= percentage = (100.to_f / > @quota.maximum_running_instances) * @quota.running_instances > + sprintf("%.2f", percentage) %></td> > + </tr> > + <tr> > + <td>Running Memory</td> > + <td><%= @quota.maximum_running_memory %></td> > + <td><%= @quota.running_memory %></td> > + <td><%= @quota.maximum_running_memory - @quota.running_memory > %></td> > + <td><%= percentage = (100.to_f / > @quota.maximum_running_memory) * @quota.running_memory > + sprintf("%.2f", percentage) %></td> > + <td></td> > + </tr> > + <tr> > + <td>Running CPUs</td> > + <td><%= @quota.maximum_running_cpus %></td> > + <td><%= @quota.running_cpus %></td> > + <td><%= @quota.maximum_running_cpus - @quota.running_cpus > %></td> > + <td><%= sprintf("%.2f", (100.to_f / @quota.maximum_running_cpus) * > @quota.running_cpus) %></td> > + </tr> > + <tr> > + <td>Total Instances</td> > + <td><%= @quota.maximum_total_instances %></td> > + <td><%= @quota.total_instances %></td> > + <td><%= @quota.maximum_total_instances - > @quota.total_instances %></td> > + <td><%= sprintf("%.2f", (100.to_f / > @quota.maximum_total_instances) * @quota.total_instances) %></td> > + </tr> > + <tr> > + <td>Total Storage</td> > + <td><%= @quota.maximum_total_storage %></td> > + <td><%= @quota.total_storage %></td> > + <td><%= @quota.maximum_total_storage - @quota.total_storage > %></td> > + <td><%= sprintf("%.2f", (100.to_f / @quota.maximum_total_storage) > * @quota.total_storage) %></td> > + </tr> > + </tbody> > + </table> > + <%= link_to "Edit", {:action => "edit", :id => @parent, :parent_type => > @parent_type}, :class=>"actionlink"%> > + <%= link_to "Delete", {:action => "delete", :id => @parent, :parent_type > => @parent_type}, :class=>"actionlink"%> > +<% end %> > \ No newline at end of file > diff --git a/src/db/migrate/20090802000000_create_quotas.rb > b/src/db/migrate/20090802000000_create_quotas.rb > index c61fb16..01c885d 100644 > --- a/src/db/migrate/20090802000000_create_quotas.rb > +++ b/src/db/migrate/20090802000000_create_quotas.rb > @@ -20,11 +20,16 @@ > class CreateQuotas < ActiveRecord::Migration > def self.up > create_table :quotas do |t| > - t.integer :running_cpus > - t.integer :running_memory > - t.integer :running_instances > - t.integer :total_storage > - t.integer :total_instances > + t.integer :running_cpus, :default => 0 > + t.integer :running_memory, :default => 0 > + t.integer :running_instances, :default => 0 > + t.integer :total_storage, :default => 0 > + t.integer :total_instances, :default => 0 > + t.integer :maximum_running_cpus > + t.integer :maximum_running_memory > + t.integer :maximum_running_instances > + t.integer :maximum_total_storage > + t.integer :maximum_total_instances > t.integer :lock_version, :default => 0 > t.timestamps > end > diff --git a/src/features/pool.feature b/src/features/pool.feature > index 5d8f219..7308dd4 100644 > --- a/src/features/pool.feature > +++ b/src/features/pool.feature > @@ -45,3 +45,30 @@ Feature: Manage Pools > When I follow "Realms" > Then I should see "Europe" > And I should see "United States" > + > + @tag > + Scenario: View Pool's Quota Usage > + Given I own a pool named "mockpool" > + And the Pool has a quota with following capacities: > + | resource | capacity | > + | maximum_running_instances | 10 | > + | maximum_running_memory | 10240 | > + | maximum_running_cpus | 20 | > + | maximum_total_instances | 15 | > + | maximum_total_storage | 8500 | > + | running_instances | 8 | > + | running_memory | 9240 | > + | running_cpus | 16 | > + | total_instances | 15 | > + | total_storage | 8400 | > + And I am on the homepage > + When I follow "mockpool" > + Then I should be on the show pool page > + When I follow "Quota" > + Then I should see the following: > + | Resource | Max Capacity | Used Capacity | Free Capacity | % > Used | > + | Running Instances | 10 | 8 | 2 | > 80.00 | > + | Running Memory | 10240 | 9240 | 1000 | > 90.23 | > + | Running CPUs | 20 | 16 | 4 | > 80.00 | > + | Total Instances | 15 | 15 | 0 | > 100.00 | > + | Total Storage | 8500 | 8400 | 100 | > 98.82 | > \ No newline at end of file > diff --git a/src/features/step_definitions/pool_steps.rb > b/src/features/step_definitions/pool_steps.rb > index 3d97da6..3be5808 100644 > --- a/src/features/step_definitions/pool_steps.rb > +++ b/src/features/step_definitions/pool_steps.rb > @@ -48,3 +48,13 @@ Then /^I should see the following:$/ do |table| > end > end > end > + > +Given /^the Pool has a quota with following capacities:$/ do |table| > + quota_hash = { "pool_id" => @pool, "pool" => @pool} > + table.hashes.each do |hash| > + quota_hash[hash["resource"]] = hash["capacity"] > + end > + > + @quota = Factory(:quota, quota_hash) > + puts @quota.pool_id > +end > \ No newline at end of file >
_______________________________________________ deltacloud-devel mailing list [email protected] https://fedorahosted.org/mailman/listinfo/deltacloud-devel
