On Thursday 01 September 2011 20:38:01 jzigmund(a)redhat.com wrote:
From: Jozef Zigmund <jzigmund(a)redhat.com>
Added new events for counting uptimes of deployment with these status
codes: - 1st instance running - when 1st instance of deployment is
running(start point of counting uptime) - all instances runinng - when all
instances of deployment are running(start point of counting global uptime)
- any instances running - when one of running instances is
stopped/failed(end point of counting global uptime) - all instances
stopped - when all instances of deployment are stopped/failed(end point of
counting uptime) ---
src/Gemfile | 3 +-
src/app/helpers/application_helper.rb | 29 +++++++++-------
src/app/models/deployment.rb | 39 ++++++++++++++++++++++
src/app/models/event.rb | 2 +
src/app/models/instance.rb | 6 +++-
src/app/models/instance_observer.rb | 18 ++++++++++
src/app/stylesheets/custom.scss | 4 ++
src/app/views/deployments/_pretty_view.haml | 2 +-
src/app/views/deployments/_properties.haml | 6 +++
src/app/views/pools/_deployments.haml | 8 ++++-
src/spec/helpers/application_helper_spec.rb | 8 +++++
src/spec/models/deployment_spec.rb | 16 +++++++++
src/spec/models/instance_observer_spec.rb | 15 ++++++++-
src/spec/models/instance_spec.rb | 46
+++++++++++++++++++++++++++ 14 files changed, 184 insertions(+), 18
deletions(-)
diff --git a/src/Gemfile b/src/Gemfile
index 05d3b7c..a4cdab7 100644
--- a/src/Gemfile
+++ b/src/Gemfile
@@ -31,6 +31,7 @@ group :development, :test do
#gem 'cucumber-rails'
#gem 'database_cleaner'
#gem 'vcr'
- #gem 'webmock'
#gem 'launchy'
+ #gem 'ruby-debug'
+ #gem 'webmock'
end
diff --git a/src/app/helpers/application_helper.rb
b/src/app/helpers/application_helper.rb index 930ad49..ff1fca7 100644
--- a/src/app/helpers/application_helper.rb
+++ b/src/app/helpers/application_helper.rb
@@ -215,21 +215,24 @@ module ApplicationHelper
title.split(' ').join('_').downcase
end
- def count_uptime(start_time)
- result_string = []
- difference = Time.now.utc - start_time
+ def count_uptime(time)
+ if time
+ result_string = []
- seconds = difference % 60
- difference = (difference - seconds) / 60
- minutes = difference % 60
- difference = (difference - minutes) / 60
- hours = difference % 24
- difference = (difference - hours) / 24
- days = difference % 7
+ seconds = time % 60
+ time = (time - seconds) / 60
+ minutes = time % 60
+ time = (time - minutes) / 60
+ hours = time % 24
+ time = (time - hours) / 24
+ days = time % 7
- result_string<< pluralize(days.to_i, 'day') if days != 0
-
result_string<<"#{"%02d"%hours.to_i}:#{"%02d"%minutes.to_i}:#{"%02d"%secon
ds.to_i}" - result_string.join(", ")
+ result_string<< pluralize(days.to_i, 'day') if days != 0
+
result_string<<"#{"%02d"%hours.to_i}:#{"%02d"%minutes.to_i}:#{"%02d"%secon
ds.to_i}" + result_string.join(", ")
+ else
+ "N/A"
+ end
end
def owner_name(obj)
diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb
index d0ee262..a9db8c9 100644
--- a/src/app/models/deployment.rb
+++ b/src/app/models/deployment.rb
@@ -50,6 +50,9 @@ class Deployment < ActiveRecord::Base
:include => [:role],
:order => "permissions.id ASC"
belongs_to :owner, :class_name => "User", :foreign_key =>
"owner_id"
+
+ has_many :events, :as => :source
+
after_create "assign_owner_roles(owner)"
validates_presence_of :pool_id
@@ -243,4 +246,40 @@ class Deployment < ActiveRecord::Base
end
errs
end
+
+ def all_instances_running?
+ instances.deployed.count == instances.count
+ end
+
+ def any_instance_running?
+ instances.any? {|i| i.state == Instance::STATE_RUNNING }
+ end
+
+ def uptime_1st_instance
+ return if events.empty?
+ if instances.deployed.empty?
+ if instances.count > 1 && events.find_by_status_code(:all_stopped)
&& events.find_by_status_code(:first_running) +
events.find_by_status_code(:all_stopped).event_time -
events.find_by_status_code(:first_running).event_time + elsif
events.find_by_status_code(:all_stopped) &&
events.find_by_status_code(:all_running) +
events.find_by_status_code(:all_stopped).event_time -
events.find_by_status_code(:all_running).event_time + end
+ else
+ if instances.count > 1 && events.find_by_status_code(:first_running)
+ Time.now.utc -
events.find_by_status_code(:first_running).event_time + elsif
events.find_by_status_code(:all_running)
+ Time.now.utc - events.find_by_status_code(:all_running).event_time
+ end
+ end
+ end
+
+ def uptime_all
+ return if events.empty?
+ if instances.deployed.count == instances.count &&
events.find_by_status_code(:all_running) + Time.now.utc -
events.last.event_time
+ elsif instances.count > 1 && events.find_by_status_code(:all_running)
&& events.find_by_status_code(:some_stopped) +
events.find_by_status_code(:some_stopped).event_time -
events.find_by_status_code(:all_running).event_time + elsif
events.find_by_status_code(:all_stopped) &&
events.find_by_status_code(:all_running) +
events.find_by_status_code(:all_stopped).event_time -
events.find_by_status_code(:all_running).event_time + end
+ end
end
diff --git a/src/app/models/event.rb b/src/app/models/event.rb
index 1e17f35..4e54da6 100644
--- a/src/app/models/event.rb
+++ b/src/app/models/event.rb
@@ -39,4 +39,6 @@ class Event < ActiveRecord::Base
validates_presence_of :source_id
validates_presence_of :source_type
+
+ scope :lifetime, where(:status_code => [:first_running, :all_running,
:some_running, :all_stopped]) end
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb
index b682c06..72be16e 100644
--- a/src/app/models/instance.rb
+++ b/src/app/models/instance.rb
@@ -374,9 +374,13 @@ class Instance < ActiveRecord::Base
})
end
+ def first_running?
+ deployment.instances.deployed.detect {|i| i != self} ? false : true
+ end
+
private
def key_name
"#{self.name}_#{Time.now.to_i}_key_#{self.object_id}".gsub(/[^a-zA-Z0-9\.\
-]/, '_') - end
+ end
end
diff --git a/src/app/models/instance_observer.rb
b/src/app/models/instance_observer.rb index a7b53ed..a78966a 100644
--- a/src/app/models/instance_observer.rb
+++ b/src/app/models/instance_observer.rb
@@ -72,6 +72,24 @@ class InstanceObserver < ActiveRecord::Observer
event = Event.new(:source => instance, :event_time => DateTime.now,
:summary => "state changed to #{instance.state}")
event.save!
+ if instance.state == Instance::STATE_RUNNING && instance.deployment
+ event2 = Event.new(:source => instance.deployment, :event_time =>
DateTime.now, + :status_code => "first_running",
:summary => "1st instance is running") if instance.first_running? +
event3 = Event.new(:source => instance.deployment, :event_time =>
DateTime.now, + :status_code => "all_running",
:summary => "All instances are running") if
instance.deployment.all_instances_running? + event2.save! if event2
+ event3.save! if event3
+ elsif (instance.state == Instance::STATE_STOPPED || instance.state
== Instance::STATE_ERROR) && instance.deployment + if
instance.deployment.any_instance_running? &&
!(instance.deployment.events.empty?) + event4 = Event.new(:source
=> instance.deployment, :event_time => DateTime.now, +
:status_code => "some_stopped", :summary => "Some instances
are
stopped") if instance.deployment.events.lifetime.last{|e|e.status_code ==
:all_running} + else
+ event4 = Event.new(:source => instance.deployment, :event_time
=> DateTime.now, + :status_code =>
"all_stopped", :summary => "All instances are stopped") +
end
+ event4.save! if event4
+ end
+
end
end
diff --git a/src/app/stylesheets/custom.scss
b/src/app/stylesheets/custom.scss index fae47c7..967d848 100644
--- a/src/app/stylesheets/custom.scss
+++ b/src/app/stylesheets/custom.scss
@@ -77,4 +77,8 @@ footer.standard{
height: 30px;
display:block;
background: url(../../images/loading.gif) no-repeat center;
+}
+
+ul.deployment-array.small li.deployment {
+ height: 90px;
}
\ No newline at end of file
diff --git a/src/app/views/deployments/_pretty_view.haml
b/src/app/views/deployments/_pretty_view.haml index 76b5ca5..b04b579
100644
--- a/src/app/views/deployments/_pretty_view.haml
+++ b/src/app/views/deployments/_pretty_view.haml
@@ -8,7 +8,7 @@
%ul
%li.uptime
%dt.uptime Uptime
- %dd= count_uptime(deployment.created_at)
+ %dd= count_uptime(deployment.uptime_1st_instance)
%li.instances
%dt.instances.count Instances
%dd
diff --git a/src/app/views/deployments/_properties.haml
b/src/app/views/deployments/_properties.haml index 0168eb7..e7deb23 100644
--- a/src/app/views/deployments/_properties.haml
+++ b/src/app/views/deployments/_properties.haml
@@ -8,6 +8,12 @@
%tr
%td=key.to_s.capitalize
%td=value
+ %tr
+ %td Global Uptime
+ %td=count_uptime((a)deployment.uptime_all)
+ %tr
+ %td Uptime 1st instance running
+ %td=count_uptime((a)deployment.uptime_1st_instance)
:javascript
Conductor.setupPrettyFilterURL(
diff --git a/src/app/views/pools/_deployments.haml
b/src/app/views/pools/_deployments.haml index cdd99ad..6a4833a 100644
--- a/src/app/views/pools/_deployments.haml
+++ b/src/app/views/pools/_deployments.haml
@@ -4,8 +4,14 @@
%li.deployment
%h3.name
= link_to deployment.name, deployment_path(deployment)
+ Global uptime
+ = count_uptime(deployment.uptime_all)
%dl.statistics
%ul
%li.right
%dt.instances.count Instances
- %dd= deployment.instances.count || 0
\ No newline at end of file
+ %dd= deployment.instances.count || 0
+
+ %li.left
+ %dt Uptime
+ %dd= count_uptime(deployment.uptime_1st_instance)
\ No newline at end of file
diff --git a/src/spec/helpers/application_helper_spec.rb
b/src/spec/helpers/application_helper_spec.rb index fe5c956..e417044
100644
--- a/src/spec/helpers/application_helper_spec.rb
+++ b/src/spec/helpers/application_helper_spec.rb
@@ -32,6 +32,14 @@ describe ApplicationHelper do
node.first['id'].should == 'delete'
end
+ it "count_uptime should return right values" do
+ count_uptime(Time.now-(Time.now-10)).should be_true
+ end
+
+ it "count_uptime should return N/A if nil is passed as parameter" do
+ count_uptime(nil).should == "N/A"
+ end
+
end
end
diff --git a/src/spec/models/deployment_spec.rb
b/src/spec/models/deployment_spec.rb index 7359910..182b48d 100644
--- a/src/spec/models/deployment_spec.rb
+++ b/src/spec/models/deployment_spec.rb
@@ -124,4 +124,20 @@ describe Deployment do
lambda {Instance.find(inst1.id)}.should
raise_error(ActiveRecord::RecordNotFound) lambda
{Instance.find(inst2.id)}.should raise_error(ActiveRecord::RecordNotFound)
end
+
+ it "should be return nil if deployment has no events " do
+ deployment = Factory :deployment
+ deployment.uptime_1st_instance.should be_nil
+ deployment.uptime_all.should be_nil
+ end
+
+ it "should return false if no deployed instances" do
+ deployment = Factory.build :deployment
+ instance = Factory.build(:mock_running_instance, :deployment =>
deployment) + instance2 = Factory.build(:mock_pending_instance,
:deployment => deployment) + deployment.stub(:instances){[instance,
instance2]}
+ deployment.any_instance_running?.should be_true
+ instance.state = Instance::STATE_PENDING
+ deployment.any_instance_running?.should be_false
+ end
end
diff --git a/src/spec/models/instance_observer_spec.rb
b/src/spec/models/instance_observer_spec.rb index c4d0a42..4be3b1e 100644
--- a/src/spec/models/instance_observer_spec.rb
+++ b/src/spec/models/instance_observer_spec.rb
@@ -77,7 +77,7 @@ describe InstanceObserver do
it "should set accumlated shutting down time when instance changes state
from state shutting down" do @instance.state =
Instance::STATE_SHUTTING_DOWN
- @instance.save!;
+ @instance.save!
Timecop.freeze(Time.now + 1.second)
@@ -199,4 +199,17 @@ describe InstanceObserver do
@instance.instance_key.reload
@instance.instance_key.should be_nil
end
+
+ it "should create event when one of deployment's instance
stop/fail'" do
+ deployment = Factory :deployment
+ instance1 = Factory :mock_running_instance, :deployment => deployment
+ instance2 = Factory :mock_running_instance, :deployment => deployment
+ instance3 = Factory :mock_pending_instance, :deployment => deployment
+ instance3.state = Instance::STATE_RUNNING
+ instance3.save!
+ instance2.state = Instance::STATE_ERROR
+ instance2.save!
+ deployment.events.last.status_code.should == "some_stopped"
+ end
+
end
diff --git a/src/spec/models/instance_spec.rb
b/src/spec/models/instance_spec.rb index da0f849..bafac16 100644
--- a/src/spec/models/instance_spec.rb
+++ b/src/spec/models/instance_spec.rb
@@ -210,5 +210,51 @@ describe Instance do
export_string.include?(instance.id.to_s).should be_true
export_string.include?("Instance").should be_true
export_string.include?("created").should be_true
+
+ context "When more instances of deployment are starting" do
+ it "should return true if first instance of deployment is running" do
+ deployment = Factory.build :deployment
+ instance1 = Factory.build(:mock_running_instance, :deployment =>
deployment) + instance2 = Factory.build(:mock_pending_instance,
:deployment => deployment) + instance3 =
Factory.build(:mock_pending_instance, :deployment => deployment) +
instance1.state = Instance::STATE_RUNNING
+ deployment.stub(:instances){[instance1, instance2, instance3]}
+ instance1.first_running?.should be_true
+ instance2.state = Instance::STATE_RUNNING
+ instance1.first_running?.should be_false
+ end
+
+ it "should return true if first instance of deployment is running" do
+ deployment = Factory.build :deployment
+ instance1 = Factory.build(:mock_running_instance, :deployment =>
deployment) + instance2 = Factory.build(:mock_running_instance,
:deployment => deployment) + instance3 =
Factory.build(:mock_pending_instance, :deployment => deployment) +
deployment.stub(:instances){[instance1, instance3, instance2]} +
instance1.all_running?.should be_false
+ instance3.state = Instance::STATE_RUNNING
+ instance1.all_running?.should be_true
+ end
+ end
+
+ context "When more instances of deployment are starting" do
+ it "should return true if first instance of deployment is running" do
+ deployment = Factory :deployment
+ instance1 = Factory(:mock_running_instance, :deployment =>
deployment) + instance2 = Factory(:mock_pending_instance, :deployment
=> deployment) + instance3 = Factory(:mock_pending_instance,
:deployment => deployment) + instance1.first_running?.should be_true
+ instance2.update_attribute :state, Instance::STATE_RUNNING
+ instance2.first_running?.should be_false
+ end
+
+ it "should return true if all instance of deployment is running" do
+ deployment = Factory :deployment
+ instance1 = Factory(:mock_running_instance, :deployment =>
deployment) + instance2 = Factory(:mock_running_instance, :deployment
=> deployment) + instance3 = Factory(:mock_pending_instance,
:deployment => deployment) + deployment.all_instances_running?.should
be_false
+ instance3.update_attribute :state, Instance::STATE_RUNNING
+ deployment.all_instances_running?.should be_true
+ end
end
end
Please ignore this patch, one test is failing, I'm fixing it and I'll
resend
the patch soon.
--
Jozef Zigmund