From: martyntaylor mtaylor@redhat.com
--- src/app/models/instance.rb | 47 +++++++++-- src/app/models/instance_observer.rb | 24 ++++-- src/db/migrate/20090804142049_create_instances.rb | 12 +++- src/spec/factories/instance.rb | 6 +- src/spec/models/instance_observer_spec.rb | 90 +++++++++++++++++++- src/spec/models/instance_spec.rb | 23 +++++ 6 files changed, 177 insertions(+), 25 deletions(-)
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index 25d17bd..a17cf91 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -52,10 +52,12 @@ class Instance < ActiveRecord::Base STATE_STOPPED = "stopped" STATE_CREATE_FAILED = "create_failed"
- validates_inclusion_of :state, - :in => [STATE_NEW, STATE_PENDING, STATE_RUNNING, + STATES = [STATE_NEW, STATE_PENDING, STATE_RUNNING, STATE_SHUTTING_DOWN, STATE_STOPPED, STATE_CREATE_FAILED]
+ validates_inclusion_of :state, + :in => STATES + def get_action_list(user=nil) # return empty list rather than nil # FIXME: not handling pending state now -- only current state @@ -101,11 +103,42 @@ class Instance < ActiveRecord::Base self.realm = provider.realms.find_by_name(realm_name) unless realm_name.nil? end
- def total_run_time - if state == STATE_RUNNING - acc_run_time + (Time.now - time_last_start) - else - acc_run_time + # Returns the total time that this instance has been in the state + def total_state_time(state) + case state + when STATE_NEW + if self.state == STATE_NEW + return acc_new_time + (Time.now - time_last_new) + else + return acc_new_time + end + when STATE_PENDING + if self.state == STATE_PENDING + return acc_pending_time + (Time.now - time_last_pending) + else + return acc_pending_time + end + + when STATE_RUNNING + if self.state == STATE_RUNNING + return acc_running_time + (Time.now - time_last_running) + else + return acc_running_time + end + + when STATE_SHUTTING_DOWN + if self.state == STATE_SHUTTING_DOWN + return acc_shutting_down_time + (Time.now - time_last_shutting_down) + else + return acc_shutting_down_time + end + + when STATE_STOPPED + if self.state == STATE_STOPPED + return acc_stopped_time + (Time.now - time_last_stopped) + else + return acc_stopped_time + end end end
diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb index 81e75ea..95f8d19 100644 --- a/src/app/models/instance_observer.rb +++ b/src/app/models/instance_observer.rb @@ -4,19 +4,31 @@ class InstanceObserver < ActiveRecord::Observer if an_instance.changed? change = an_instance.changes['state'] if change - update_timestamps(change[0], change[1], an_instance) + update_state_timestamps(change[1], an_instance) + update_accumulative_state_time(change[0], an_instance) end end end
- def update_timestamps(state_from, state_to, an_instance) - if state_to == Instance::STATE_RUNNING - an_instance.time_last_start = Time.now - elsif state_from == Instance::STATE_RUNNING && state_to == Instance::STATE_STOPPED - an_instance.acc_run_time = an_instance.acc_run_time + (Time.now - an_instance.time_last_start) + def update_state_timestamps(state_to, an_instance) + case state_to + when Instance::STATE_NEW then an_instance.time_last_new = Time.now + when Instance::STATE_PENDING then an_instance.time_last_pending = Time.now + when Instance::STATE_RUNNING then an_instance.time_last_running = Time.now + when Instance::STATE_SHUTTING_DOWN then an_instance.time_last_shutting_down = Time.now + when Instance::STATE_STOPPED then an_instance.time_last_stopped = Time.now end end
+ def update_accumulative_state_time(state_from, an_instance) + case state_from + when Instance::STATE_NEW then an_instance.acc_new_time += Time.now - an_instance.time_last_new + when Instance::STATE_PENDING then an_instance.acc_pending_time += Time.now - an_instance.time_last_pending + when Instance::STATE_RUNNING then an_instance.acc_running_time += Time.now - an_instance.time_last_running + 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
InstanceObserver.instance \ No newline at end of file diff --git a/src/db/migrate/20090804142049_create_instances.rb b/src/db/migrate/20090804142049_create_instances.rb index a571b68..216f091 100644 --- a/src/db/migrate/20090804142049_create_instances.rb +++ b/src/db/migrate/20090804142049_create_instances.rb @@ -33,8 +33,16 @@ class CreateInstances < ActiveRecord::Migration t.string :private_address t.string :state t.integer :lock_version, :default => 0 - t.integer :acc_run_time, :default => 0 - t.timestamp :time_last_start + t.integer :acc_new_time, :default => 0 + t.integer :acc_pending_time, :default => 0 + t.integer :acc_running_time, :default => 0 + t.integer :acc_shutting_down_time, :default => 0 + t.integer :acc_stopped_time, :default => 0 + t.timestamp :time_last_new + t.timestamp :time_last_pending + t.timestamp :time_last_running + t.timestamp :time_last_shutting_down + t.timestamp :time_last_stopped t.timestamps end end diff --git a/src/spec/factories/instance.rb b/src/spec/factories/instance.rb index 12156ec..611212d 100644 --- a/src/spec/factories/instance.rb +++ b/src/spec/factories/instance.rb @@ -4,9 +4,5 @@ Factory.define :instance do |i| i.hardware_profile_id 1 i.image_id 1 i.pool_id 1 - i.state "running" -end - -Factory.define :pending_instance, :parent => :instance do |pi| - pi.state "pending" + i.state Instance::STATE_RUNNING end \ No newline at end of file diff --git a/src/spec/models/instance_observer_spec.rb b/src/spec/models/instance_observer_spec.rb index 65e0d50..a58d55e 100644 --- a/src/spec/models/instance_observer_spec.rb +++ b/src/spec/models/instance_observer_spec.rb @@ -4,26 +4,106 @@ describe InstanceObserver do
before(:each) do @timestamp = Time.now - @instance = Factory :pending_instance + @instance = Factory(:instance, :state => Instance::STATE_CREATE_FAILED) + end + + it "should set new at timestamp when instance goes to state new" do + @instance.state = Instance::STATE_NEW + @instance.save + + @instance.time_last_new.should >= @timestamp + end + + it "should set started at timestamp when instance goes to state pending" do + @instance.state = Instance::STATE_PENDING + @instance.save + + @instance.time_last_pending.should >= @timestamp end
it "should set started at timestamp when instance goes to state running" do @instance.state = Instance::STATE_RUNNING @instance.save
- @instance.time_last_start.should >= @timestamp + @instance.time_last_running.should >= @timestamp + end + + it "should set started at timestamp when instance goes to state shutting down" do + @instance.state = Instance::STATE_SHUTTING_DOWN + @instance.save + + @instance.time_last_shutting_down.should >= @timestamp + end + + it "should set started at timestamp when instance goes to state stopped" do + @instance.state = Instance::STATE_STOPPED + @instance.save + + @instance.time_last_stopped.should >= @timestamp + end + + it "should set accumlated new time when instance changes state from state new" do + @instance.state = Instance::STATE_NEW + @instance.save + + sleep(1) + + @instance.state = Instance::STATE_PENDING + @instance.save + + @instance.acc_new_time.should >= 1 + @instance.acc_new_time.should <= 2 + end + + it "should set accumlated pending time when instance changes state from state pending" do + @instance.state = Instance::STATE_PENDING + @instance.save + + sleep(1) + + @instance.state = Instance::STATE_RUNNING + @instance.save + + @instance.acc_pending_time.should >= 1 + @instance.acc_pending_time.should <= 2 end
- it "should set accumlated run time when instance goes to from state running to state stopped" do + it "should set accumlated running time when instance changes state from state running" do @instance.state = Instance::STATE_RUNNING + @instance.save + + sleep(1) + + @instance.state = Instance::STATE_SHUTTING_DOWN + @instance.save + + @instance.acc_running_time.should >= 1 + @instance.acc_running_time.should <= 2 + end + + it "should set accumlated shutting down time when instance changes state from state shutting down" do + @instance.state = Instance::STATE_SHUTTING_DOWN @instance.save;
- sleep(2) + sleep(1)
@instance.state = Instance::STATE_STOPPED @instance.save
- @instance.acc_run_time.should >= 2 + @instance.acc_shutting_down_time.should >= 1 + @instance.acc_shutting_down_time.should <= 2 end
+ it "should set accumlated stopped time when instance changes state from state stopped" do + @instance.state = Instance::STATE_STOPPED + @instance.save + + sleep(1) + + @instance.state = Instance::STATE_PENDING + @instance.save + + @instance.acc_stopped_time.should >= 1 + @instance.acc_stopped_time.should <= 2 + 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 84cd234..70530a8 100644 --- a/src/spec/models/instance_spec.rb +++ b/src/spec/models/instance_spec.rb @@ -109,5 +109,28 @@ describe Instance do @instance.front_end_realm.should eql('mock2:john doe/different realm') end
+ it "should properly calculate the total time that the instance has been in a monitored state" do + [ Instance::STATE_NEW, Instance::STATE_PENDING, Instance::STATE_RUNNING, Instance::STATE_SHUTTING_DOWN, Instance::STATE_STOPPED ].each do |s| + # Use State create failed as default since it is not monitored + @instance = Factory(:instance, :state => Instance::STATE_CREATE_FAILED) + + # Test when instance is still in the same state + @instance.state = s + @instance.save + + sleep(1) + + @instance.total_state_time(s).should >= 1 + @instance.total_state_time(s).should <= 2 + + # Test when instance has changed state + sleep(1) + @instance.state = Instance::STATE_CREATE_FAILED + @instance.save + + @instance.total_state_time(s).should >= 2 + @instance.total_state_time(s).should <= 3 + end + end
end