From: martyntaylor <mtaylor(a)redhat.com>
---
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 @@
+#
+# Copyright (C) 2009 Red Hat, Inc.
+#
+# 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.
+
+# Filters added to this controller apply to all controllers in the application.
+# Likewise, all the methods added will be available for all controllers.
+
+
+class QuotaController < ApplicationController
+
+ def show
+ @parent = get_parent_object(params)
+ @parent_type = params[:parent_type]
+ if Quota.exists?((a)parent.quota_id)
+ @quota = Quota.find((a)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?((a)parent.quota_id)
+ require_privilege(Privilege::QUOTA_MODIFY, @parent)
+ @quota = Quota.new(params[:quota])
+
+ # Populate Current Pool totals to Quota
+ @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)
+ @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!
+ 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((a)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((a)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((a)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"%>
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>
</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
@@ -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
--
1.6.6.1