From: martyntaylor mtaylor@redhat.com
--- src/app/models/instance.rb | 49 ++++++++++++-- src/app/models/instance_observer.rb | 22 +++++-- src/db/migrate/20090804142049_create_instances.rb | 10 +++- src/spec/factories/instance.rb | 8 ++- src/spec/models/instance_observer_spec.rb | 70 +++++++++++++++++++-- src/spec/models/instance_spec.rb | 23 +++++++ 6 files changed, 160 insertions(+), 22 deletions(-)
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index 25d17bd..07d0784 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,44 @@ 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) + + if !STATES.include?(state) + return "Error, could not calculate state time: invalid state" + end + + case state + 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 + + else + return "Error, could not calculate state time: state is not monitored" end end
diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb index 81e75ea..283991d 100644 --- a/src/app/models/instance_observer.rb +++ b/src/app/models/instance_observer.rb @@ -4,19 +4,29 @@ 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_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_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..335b93f 100644 --- a/src/db/migrate/20090804142049_create_instances.rb +++ b/src/db/migrate/20090804142049_create_instances.rb @@ -33,8 +33,14 @@ 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_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_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..3a453c3 100644 --- a/src/spec/factories/instance.rb +++ b/src/spec/factories/instance.rb @@ -7,6 +7,10 @@ Factory.define :instance do |i| i.state "running" end
-Factory.define :pending_instance, :parent => :instance do |pi| - pi.state "pending" +Factory.define :pending_instance, :parent => :instance do |i| + i.state Instance::STATE_PENDING +end + +Factory.define :new_instance, :parent => :instance do |i| + i.state Instance::STATE_NEW 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..9e3dcc7 100644 --- a/src/spec/models/instance_observer_spec.rb +++ b/src/spec/models/instance_observer_spec.rb @@ -4,26 +4,86 @@ describe InstanceObserver do
before(:each) do @timestamp = Time.now - @instance = Factory :pending_instance + @instance = Factory :new_instance + 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 run time when instance goes to from state running to state stopped" do + 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 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 afdc0e0..0eaf837 100644 --- a/src/spec/models/instance_spec.rb +++ b/src/spec/models/instance_spec.rb @@ -111,5 +111,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 = Factory :new_instance + + [ Instance::STATE_PENDING, Instance::STATE_RUNNING, Instance::STATE_SHUTTING_DOWN, Instance::STATE_STOPPED ].each do |s| + # Test when instance is still in the same state + instance.state = s + instance.save + + sleep(2) + + instance.total_state_time(s).should >= 2 + instance.total_state_time(s).should <= 3 + + # Test when instance has changed state + sleep(1) + instance.state = Instance::STATE_NEW + instance.save + sleep(1) + + instance.total_state_time(s).should >= 3 + instance.total_state_time(s).should <= 4 + end + end
end