From: martyntaylor mtaylor@redhat.com
--- src/app/models/instance.rb | 8 ++++ src/app/models/instance_observer.rb | 22 ++++++++++++ src/app/models/task.rb | 24 ++++++++++++- src/app/models/task_observer.rb | 24 +++++++++++++ src/db/migrate/20090804142049_create_instances.rb | 24 +++++++------ src/db/migrate/20090831140000_create_tasks.rb | 1 + src/spec/factories/instance.rb | 4 ++ src/spec/models/instance_observer_spec.rb | 29 ++++++++++++++++ src/spec/models/task_observer_spec.rb | 38 +++++++++++++++++++++ src/spec/models/task_spec.rb | 5 ++- 10 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 src/app/models/instance_observer.rb create mode 100644 src/app/models/task_observer.rb create mode 100644 src/spec/models/instance_observer_spec.rb create mode 100644 src/spec/models/task_observer_spec.rb
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index fa89844..83b07ef 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -101,5 +101,13 @@ 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 + end + end +
end diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb new file mode 100644 index 0000000..81e75ea --- /dev/null +++ b/src/app/models/instance_observer.rb @@ -0,0 +1,22 @@ +class InstanceObserver < ActiveRecord::Observer + + def after_save(an_instance) + if an_instance.changed? + change = an_instance.changes['state'] + if change + update_timestamps(change[0], change[1], 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) + end + end + +end + +InstanceObserver.instance \ No newline at end of file diff --git a/src/app/models/task.rb b/src/app/models/task.rb index 6cb907e..7cf7347 100644 --- a/src/app/models/task.rb +++ b/src/app/models/task.rb @@ -21,6 +21,7 @@
class Task < ActiveRecord::Base belongs_to :task_target, :polymorphic => true + # InstanceTask association belongs_to :instance, :class_name => "Instance", :foreign_key => "task_target_id" @@ -37,8 +38,28 @@ class Task < ActiveRecord::Base COMPLETED_STATES = [STATE_FINISHED, STATE_FAILED, STATE_CANCELED] WORKING_STATES = [STATE_QUEUED, STATE_RUNNING, STATE_PAUSED]
+ # - Failure Codes - + + # Failures that happen in the provider + PROVIDER_OVER_QUOTA = "PROVIDER_OVER_QUOTA" + PROVIDER_FAILED_TASK = "PROVIDER_FAILED_TASK" + PROVIDER_CONNECTION_FAILURE = "PROVIDER_CONNECTION_FAILURE" + + # Failures that happen in the aggregator + AGGREGATOR_OVER_POOL_QUOTA = "AGGREGATOR_OVER_POOL_QUOTA" + AGGREGATOR_OVER_USER_QUOTA = "AGGREGATOR_OVER_USER_QUOTA" + AGGREGATOR_NO_MATCHING_PROVIDER = "AGGREGATOR_NO_MATCHING_PROVIDER" + + PROVIDER_FAILURE_CODES = [PROVIDER_OVER_QUOTA, PROVIDER_FAILED_TASK, PROVIDER_CONNECTION_FAILURE] + AGGREGATOR_FAILURE_CODES = [AGGREGATOR_OVER_POOL_QUOTA, AGGREGATOR_OVER_USER_QUOTA, AGGREGATOR_NO_MATCHING_PROVIDER] + + FAILURE_CODES = PROVIDER_FAILURE_CODES + AGGREGATOR_FAILURE_CODES + [nil] + + validates_inclusion_of :failure_code, + :in => FAILURE_CODES + validates_inclusion_of :type, - :in => %w( InstanceTask ) + :in => %w( InstanceTask )
validates_inclusion_of :state, :in => COMPLETED_STATES + WORKING_STATES @@ -82,6 +103,7 @@ class Task < ActiveRecord::Base def type_label self.class.name[0..-5] end + def task_obj "" end diff --git a/src/app/models/task_observer.rb b/src/app/models/task_observer.rb new file mode 100644 index 0000000..2614519 --- /dev/null +++ b/src/app/models/task_observer.rb @@ -0,0 +1,24 @@ +class TaskObserver < ActiveRecord::Observer + + END_STATES = [ Task::STATE_CANCELED, Task::STATE_FAILED, Task::STATE_FINISHED ] + + def after_save(a_task) + if a_task.changed? + change = a_task.changes['state'] + if change + update_timestamp(change[0], change[1], a_task) + end + end + end + + def update_timestamp(state_from, state_to, a_task) + if END_STATES.include?(state_to) + a_task.time_ended = Time.now + elsif state_to == Task::STATE_RUNNING + a_task.time_started = Time.now + end + end + +end + +TaskObserver.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 714a7e4..b1e7f80 100644 --- a/src/db/migrate/20090804142049_create_instances.rb +++ b/src/db/migrate/20090804142049_create_instances.rb @@ -22,17 +22,19 @@ class CreateInstances < ActiveRecord::Migration def self.up create_table :instances do |t| - t.string :external_key - t.string :name, :null => false, :limit => 1024 - t.integer :hardware_profile_id, :null => false - t.integer :image_id, :null => false - t.integer :realm_id - t.integer :pool_id, :null => false - t.integer :cloud_account_id - t.string :public_address - t.string :private_address - t.string :state - t.integer :lock_version, :default => 0 + t.string :external_key + t.string :name, :null => false, :limit => 1024 + t.integer :hardware_profile_id, :null => false + t.integer :image_id, :null => false + t.integer :realm_id + t.integer :pool_id, :null => false + t.integer :cloud_account_id + t.string :public_address + t.string :private_address + t.string :state + t.datetime :time_last_start + t.integer :acc_run_time, :default => 0 + t.integer :lock_version, :default => 0 t.timestamps end end diff --git a/src/db/migrate/20090831140000_create_tasks.rb b/src/db/migrate/20090831140000_create_tasks.rb index a9e099f..823b9d0 100644 --- a/src/db/migrate/20090831140000_create_tasks.rb +++ b/src/db/migrate/20090831140000_create_tasks.rb @@ -24,6 +24,7 @@ class CreateTasks < ActiveRecord::Migration t.string :type t.string :action t.string :state + t.string :failure_code t.integer :task_target_id t.string :task_target_type t.string :args diff --git a/src/spec/factories/instance.rb b/src/spec/factories/instance.rb index 0cd1ea2..5855e9d 100644 --- a/src/spec/factories/instance.rb +++ b/src/spec/factories/instance.rb @@ -6,3 +6,7 @@ Factory.define :instance do |i| i.pool_id 1 i.state "running" end + +Factory.define :queued_instance, :parent => :instance do |qi| + qi.state "pending" +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 new file mode 100644 index 0000000..1d1a33a --- /dev/null +++ b/src/spec/models/instance_observer_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe InstanceObserver do + + before(:each) do + @timestamp = Time.now + @instance = Factory :queued_instance + 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 + end + + it "should set accumlated run time when instance goes to from state running to state stopped" do + @instance.state = Instance::STATE_RUNNING + @instance.save; + + sleep(2) + + @instance.state = Instance::STATE_STOPPED + @instance.save + + @instance.acc_run_time.should >= 2 + end + +end \ No newline at end of file diff --git a/src/spec/models/task_observer_spec.rb b/src/spec/models/task_observer_spec.rb new file mode 100644 index 0000000..6a376b3 --- /dev/null +++ b/src/spec/models/task_observer_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe TaskObserver do + + before(:each) do + @timestamp = Time.now + @task = InstanceTask.new({}) + end + + it "should set started at timestamp when the task goes to state running" do + @task.state = Task::STATE_RUNNING + @task.save + + @task.time_started.should >= @timestamp + end + + it "should set ended timestamp when the task has finished" do + @task.state = Task::STATE_FINISHED + @task.save + + @task.time_ended.should >= @timestamp + end + + it "should set ended timestamp when the task is cancelled" do + @task.state = Task::STATE_CANCELED + @task.save + + @task.time_ended.should >= @timestamp + end + + it "should set ended timestamp when the task has failed" do + @task.state = Task::STATE_FAILED + @task.save + + @task.time_ended.should >= @timestamp + end + +end \ No newline at end of file diff --git a/src/spec/models/task_spec.rb b/src/spec/models/task_spec.rb index d392cb2..674c567 100644 --- a/src/spec/models/task_spec.rb +++ b/src/spec/models/task_spec.rb @@ -6,8 +6,9 @@ describe Task do @valid_attributes = { :created_at => Time.now, :time_started => Time.now + 3.minutes, :time_ended => Time.now + 5.minutes, - :state => Task::STATE_FINISHED } - @task = InstanceTask.new( {} ) + :state => Task::STATE_FINISHED, + :failure_code => nil } + @task = InstanceTask.new({}) end
it "should be valid with the test data" do
Note: This patch requires database rebuild
----- Original Message ----- From: mtaylor@redhat.com To: deltacloud-devel@lists.fedorahosted.org Cc: "martyntaylor" mtaylor@redhat.com Sent: Monday, April 26, 2010 5:54:13 PM GMT +00:00 GMT Britain, Ireland, Portugal Subject: [PATCH] Augemented Task State Model + Added Observers for Instance & Task for Auditing
From: martyntaylor mtaylor@redhat.com
--- src/app/models/instance.rb | 8 ++++ src/app/models/instance_observer.rb | 22 ++++++++++++ src/app/models/task.rb | 24 ++++++++++++- src/app/models/task_observer.rb | 24 +++++++++++++ src/db/migrate/20090804142049_create_instances.rb | 24 +++++++------ src/db/migrate/20090831140000_create_tasks.rb | 1 + src/spec/factories/instance.rb | 4 ++ src/spec/models/instance_observer_spec.rb | 29 ++++++++++++++++ src/spec/models/task_observer_spec.rb | 38 +++++++++++++++++++++ src/spec/models/task_spec.rb | 5 ++- 10 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 src/app/models/instance_observer.rb create mode 100644 src/app/models/task_observer.rb create mode 100644 src/spec/models/instance_observer_spec.rb create mode 100644 src/spec/models/task_observer_spec.rb
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index fa89844..83b07ef 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -101,5 +101,13 @@ 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 + end + end +
end diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb new file mode 100644 index 0000000..81e75ea --- /dev/null +++ b/src/app/models/instance_observer.rb @@ -0,0 +1,22 @@ +class InstanceObserver < ActiveRecord::Observer + + def after_save(an_instance) + if an_instance.changed? + change = an_instance.changes['state'] + if change + update_timestamps(change[0], change[1], 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) + end + end + +end + +InstanceObserver.instance \ No newline at end of file diff --git a/src/app/models/task.rb b/src/app/models/task.rb index 6cb907e..7cf7347 100644 --- a/src/app/models/task.rb +++ b/src/app/models/task.rb @@ -21,6 +21,7 @@
class Task < ActiveRecord::Base belongs_to :task_target, :polymorphic => true + # InstanceTask association belongs_to :instance, :class_name => "Instance", :foreign_key => "task_target_id" @@ -37,8 +38,28 @@ class Task < ActiveRecord::Base COMPLETED_STATES = [STATE_FINISHED, STATE_FAILED, STATE_CANCELED] WORKING_STATES = [STATE_QUEUED, STATE_RUNNING, STATE_PAUSED]
+ # - Failure Codes - + + # Failures that happen in the provider + PROVIDER_OVER_QUOTA = "PROVIDER_OVER_QUOTA" + PROVIDER_FAILED_TASK = "PROVIDER_FAILED_TASK" + PROVIDER_CONNECTION_FAILURE = "PROVIDER_CONNECTION_FAILURE" + + # Failures that happen in the aggregator + AGGREGATOR_OVER_POOL_QUOTA = "AGGREGATOR_OVER_POOL_QUOTA" + AGGREGATOR_OVER_USER_QUOTA = "AGGREGATOR_OVER_USER_QUOTA" + AGGREGATOR_NO_MATCHING_PROVIDER = "AGGREGATOR_NO_MATCHING_PROVIDER" + + PROVIDER_FAILURE_CODES = [PROVIDER_OVER_QUOTA, PROVIDER_FAILED_TASK, PROVIDER_CONNECTION_FAILURE] + AGGREGATOR_FAILURE_CODES = [AGGREGATOR_OVER_POOL_QUOTA, AGGREGATOR_OVER_USER_QUOTA, AGGREGATOR_NO_MATCHING_PROVIDER] + + FAILURE_CODES = PROVIDER_FAILURE_CODES + AGGREGATOR_FAILURE_CODES + [nil] + + validates_inclusion_of :failure_code, + :in => FAILURE_CODES + validates_inclusion_of :type, - :in => %w( InstanceTask ) + :in => %w( InstanceTask )
validates_inclusion_of :state, :in => COMPLETED_STATES + WORKING_STATES @@ -82,6 +103,7 @@ class Task < ActiveRecord::Base def type_label self.class.name[0..-5] end + def task_obj "" end diff --git a/src/app/models/task_observer.rb b/src/app/models/task_observer.rb new file mode 100644 index 0000000..2614519 --- /dev/null +++ b/src/app/models/task_observer.rb @@ -0,0 +1,24 @@ +class TaskObserver < ActiveRecord::Observer + + END_STATES = [ Task::STATE_CANCELED, Task::STATE_FAILED, Task::STATE_FINISHED ] + + def after_save(a_task) + if a_task.changed? + change = a_task.changes['state'] + if change + update_timestamp(change[0], change[1], a_task) + end + end + end + + def update_timestamp(state_from, state_to, a_task) + if END_STATES.include?(state_to) + a_task.time_ended = Time.now + elsif state_to == Task::STATE_RUNNING + a_task.time_started = Time.now + end + end + +end + +TaskObserver.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 714a7e4..b1e7f80 100644 --- a/src/db/migrate/20090804142049_create_instances.rb +++ b/src/db/migrate/20090804142049_create_instances.rb @@ -22,17 +22,19 @@ class CreateInstances < ActiveRecord::Migration def self.up create_table :instances do |t| - t.string :external_key - t.string :name, :null => false, :limit => 1024 - t.integer :hardware_profile_id, :null => false - t.integer :image_id, :null => false - t.integer :realm_id - t.integer :pool_id, :null => false - t.integer :cloud_account_id - t.string :public_address - t.string :private_address - t.string :state - t.integer :lock_version, :default => 0 + t.string :external_key + t.string :name, :null => false, :limit => 1024 + t.integer :hardware_profile_id, :null => false + t.integer :image_id, :null => false + t.integer :realm_id + t.integer :pool_id, :null => false + t.integer :cloud_account_id + t.string :public_address + t.string :private_address + t.string :state + t.datetime :time_last_start + t.integer :acc_run_time, :default => 0 + t.integer :lock_version, :default => 0 t.timestamps end end diff --git a/src/db/migrate/20090831140000_create_tasks.rb b/src/db/migrate/20090831140000_create_tasks.rb index a9e099f..823b9d0 100644 --- a/src/db/migrate/20090831140000_create_tasks.rb +++ b/src/db/migrate/20090831140000_create_tasks.rb @@ -24,6 +24,7 @@ class CreateTasks < ActiveRecord::Migration t.string :type t.string :action t.string :state + t.string :failure_code t.integer :task_target_id t.string :task_target_type t.string :args diff --git a/src/spec/factories/instance.rb b/src/spec/factories/instance.rb index 0cd1ea2..5855e9d 100644 --- a/src/spec/factories/instance.rb +++ b/src/spec/factories/instance.rb @@ -6,3 +6,7 @@ Factory.define :instance do |i| i.pool_id 1 i.state "running" end + +Factory.define :queued_instance, :parent => :instance do |qi| + qi.state "pending" +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 new file mode 100644 index 0000000..1d1a33a --- /dev/null +++ b/src/spec/models/instance_observer_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe InstanceObserver do + + before(:each) do + @timestamp = Time.now + @instance = Factory :queued_instance + 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 + end + + it "should set accumlated run time when instance goes to from state running to state stopped" do + @instance.state = Instance::STATE_RUNNING + @instance.save; + + sleep(2) + + @instance.state = Instance::STATE_STOPPED + @instance.save + + @instance.acc_run_time.should >= 2 + end + +end \ No newline at end of file diff --git a/src/spec/models/task_observer_spec.rb b/src/spec/models/task_observer_spec.rb new file mode 100644 index 0000000..6a376b3 --- /dev/null +++ b/src/spec/models/task_observer_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe TaskObserver do + + before(:each) do + @timestamp = Time.now + @task = InstanceTask.new({}) + end + + it "should set started at timestamp when the task goes to state running" do + @task.state = Task::STATE_RUNNING + @task.save + + @task.time_started.should >= @timestamp + end + + it "should set ended timestamp when the task has finished" do + @task.state = Task::STATE_FINISHED + @task.save + + @task.time_ended.should >= @timestamp + end + + it "should set ended timestamp when the task is cancelled" do + @task.state = Task::STATE_CANCELED + @task.save + + @task.time_ended.should >= @timestamp + end + + it "should set ended timestamp when the task has failed" do + @task.state = Task::STATE_FAILED + @task.save + + @task.time_ended.should >= @timestamp + end + +end \ No newline at end of file diff --git a/src/spec/models/task_spec.rb b/src/spec/models/task_spec.rb index d392cb2..674c567 100644 --- a/src/spec/models/task_spec.rb +++ b/src/spec/models/task_spec.rb @@ -6,8 +6,9 @@ describe Task do @valid_attributes = { :created_at => Time.now, :time_started => Time.now + 3.minutes, :time_ended => Time.now + 5.minutes, - :state => Task::STATE_FINISHED } - @task = InstanceTask.new( {} ) + :state => Task::STATE_FINISHED, + :failure_code => nil } + @task = InstanceTask.new({}) end
it "should be valid with the test data" do
Just a few comments inline (I haven't applied/tested it though)
mtaylor@redhat.com wrote:
From: martyntaylor mtaylor@redhat.com
diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb new file mode 100644 index 0000000..81e75ea --- /dev/null +++ b/src/app/models/instance_observer.rb @@ -0,0 +1,22 @@ +class InstanceObserver < ActiveRecord::Observer
- def after_save(an_instance)
- if an_instance.changed?
change = an_instance.changes['state']
if change
update_timestamps(change[0], change[1], 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)
- end
- end
We should make sure that there aren't any hidden edge cases here -- instances going from STATE_RUNNING to _some other state_ and then later to STATE_STOPPED, for example, wouldn't be tracked properly here, if that's a valid state transition -- some providers might return some temporary "stopping" or "stop pending" state which might then later change to stopped. I'm not sure how the various provider FSM diagrams handle stopping, but we need to handle all transitions from running states to stopped states here.
+end
+InstanceObserver.instance \ No newline at end of file diff --git a/src/app/models/task.rb b/src/app/models/task.rb index 6cb907e..7cf7347 100644 --- a/src/app/models/task.rb +++ b/src/app/models/task.rb @@ -21,6 +21,7 @@
class Task < ActiveRecord::Base belongs_to :task_target, :polymorphic => true
- # InstanceTask association belongs_to :instance, :class_name => "Instance", :foreign_key => "task_target_id"
@@ -37,8 +38,28 @@ class Task < ActiveRecord::Base COMPLETED_STATES = [STATE_FINISHED, STATE_FAILED, STATE_CANCELED] WORKING_STATES = [STATE_QUEUED, STATE_RUNNING, STATE_PAUSED]
- # - Failure Codes -
- # Failures that happen in the provider
- PROVIDER_OVER_QUOTA = "PROVIDER_OVER_QUOTA"
- PROVIDER_FAILED_TASK = "PROVIDER_FAILED_TASK"
- PROVIDER_CONNECTION_FAILURE = "PROVIDER_CONNECTION_FAILURE"
- # Failures that happen in the aggregator
- AGGREGATOR_OVER_POOL_QUOTA = "AGGREGATOR_OVER_POOL_QUOTA"
- AGGREGATOR_OVER_USER_QUOTA = "AGGREGATOR_OVER_USER_QUOTA"
We don't need the last one above. There are currently two quota types defined in the aggregator: 1) quota on a pool (shown above) limits amount of resource use by a user/users for a given pool (so this would effectively be a 'user quota', but it's enforced at the pool level) 2) quota on a back end account. If an account is over quota, this will prevent the scheduler from sending it any more 'start instance' requests. If all otherwise-matching accounts are over quota, this will result in a 'no match found' error state as you define below
- AGGREGATOR_NO_MATCHING_PROVIDER = "AGGREGATOR_NO_MATCHING_PROVIDER"
This should ptobably be AGGREGATOR_NO_MATCHING_PROVIDER_ACCOUNT -- since it's the accounts within the providers that are the basic unit of resource matching
- PROVIDER_FAILURE_CODES = [PROVIDER_OVER_QUOTA, PROVIDER_FAILED_TASK, PROVIDER_CONNECTION_FAILURE]
- AGGREGATOR_FAILURE_CODES = [AGGREGATOR_OVER_POOL_QUOTA, AGGREGATOR_OVER_USER_QUOTA, AGGREGATOR_NO_MATCHING_PROVIDER]
- FAILURE_CODES = PROVIDER_FAILURE_CODES + AGGREGATOR_FAILURE_CODES + [nil]
- validates_inclusion_of :failure_code,
- :in => FAILURE_CODES
- validates_inclusion_of :type,
- :in => %w( InstanceTask )
:in => %w( InstanceTask )
validates_inclusion_of :state, :in => COMPLETED_STATES + WORKING_STATES
@@ -82,6 +103,7 @@ class Task < ActiveRecord::Base def type_label self.class.name[0..-5] end
- def task_obj "" end
diff --git a/src/app/models/task_observer.rb b/src/app/models/task_observer.rb new file mode 100644 index 0000000..2614519 --- /dev/null +++ b/src/app/models/task_observer.rb @@ -0,0 +1,24 @@ +class TaskObserver < ActiveRecord::Observer
- END_STATES = [ Task::STATE_CANCELED, Task::STATE_FAILED, Task::STATE_FINISHED ]
- def after_save(a_task)
- if a_task.changed?
change = a_task.changes['state']
if change
update_timestamp(change[0], change[1], a_task)
end
- end
- end
- def update_timestamp(state_from, state_to, a_task)
- if END_STATES.include?(state_to)
a_task.time_ended = Time.now
- elsif state_to == Task::STATE_RUNNING
a_task.time_started = Time.now
- end
- end
+end
+TaskObserver.instance \ No newline at end of file
deltacloud-devel@lists.fedorahosted.org