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