From: martyntaylor <[email protected]>

---
 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
-- 
1.6.6.1

_______________________________________________
deltacloud-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/deltacloud-devel

Reply via email to