Hi, this patchset is partially rebased version previously sent patch: https://fedorahosted.org/pipermail/aeolus-devel/2012-June/010707.html but now it includes couple of additional patches: - events cleanup - delayed_job is used for launch/rollback
Jan
From: Jan Provaznik jprovazn@redhat.com
and Instance::Match usage replaced with InstanceMatch model
https://www.aeolusproject.org/redmine/issues/3361 --- src/app/models/instance.rb | 24 +------------------- src/app/models/instance_match.rb | 17 ++++++++++++++ src/app/models/provider_account.rb | 18 +++++++++++++- src/app/util/taskomatic.rb | 6 ++-- .../20120528130306_create_instance_match.rb | 18 +++++++++++++++ src/spec/factories/instance_match.rb | 23 +++++++++++++++++++ src/spec/models/deployment_spec.rb | 10 ++++---- 7 files changed, 83 insertions(+), 33 deletions(-) create mode 100644 src/app/models/instance_match.rb create mode 100644 src/db/migrate/20120528130306_create_instance_match.rb create mode 100644 src/spec/factories/instance_match.rb
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index 3806d16..88631c1 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -89,6 +89,7 @@ class Instance < ActiveRecord::Base has_many :events, :as => :source, :dependent => :destroy, :order => 'events.id ASC' has_many :instance_parameters, :dependent => :destroy + has_many :instance_matches, :dependent => :destroy has_many :tasks, :as =>:task_target, :dependent => :destroy after_create "assign_owner_roles(owner)"
@@ -352,29 +353,6 @@ class Instance < ActiveRecord::Base includes(:owner).order((order_field || 'name') +' '+ (order_dir || 'asc')) end
- class Match - attr_reader :pool_family, :provider_account, :hwp, :provider_image, :realm, :instance - - def initialize(pool_family, provider_account, hwp, provider_image, realm, instance) - @pool_family = pool_family - @provider_account = provider_account - @hwp = hwp - @provider_image = provider_image - @realm = realm - @instance = instance - end - - def ==(other) - return self.nil? && other.nil? if (self.nil? || other.nil?) - self.pool_family == other.pool_family && - self.provider_account == other.provider_account && - self.hwp == other.hwp && - self.provider_image == other.provider_image && - self.realm == other.realm - self.instance == other.instance - end - end - def image_arch # try to get architecture of the image associated with this instance # for imported images template is empty -> architecture is not set, diff --git a/src/app/models/instance_match.rb b/src/app/models/instance_match.rb new file mode 100644 index 0000000..8d797ca --- /dev/null +++ b/src/app/models/instance_match.rb @@ -0,0 +1,17 @@ +class InstanceMatch < ActiveRecord::Base + belongs_to :instance + belongs_to :pool_family + belongs_to :provider_account + belongs_to :hardware_profile + belongs_to :realm + + def equals?(other) + return self.nil? && other.nil? if (self.nil? || other.nil?) + self.pool_family_id == other.pool_family_id && + self.provider_account_id == other.provider_account_id && + self.hardware_profile_id == other.hardware_profile_id && + self.provider_image == other.provider_image && + self.realm_id == other.realm_id && + self.instance_id == other.instance_id + end +end diff --git a/src/app/models/provider_account.rb b/src/app/models/provider_account.rb index 7fbc584..b9929e5 100644 --- a/src/app/models/provider_account.rb +++ b/src/app/models/provider_account.rb @@ -362,11 +362,25 @@ class ProviderAccount < ActiveRecord::Base # backend realm which is available and is accessible for this # provider account if (brealm_target.target_realm.nil? || (brealm_target.target_realm.available && realms.include?(brealm_target.target_realm))) - matched << Instance::Match.new(instance.pool.pool_family, self, hwp, pi, brealm_target.target_realm, instance) + matched << InstanceMatch.new( + :pool_family => instance.pool.pool_family, + :provider_account => self, + :hardware_profile => hwp, + :provider_image => pi.target_identifier, + :realm => brealm_target.target_realm, + :instance => instance + ) end end else - matched << Instance::Match.new(instance.pool.pool_family, self, hwp, pi, nil, instance) + matched << InstanceMatch.new( + :pool_family => instance.pool.pool_family, + :provider_account => self, + :hardware_profile => hwp, + :provider_image => pi.target_identifier, + :realm => nil, + :instance => instance + ) end end end diff --git a/src/app/util/taskomatic.rb b/src/app/util/taskomatic.rb index 43e7975..994d1f9 100644 --- a/src/app/util/taskomatic.rb +++ b/src/app/util/taskomatic.rb @@ -142,11 +142,11 @@ module Taskomatic client = match.provider_account.connect raise I18n.t("provider_accounts.errors.could_not_connect") unless client
- overrides = HardwareProfile.generate_override_property_values(instance.hardware_profile, match.hwp) + overrides = HardwareProfile.generate_override_property_values(instance.hardware_profile, match.hardware_profile)
- client_args = {:image_id => match.provider_image.target_identifier, + client_args = {:image_id => match.provider_image, :name => instance.name.tr("/", "-"), - :hwp_id => match.hwp.external_key, + :hwp_id => match.hardware_profile.external_key, :hwp_memory => overrides[:memory], :hwp_cpu => overrides[:cpu], :hwp_storage => overrides[:storage], diff --git a/src/db/migrate/20120528130306_create_instance_match.rb b/src/db/migrate/20120528130306_create_instance_match.rb new file mode 100644 index 0000000..9c2688a --- /dev/null +++ b/src/db/migrate/20120528130306_create_instance_match.rb @@ -0,0 +1,18 @@ +class CreateInstanceMatch < ActiveRecord::Migration + def self.up + create_table :instance_matches do |t| + t.integer :pool_family_id + t.integer :provider_account_id + t.integer :hardware_profile_id + t.string :provider_image + t.integer :realm_id + t.integer :instance_id + t.string :error + t.timestamps + end + end + + def self.down + drop_table :instance_matches + end +end diff --git a/src/spec/factories/instance_match.rb b/src/spec/factories/instance_match.rb new file mode 100644 index 0000000..f899927 --- /dev/null +++ b/src/spec/factories/instance_match.rb @@ -0,0 +1,23 @@ +# +# Copyright 2011 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FactoryGirl.define do + factory :instance_match do + association :instance, :factory => :instance + association :hardware_profile, :factory => :mock_hwp1 + association :provider_account, :factory => :mock_provider_account + end +end diff --git a/src/spec/models/deployment_spec.rb b/src/spec/models/deployment_spec.rb index f6b4147..1f4ea9e 100644 --- a/src/spec/models/deployment_spec.rb +++ b/src/spec/models/deployment_spec.rb @@ -593,11 +593,11 @@ describe Deployment do account2 = FactoryGirl.create(:mock_provider_account, :label => "test_account2") account3 = FactoryGirl.create(:mock_provider_account, :label => "test_account3") @deployment.pool.pool_family.provider_accounts += [account1, account2, account3] - possible1 = Instance::Match.new(nil,account1,nil,nil,nil, nil) - possible2 = Instance::Match.new(nil,account2,nil,nil,nil, nil) - possible3 = Instance::Match.new(nil,account2,nil,nil,nil, nil) - possible4 = Instance::Match.new(nil,account3,nil,nil,nil, nil) - possible5 = Instance::Match.new(nil,account2,nil,nil,nil, nil) + possible1 = FactoryGirl.build(:instance_match, :provider_account => account1) + possible2 = FactoryGirl.build(:instance_match, :provider_account => account2) + possible3 = FactoryGirl.build(:instance_match, :provider_account => account2) + possible4 = FactoryGirl.build(:instance_match, :provider_account => account3) + possible5 = FactoryGirl.build(:instance_match, :provider_account => account2)
# not gonna test the individual instance "machtes" logic again # just stub out the behavior
From: Jan Provaznik jprovazn@redhat.com
AR transaction doesn't handle restoring object's state on rollback by default. Till now I used rollback_active_record_state! to restore the state but it turned out that this doesn't work in all cases.
In short the problem is that if you use some other save calls inside transaction, restore might not be restored properly.
So instead of trying to restore deployment's state, new deployment object is created.
If the deployment's launch transaction si rolled back, deployment's id and new_record attrs should be set as for --- src/app/controllers/deployments_controller.rb | 6 ++++++ src/app/models/deployment.rb | 20 +++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/src/app/controllers/deployments_controller.rb b/src/app/controllers/deployments_controller.rb index c935226..73eccce 100644 --- a/src/app/controllers/deployments_controller.rb +++ b/src/app/controllers/deployments_controller.rb @@ -159,6 +159,12 @@ class DeploymentsController < ApplicationController format.js { render :partial => 'properties' } format.json { render :json => @deployment, :status => :created } else + # if rollback was done, we create new @deployment object instead of + # trying restoring the original @deployment's state + # TODO: replace with 'initialize_dup' method after upgrading + # to newer Rails + @deployment = @deployment.copy_as_new + # TODO: put deployment's errors into flash or display inside page? format.html do flash.now[:warning] = t "deployments.flash.warning.failed_to_launch" diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb index f5abd49..792a6ac 100644 --- a/src/app/models/deployment.rb +++ b/src/app/models/deployment.rb @@ -212,13 +212,13 @@ class Deployment < ActiveRecord::Base
def create_and_launch(session, user) begin - rollback_active_record_state! do - # deployment's attrs are not reset on rollback, - # rollback_active_record_state! takes care of this - transaction do - create_instances_with_params!(session, user) - launch!(user) - end + # this method doesn't restore record state if this transaction + # fails, wrapping transaction in rollback_active_record_state! + # is not sufficient because restore then doesn't work if + # you have some nested save operations inside the transaction + transaction do + create_instances_with_params!(session, user) + launch!(user) end return true rescue @@ -486,6 +486,12 @@ class Deployment < ActiveRecord::Base end end
+ def copy_as_new + d = Deployment.new(self.attributes) + d.errors.merge!(self.errors) + d + end + PRESET_FILTERS_OPTIONS = []
private
From: Jan Provaznik jprovazn@redhat.com
If partial launch (with errors) is allowed, the errors should be displayed --- src/app/controllers/deployments_controller.rb | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/app/controllers/deployments_controller.rb b/src/app/controllers/deployments_controller.rb index 73eccce..0ae49a1 100644 --- a/src/app/controllers/deployments_controller.rb +++ b/src/app/controllers/deployments_controller.rb @@ -154,6 +154,9 @@ class DeploymentsController < ApplicationController if @deployment.create_and_launch(current_session, current_user) format.html do flash[:notice] = t "deployments.flash.notice.launched" + if @deployment.errors.present? + flash[:error] = @deployment.errors.full_messages + end redirect_to deployment_path(@deployment) end format.js { render :partial => 'properties' }
From: Jan Provaznik jprovazn@redhat.com
If a deployment launch fails and the deployment is rolled back and there are some other instance matches which can be used for launch, we try to re-launch the deployment with another instance match.
https://www.aeolusproject.org/redmine/issues/3370 --- src/app/models/deployment.rb | 39 ++++++++++++++++++++++++++++++++++- src/app/models/instance.rb | 14 ++++++++++++ src/spec/models/deployment_spec.rb | 33 +++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb index 792a6ac..ac5820f 100644 --- a/src/app/models/deployment.rb +++ b/src/app/models/deployment.rb @@ -82,6 +82,7 @@ class Deployment < ActiveRecord::Base before_create :set_pool_family before_create :set_new_state after_save :log_state_change + after_save :handle_completed_rollback
USER_MUTABLE_ATTRS = ['name']
@@ -230,11 +231,20 @@ class Deployment < ActiveRecord::Base end
def launch!(user) + self.reload unless self.new_record? self.state = STATE_PENDING save! all_inst_match, account, errs = find_match_with_common_account
- unless all_inst_match + if all_inst_match + self.events << Event.create( + :source => self, + :event_time => DateTime.now, + :status_code => 'deployment_launch_match', + :summary => "Attempting to launch this deployment on provider account "\ + "#{account.name}" + ) + else raise I18n.t('deployments.errors.match_not_found', :errors => errs.join(", ")) end @@ -259,7 +269,9 @@ class Deployment < ActiveRecord::Base # occurs (for example DC API is not running, or config server is not # running), then CREATE_FAILED is set in instance.launch! instances.each do |instance| + instance.reset_attrs unless instance.state == Instance::STATE_NEW match = all_inst_match.find{|m| m.instance.id == instance.id} + instance.instance_matches << match begin instance.launch!(match, user, @@ -547,7 +559,8 @@ class Deployment < ActiveRecord::Base all_matches = instances.map do |instance| m, e = instance.matches errors = e.map {|e| "#{instance.name}: #{e}"} - m + # filter matches we used in previous retries + m.select {|inst_match| !instance.includes_instance_match?(inst_match)} end
pool.pool_family.provider_accounts_by_priority.each do |account| @@ -715,4 +728,26 @@ class Deployment < ActiveRecord::Base ) end end + + def handle_completed_rollback + if self.state_changed? and self.state == STATE_ROLLBACK_COMPLETE + begin + if self.events.where( + :status_code => 'deployment_launch_match').count > 9 + raise "There was too many launch retries, aborting" + end + launch!(self.owner) + rescue + self.events << Event.create( + :source => self, + :event_time => DateTime.now, + :status_code => 'deployment_launch_failed', + :summary => "Failed to launch deployment: #{$!.message}" + ) + update_attribute(:state, STATE_FAILED) + logger.error $!.message + logger.error $!.backtrace.join("\n ") + end + end + end end diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index 88631c1..4dd8589 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -387,6 +387,10 @@ class Instance < ActiveRecord::Base [matched, errors] end
+ def includes_instance_match?(match) + instance_matches.any?{|m| m.equals?(match)} + end + def launch!(match, user, config_server, config) # create a taskomatic task task = InstanceTask.create!({:user => user, @@ -498,6 +502,16 @@ class Instance < ActiveRecord::Base end end
+ def reset_attrs + # TODO: is it OK to upload params to config server multiple times? + # do we now keep instance config on config server by default? + update_attributes(:state => Instance::STATE_NEW, + :provider_account => nil, + :public_addresses => nil, + :private_addresses => nil) + instance_key.destroy if instance_key + end + private
def self.apply_search_filter(search) diff --git a/src/spec/models/deployment_spec.rb b/src/spec/models/deployment_spec.rb index 1f4ea9e..cf4cde0 100644 --- a/src/spec/models/deployment_spec.rb +++ b/src/spec/models/deployment_spec.rb @@ -455,7 +455,7 @@ describe Deployment do end end
- context "in rollback_in_progress state" do + context "in rollback_in_progress" do before :each do @deployment.state = Deployment::STATE_ROLLBACK_IN_PROGRESS @deployment.save! @@ -468,6 +468,37 @@ describe Deployment do @deployment.instances << @inst1 @deployment.instances << @inst2 end + + it "should relaunch the deployment if rollback is finished" do + Deployment.any_instance.should_receive(:launch!) + @inst2.update_attribute(:state, Instance::STATE_STOPPED) + end + + describe "on relaunch" do + before :each do + account = Factory.create(:mock_provider_account) + match1 = FactoryGirl.build(:instance_match, + :provider_account => account, + :instance_id => @inst1.id) + match2 = FactoryGirl.build(:instance_match, + :provider_account => account, + :instance_id => @inst2.id) + Instance.any_instance.stub(:launch!).and_return(true) + Deployment.any_instance.stub(:find_match_with_common_account). + and_return([[match1, match2], account, []]) + @inst2.update_attribute(:state, Instance::STATE_STOPPED) + end + + it "should set pending state for the deployment" do + @deployment.reload + @deployment.state.should == Deployment::STATE_PENDING + end + + it "should save instance match for each instance" do + @inst1.instance_matches.count.should > 0 + @inst2.instance_matches.count.should > 0 + end + end end
context "in incomplete state" do
From: Jan Provaznik jprovazn@redhat.com
Now there can be multiple same events (first/some running event) which are used when computing uptime. Last saved event is now used. --- src/app/models/deployment.rb | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb index ac5820f..4e42422 100644 --- a/src/app/models/deployment.rb +++ b/src/app/models/deployment.rb @@ -399,7 +399,7 @@ class Deployment < ActiveRecord::Base def uptime_1st_instance return nil if events.empty?
- first_running = events.find_by_status_code(:first_running) + first_running = events.find_last_by_status_code(:first_running) if instances.deployed.empty? all_stopped = events.find_last_by_status_code(:all_stopped) if all_stopped && first_running && all_stopped.event_time > first_running.event_time @@ -436,7 +436,7 @@ class Deployment < ActiveRecord::Base
# A deployment "starts" when _all_ instances begin to run def start_time - if instances.deployed.count == instances.count && ev = events.find_by_status_code(:all_running) + if instances.deployed.count == instances.count && ev = events.find_last_by_status_code(:all_running) ev.event_time else nil @@ -445,8 +445,8 @@ class Deployment < ActiveRecord::Base
# A deployment "ends" when one or more instances stop, assuming they were ever all-running def end_time - if events.find_by_status_code(:all_running) - ev = events.find_by_status_code(:some_stopped) || events.find_by_status_code(:all_stopped) + if events.find_last_by_status_code(:all_running) + ev = events.find_last_by_status_code(:some_stopped) || events.find_last_by_status_code(:all_stopped) ev.present? ? ev.event_time : nil else nil
From: Jan Provaznik jprovazn@redhat.com
Instances are now launched on background, stopping of instances when doing rollback is on background too.
https://www.aeolusproject.org/redmine/issues/3395 --- src/app/models/deployment.rb | 34 ++++++++++++++++++++++--------- src/config/initializers/delayed_job.rb | 4 ++- src/spec/models/deployment_spec.rb | 2 - 3 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb index 4e42422..7bb5831 100644 --- a/src/app/models/deployment.rb +++ b/src/app/models/deployment.rb @@ -234,6 +234,7 @@ class Deployment < ActiveRecord::Base self.reload unless self.new_record? self.state = STATE_PENDING save! + all_inst_match, account, errs = find_match_with_common_account
if all_inst_match @@ -249,6 +250,11 @@ class Deployment < ActiveRecord::Base :errors => errs.join(", ")) end
+ # Array of InstanceMatches returned by find_match_with_common_account + # is converted to hashes because if we use directly instance of + # InstanceMatch model, delayed job tries to load this object from DB + all_inst_match.map!{|m| m.attributes} + if deployable_xml.requires_config_server? # the instance configurations need to be generated from the entire set of # instances (and not each individual instance) in order to do parameter @@ -262,24 +268,28 @@ class Deployment < ActiveRecord::Base instance_configs = {} end
+ delay.send_launch_requests(all_inst_match, config_server, + instance_configs, user) + end
- # TODO: in follow up patch there should be only delayed job call - # on this place - # For now, we just call DC create intance method on foreground, if an error - # occurs (for example DC API is not running, or config server is not - # running), then CREATE_FAILED is set in instance.launch! + def send_launch_requests(all_inst_match, config_server, instance_configs, user) instances.each do |instance| instance.reset_attrs unless instance.state == Instance::STATE_NEW - match = all_inst_match.find{|m| m.instance.id == instance.id} - instance.instance_matches << match + instance.instance_matches << InstanceMatch.new( + all_inst_match.find{|m| m['instance_id'] == instance.id}) begin - instance.launch!(match, + instance.launch!(instance.instance_matches.last, user, config_server, instance_configs[instance.uuid]) rescue - errors.add(:base, - "#{instance.name}: #{$!.message.to_s.split("\n").first}") + self.events << Event.create( + :source => self, + :event_time => DateTime.now, + :status_code => 'instance_launch_failed', + :summary => "#{instance.name}: #{$!.message.to_s.split("\n").first}" + ) + logger.error $!.message logger.error $!.backtrace.join("\n ")
@@ -695,6 +705,10 @@ class Deployment < ActiveRecord::Base return end
+ delay.send_rollback_requests + end + + def send_rollback_requests error_occured = false instances.running.each do |instance| begin diff --git a/src/config/initializers/delayed_job.rb b/src/config/initializers/delayed_job.rb index 6e0d177..6f95a6b 100644 --- a/src/config/initializers/delayed_job.rb +++ b/src/config/initializers/delayed_job.rb @@ -6,4 +6,6 @@ Delayed::Worker.destroy_failed_jobs = false Delayed::Worker.max_attempts = 2 #Delayed::Worker.max_run_time = 5.minutes #Delayed::Worker.read_ahead = 10 -#Delayed::Worker.delay_jobs = !Rails.env.test? + +# in test env jobs are not delayed and are executed directly +Delayed::Worker.delay_jobs = !Rails.env.test? diff --git a/src/spec/models/deployment_spec.rb b/src/spec/models/deployment_spec.rb index cf4cde0..c996d51 100644 --- a/src/spec/models/deployment_spec.rb +++ b/src/spec/models/deployment_spec.rb @@ -427,8 +427,6 @@ describe Deployment do @inst2.save! @deployment.reload @deployment.state.should == Deployment::STATE_ROLLBACK_IN_PROGRESS - @deployment.events.find_by_status_code('instance_launch_failed'). - should_not be_nil end
it "should stop all running instances if an instance fails" do
From: Jan Provaznik jprovazn@redhat.com
Instance-related events are now associated with an instance, deployment's history page now displays its own events and also events of all its instances.
Changed ordering of events on instance show page to be ascending (deployment events are ascending too). --- src/app/controllers/deployments_controller.rb | 2 +- src/app/controllers/instances_controller.rb | 2 +- src/app/models/deployment.rb | 27 +++++++++--------------- src/app/models/event.rb | 1 - src/app/util/taskomatic.rb | 6 +++++ src/app/views/deployments/_history.html.haml | 5 +++- src/config/locales/en.yml | 2 + 7 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/src/app/controllers/deployments_controller.rb b/src/app/controllers/deployments_controller.rb index 0ae49a1..6dc2c70 100644 --- a/src/app/controllers/deployments_controller.rb +++ b/src/app/controllers/deployments_controller.rb @@ -213,7 +213,7 @@ class DeploymentsController < ApplicationController details_tab_name = params[:details_tab].blank? ? 'instances' : params[:details_tab] @details_tab = @tabs.find {|t| t[:id] == details_tab_name} || @tabs.first[:name].downcase if @details_tab[:id] == 'history' - @events = @deployment.events + @events = @deployment.events_of_deployment_and_instances end if params[:details_tab] @view = @details_tab[:view] diff --git a/src/app/controllers/instances_controller.rb b/src/app/controllers/instances_controller.rb index ac78096..110f1d2 100644 --- a/src/app/controllers/instances_controller.rb +++ b/src/app/controllers/instances_controller.rb @@ -46,7 +46,7 @@ class InstancesController < ApplicationController def show load_instances save_breadcrumb(instance_path(@instance), @instance.name) - @events = @instance.events.descending_by_created_at.paginate(:page => params[:page] || 1) + @events = @instance.events.paginate(:page => params[:page] || 1) @view = params[:details_tab].blank? ? 'properties' : params[:details_tab] @tabs = [ {:name => t('properties'), :view => @view, :id => 'properties'}, diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb index 7bb5831..3ad7863 100644 --- a/src/app/models/deployment.rb +++ b/src/app/models/deployment.rb @@ -283,16 +283,6 @@ class Deployment < ActiveRecord::Base config_server, instance_configs[instance.uuid]) rescue - self.events << Event.create( - :source => self, - :event_time => DateTime.now, - :status_code => 'instance_launch_failed', - :summary => "#{instance.name}: #{$!.message.to_s.split("\n").first}" - ) - - logger.error $!.message - logger.error $!.backtrace.join("\n ") - # be default launching of instances is terminated if an error occurs, # user can set "partial_launch" attribute - launch request is then # sent for all deployment's instances @@ -514,6 +504,15 @@ class Deployment < ActiveRecord::Base d end
+ def events_of_deployment_and_instances + instance_ids = instances.map(&:id) + Event.all(:conditions => ["(source_type='Instance' AND source_id in (?))"\ + "OR (source_type='Deployment' AND source_id=?)", + instance_ids, self.id], + :order => "created_at ASC") + + end + PRESET_FILTERS_OPTIONS = []
private @@ -645,12 +644,6 @@ class Deployment < ActiveRecord::Base elsif partial_launch and instances.all? {|i| i.failed_or_running?} self.state = STATE_RUNNING elsif !partial_launch and Instance::FAILED_STATES.include?(instance.state) - self.events << Event.create( - :source => self, - :event_time => DateTime.now, - :status_code => 'instance_launch_failed', - :summary => "Failed to launch instance #{instance.name}, doing rollback" - ) # TODO: now this is done in instance's after_update callback - as part # of instance save transaction - this might be done on background by # using delayed_job @@ -716,7 +709,7 @@ class Deployment < ActiveRecord::Base rescue error_occured = true self.events << Event.create( - :source => self, + :source => instance, :event_time => DateTime.now, :status_code => 'instance_stop_failed', :summary => "Failed to stop instance #{instance.name}", diff --git a/src/app/models/event.rb b/src/app/models/event.rb index c2593f8..8479c58 100644 --- a/src/app/models/event.rb +++ b/src/app/models/event.rb @@ -46,7 +46,6 @@ class Event < ActiveRecord::Base attr_accessor :change_hash # allows us to pass in .changes on the parent ("source") object
scope :lifetime, where(:status_code => [:first_running, :all_running, :some_running, :all_stopped]) - scope :descending_by_created_at, order('created_at DESC')
# Notifies the Event API if certain conditions are met def transmit_event diff --git a/src/app/util/taskomatic.rb b/src/app/util/taskomatic.rb index 994d1f9..0e95e12 100644 --- a/src/app/util/taskomatic.rb +++ b/src/app/util/taskomatic.rb @@ -135,6 +135,12 @@ module Taskomatic Rails.logger.error ex.backtrace.join("\n") task.state = Task::STATE_FAILED task.instance.state = Instance::STATE_CREATE_FAILED + task.instance.events << Event.create( + :source => task.instance, + :event_time => DateTime.now, + :status_code => 'instance_launch_failed', + :summary => "#{task.instance.name}: #{ex.message.to_s.split("\n").first}" + ) raise ex end
diff --git a/src/app/views/deployments/_history.html.haml b/src/app/views/deployments/_history.html.haml index ece5015..f5dbcec 100644 --- a/src/app/views/deployments/_history.html.haml +++ b/src/app/views/deployments/_history.html.haml @@ -1,4 +1,7 @@ %ol.listing - @events.each do |event| %li - = "#{event.event_time.strftime('%d-%b-%Y %H:%M:%S')}: #{event.summary}" + = "#{event.event_time.strftime('%d-%b-%Y %H:%M:%S')}:" + - if event.source_type == 'Instance' + = link_to t('.instance', :name => event.source.name), instance_path(event.source) + = event.summary diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml index 9c42494..b20ecb6 100644 --- a/src/config/locales/en.yml +++ b/src/config/locales/en.yml @@ -267,6 +267,8 @@ en: deployable_xml: Deployable XML show: name: "%{name} Deployment" + history: + instance: "Instance %{name}" new: launch: Launch this deployment deployable_definition: Deployable definition
From: Jan Provaznik jprovazn@redhat.com
--- .../_deployment_card_index.html.mustache | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/app/views/deployments/_deployment_card_index.html.mustache b/src/app/views/deployments/_deployment_card_index.html.mustache index 875cf95..5984b94 100644 --- a/src/app/views/deployments/_deployment_card_index.html.mustache +++ b/src/app/views/deployments/_deployment_card_index.html.mustache @@ -2,7 +2,7 @@ <h3 class="name"> <a href="{{path}}">{{name}}</a> </h3> - <span class="status {{state}}" title="${translated_state}">{{state}}</span> + <span class="status {{state}}" title="{{translated_state}}">{{state}}</span> <dl class="statistics"> <ul> <li class="right">
On 06/14/2012 03:36 PM, jprovazn@redhat.com wrote:
Hi, this patchset is partially rebased version previously sent patch: https://fedorahosted.org/pipermail/aeolus-devel/2012-June/010707.html but now it includes couple of additional patches:
- events cleanup
- delayed_job is used for launch/rollback
Jan
ACK to the patchset
aeolus-devel@lists.fedorahosted.org