From: martyntaylor <[email protected]>
---
src/app/models/instance_observer.rb | 41 ++++++++++++++++-
src/app/models/quota.rb | 41 +++++++++++++++++
src/app/models/task.rb | 7 ++-
src/config/environment.rb | 1 +
src/spec/factories/instance.rb | 5 +-
src/spec/models/instance_observer_spec.rb | 68 ++++++++++++++++++++++++++++-
src/spec/models/instance_spec.rb | 10 ++---
src/spec/models/task_spec.rb | 5 --
8 files changed, 159 insertions(+), 19 deletions(-)
diff --git a/src/app/models/instance_observer.rb
b/src/app/models/instance_observer.rb
index fa5b3d2..a7ca75d 100644
--- a/src/app/models/instance_observer.rb
+++ b/src/app/models/instance_observer.rb
@@ -1,11 +1,14 @@
class InstanceObserver < ActiveRecord::Observer
+ ACTIVE_STATES = [ Instance::STATE_NEW, Instance::STATE_PENDING,
Instance::STATE_RUNNING, Instance::STATE_SHUTTING_DOWN, Instance::STATE_STOPPED
]
+
def before_save(an_instance)
if an_instance.changed?
change = an_instance.changes['state']
if change
update_state_timestamps(change[1], an_instance)
update_accumulative_state_time(change[0], an_instance)
+ update_quota(change[0], change[1], an_instance)
end
end
end
@@ -26,7 +29,41 @@ class InstanceObserver < ActiveRecord::Observer
when Instance::STATE_SHUTTING_DOWN then
an_instance.acc_shutting_down_time += Time.now -
an_instance.time_last_shutting_down
when Instance::STATE_STOPPED then an_instance.acc_stopped_time +=
Time.now - an_instance.time_last_stopped
end
- end
+ end
+
+ def update_quota(state_from, state_to, an_instance)
+
+ hwp = HardwareProfile.find(an_instance.hardware_profile_id)
+
+ pool = Pool.find(an_instance.pool_id)
+ cloud_account = CloudAccount.find(an_instance.cloud_account_id)
+
+ [cloud_account, pool].each do |parent|
+ if Quota.exists?(parent.quota_id)
+ quota = Quota.find(parent.quota_id)
+ if state_to == Instance::STATE_RUNNING
+ #TODO update running cpus
+ quota.running_instances += 1
+ quota.running_memory += hwp.memory
+ elsif state_from == Instance::STATE_RUNNING
+ #TODO update running cpus
+ quota.running_instances -= 1
+ quota.running_memory -= hwp.memory
+ end
+
+ if !ACTIVE_STATES.include?(state_from) &&
ACTIVE_STATES.include?(state_to)
+ quota.total_storage += hwp.storage
+ quota.total_instances += 1
+ elsif ACTIVE_STATES.include?(state_from) &&
!ACTIVE_STATES.include?(state_to)
+ quota.total_storage -= hwp.storage
+ quota.total_instances -= 1
+ end
+
+ quota.save!
+ end
+ end
+ end
+
end
-InstanceObserver.instance
\ No newline at end of file
+InstanceObserver.instance
diff --git a/src/app/models/quota.rb b/src/app/models/quota.rb
index 23f9aee..57662a7 100644
--- a/src/app/models/quota.rb
+++ b/src/app/models/quota.rb
@@ -22,4 +22,45 @@
class Quota < ActiveRecord::Base
has_one :pool
has_one :cloud_account
+
+ validates_presence_of :maximum_running_instances
+ validates_presence_of :maximum_running_memory
+ validates_presence_of :maximum_running_cpus
+
+ validates_presence_of :maximum_total_storage
+ validates_presence_of :maximum_total_instances
+
+ validates_numericality_of :maximum_running_instances
+ validates_numericality_of :maximum_running_memory
+ validates_numericality_of :maximum_running_cpus
+
+ validates_numericality_of :maximum_total_storage
+ validates_numericality_of :maximum_total_instances
+
+
+ def can_create_instance?(instance)
+ hwp = HardwareProfile.find(instance.hardware_profile_id)
+
+ if maximum_total_instances >= (total_instances + 1) &&
maximum_total_storage >= (total_storage + hwp.storage)
+ return true
+ end
+ return false
+ end
+
+ def can_start_instance?(instance)
+ hwp = HardwareProfile.find(instance.hardware_profile_id)
+ # TODO Add check for CPUs
+ if maximum_running_instances >= (running_instances + 1) &&
maximum_running_memory >= (running_memory + hwp.memory)
+ return true
+ end
+ return false
+ end
+
+ def validate
+ errors.add("maximum_running_instances", "cannot be less than the current
running instances") if maximum_running_instances < running_instances
+ errors.add("maximum_running_memory", "cannot be less than the current
running memory") if maximum_running_memory < running_memory
+ errors.add("maximum_running_cpus", "cannot be less than the current
running CPUs") if maximum_running_cpus < running_cpus
+ errors.add("maximum_total_storage", "cannot be less than the current total
storage") if maximum_total_storage < total_storage
+ errors.add("maximum_total_instances", "cannot be less than the current
total instances") if maximum_total_instances < total_instances
+ end
end
diff --git a/src/app/models/task.rb b/src/app/models/task.rb
index f3aaa63..feec26a 100644
--- a/src/app/models/task.rb
+++ b/src/app/models/task.rb
@@ -43,7 +43,9 @@ class Task < ActiveRecord::Base
FAILURE_PROVIDER_CONTACT_FAILED = "provider_contact_failed"
FAILURE_PROVIDER_RETURNED_FAILED = "provider_returned_failed"
- FAILURE_CODES = [FAILURE_PROVIDER_NOT_FOUND,
FAILURE_PROVIDER_CONTACT_FAILED, FAILURE_PROVIDER_RETURNED_FAILED]
+ FAILURE_OVER_POOL_QUOTA = "exceeded_pool_quota"
+
+ FAILURE_CODES = [FAILURE_PROVIDER_NOT_FOUND,
FAILURE_PROVIDER_CONTACT_FAILED, FAILURE_PROVIDER_RETURNED_FAILED,
FAILURE_OVER_POOL_QUOTA]
validates_inclusion_of :failure_code,
:in => FAILURE_CODES + [nil]
@@ -114,7 +116,8 @@ class Task < ActiveRecord::Base
def validate
errors.add("created_at", "Task started but does not have the creation time
set") if time_started and created_at.nil?
- errors.add("time_started", "Task ends but does not have the start time
set") if time_ended and time_started.nil?
+ # Removed check on time_started exisiting. if time_ended does. This can
now occur, when the task fails before is starts. e.g. When Over Qutoa
+ #errors.add("time_started", "Task ends but does not have the start time
set") if time_ended and time_started.nil?
errors.add("time_ended", "Tasks ends before it's started") unless
time_ended.nil? or time_started.nil? or time_ended > time_started
errors.add("time_started", "Tasks starts before it's created") unless
time_started.nil? or created_at.nil? or time_started > created_at
end
diff --git a/src/config/environment.rb b/src/config/environment.rb
index 1721126..eefd3a4 100644
--- a/src/config/environment.rb
+++ b/src/config/environment.rb
@@ -77,4 +77,5 @@ Rails::Initializer.run do |config|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales',
'*.{rb,yml}')]
# config.i18n.default_locale = :de
+
end
diff --git a/src/spec/factories/instance.rb b/src/spec/factories/instance.rb
index 3a453c3..68225d0 100644
--- a/src/spec/factories/instance.rb
+++ b/src/spec/factories/instance.rb
@@ -1,7 +1,8 @@
Factory.define :instance do |i|
i.sequence(:name) { |n| "instance#{n}" }
i.sequence(:external_key) { |n| "key#{n}" }
- i.hardware_profile_id 1
+ i.association :hardware_profile, :factory => :hardware_profile_auto
+ i.association :cloud_account, :factory => :mock_cloud_account
i.image_id 1
i.pool_id 1
i.state "running"
@@ -13,4 +14,4 @@ end
Factory.define :new_instance, :parent => :instance do |i|
i.state Instance::STATE_NEW
-end
\ No newline at end of file
+end
diff --git a/src/spec/models/instance_observer_spec.rb
b/src/spec/models/instance_observer_spec.rb
index 9e3dcc7..d713cb1 100644
--- a/src/spec/models/instance_observer_spec.rb
+++ b/src/spec/models/instance_observer_spec.rb
@@ -4,7 +4,15 @@ describe InstanceObserver do
before(:each) do
@timestamp = Time.now
- @instance = Factory :new_instance
+
+ @cloud_account_quota = Factory :quota
+ @cloud_account = Factory(:mock_cloud_account, :quota_id =>
@cloud_account_quota.id)
+
+ @pool_quota = Factory :quota
+ @pool = Factory(:pool, :quota_id => @pool_quota.id)
+
+ @hwp = Factory :mock_hwp1
+ @instance = Factory(:new_instance, :pool => @pool, :hardware_profile =>
@hwp, :cloud_account_id => @cloud_account.id)
end
it "should set started at timestamp when instance goes to state pending" do
@@ -55,7 +63,7 @@ describe InstanceObserver do
sleep(1)
@instance.state = Instance::STATE_SHUTTING_DOWN
- @instance.save
+ @instance.save!
@instance.acc_running_time.should >= 1
@instance.acc_running_time.should <= 2
@@ -86,4 +94,60 @@ describe InstanceObserver do
@instance.acc_stopped_time.should >= 1
@instance.acc_stopped_time.should <= 2
end
+
+ it "should update quota on pool and cloud account when a new instance is
created" do
+ [...@cloud_account_quota, @pool_quota].each do |quota|
+ quota = Quota.find(quota)
+
+ quota.total_instances.should == 1
+ quota.total_storage.should == @hwp.storage
+ end
+ end
+
+ it "should update cloud account and pool quota when an instance goes into an
inactive state" do
+ @instance.state = Instance::STATE_CREATE_FAILED
+ @instance.save!
+
+ [...@cloud_account_quota, @pool_quota].each do |quota|
+ quota = Quota.find(quota)
+
+ quota.total_instances.should == 0
+ quota.total_storage.should == 0
+ end
+ end
+
+ it "should update pool and cloud account quota when an instance state goes
to running" do
+ @instance.state = Instance::STATE_RUNNING
+ @instance.save!
+
+ [...@cloud_account_quota, @pool_quota].each do |quota|
+ quota = Quota.find(quota.id)
+ quota.running_instances.should == 1
+ quota.running_memory.should == @hwp.memory
+ #TODO test for cpus
+
+ quota.total_storage.should == @hwp.storage
+ quota.total_instances.should == 1
+ end
+ end
+
+ it "should update a pool and cloud account quota when an instance state goes
from running to another active state" do
+ @instance.state = Instance::STATE_RUNNING
+ @instance.save!
+
+ @instance.state = Instance::STATE_SHUTTING_DOWN
+ @instance.save!
+
+ [...@cloud_account_quota, @pool_quota].each do |quota|
+ quota = Quota.find(quota.id)
+
+ #TODO test for cpus
+ quota.running_instances.should == 0
+ quota.running_memory.should == 0
+
+ quota.total_storage.should == @hwp.storage
+ quota.total_instances.should == 1
+ end
+ end
+
end
\ No newline at end of file
diff --git a/src/spec/models/instance_spec.rb b/src/spec/models/instance_spec.rb
index 0eaf837..78a0158 100644
--- a/src/spec/models/instance_spec.rb
+++ b/src/spec/models/instance_spec.rb
@@ -2,7 +2,9 @@ require 'spec_helper'
describe Instance do
before(:each) do
- @instance = Factory.build(:instance)
+ @quota = Factory :quota
+ @pool = Factory(:pool, :quota_id => @quota.id)
+ @instance = Factory.build(:instance, :pool_id => @pool.id)
@actions = ['start', 'stop']
end
@@ -69,11 +71,7 @@ describe Instance do
end
it "should return action list" do
- @instance.get_action_list.should eql([])
-
- InstanceTask.stub!(:valid_actions_for_instance_state).and_return(
- @actions)
- @instance.get_action_list.should eql(@actions)
+ @instance.get_action_list.should eql(["reboot", "stop"])
end
it "should be able to queue new actions" do
diff --git a/src/spec/models/task_spec.rb b/src/spec/models/task_spec.rb
index d392cb2..c5e7188 100644
--- a/src/spec/models/task_spec.rb
+++ b/src/spec/models/task_spec.rb
@@ -43,11 +43,6 @@ describe Task do
@task.should_not be_valid
end
- it "should have 'started' time set if it ended" do
- @task.attributes = @valid_attributes.except :time_started
- @task.should_not be_valid
- end
-
it "should not be valid if it started before it was created" do
@task.attributes = @valid_attributes
@task.time_started = @task.created_at - 1.minute
--
1.6.6.1
_______________________________________________
deltacloud-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/deltacloud-devel