[PATCH 1/2] RM3509 re-establish providers/ index page, with useful statistics and graphs
Tzu-Mainn Chen
tzumainn at redhat.com
Thu Jul 19 17:30:31 UTC 2012
---
src/app/controllers/providers_controller.rb | 201 ++++++++++++++++++++++++---
src/app/views/providers/index.html.haml | 73 +++++++++-
src/config/locales/en.yml | 5 +
src/config/routes.rb | 1 +
src/features/provider.feature | 11 --
5 files changed, 258 insertions(+), 33 deletions(-)
diff --git a/src/app/controllers/providers_controller.rb b/src/app/controllers/providers_controller.rb
index 81ac69f..5142997 100644
--- a/src/app/controllers/providers_controller.rb
+++ b/src/app/controllers/providers_controller.rb
@@ -21,27 +21,28 @@ class ProvidersController < ApplicationController
before_filter :parse_provider_type, :only => [:create, :update]
def index
- @params = params
- begin
- @provider = Provider.find(session[:current_provider_id]) if session[:current_provider_id]
- rescue ActiveRecord::RecordNotFound => exc
- logger.error(exc.message)
- ensure
- @provider ||= @providers.first
- end
+ @from_date = params[:from_date].nil? ? Date.today - 7.days :
+ Date.civil(params[:from_date][:year].to_i,
+ params[:from_date][:month].to_i,
+ params[:from_date][:day].to_i)
+ @to_date = params[:to_date].nil? ? Date.today :
+ Date.civil(params[:to_date][:year].to_i,
+ params[:to_date][:month].to_i,
+ params[:to_date][:day].to_i)
+
+ load_headers
+ statistics
respond_to do |format|
- format.html do
- if @providers.present?
- flash.keep
- redirect_to edit_provider_path(@provider)
- else
- render :action => :index
- end
- end
+ format.html
+ format.js { render :partial => 'list' }
format.xml { render :partial => 'list.xml' }
end
+ end
+ def filter
+ redirect_to_original({ "from_date" => params[:from_date],
+ "to_date" => params[:to_date] })
end
def new
@@ -221,8 +222,8 @@ class ProvidersController < ApplicationController
end
def load_providers
- @providers = Provider.list_for_user(current_session, current_user,
- Privilege::VIEW)
+ @providers = Provider.includes(:provider_type).list_for_user(current_session, current_user,
+ Privilege::VIEW).order("name")
end
def disable_provider
@@ -322,4 +323,168 @@ class ProvidersController < ApplicationController
@view = @details_tab[:view]
end
+
+ def load_headers
+ @header = [
+ { :name => t('providers.index.provider_name'), :sortable => false },
+ { :name => t('providers.index.provider_type'), :sortable => false },
+ { :name => t('providers.index.running_instances'), :sortable => false },
+ { :name => t('providers.index.pending_instances'), :sortable => false },
+ { :name => t('providers.index.error_instances'), :sortable => false },
+ { :name => t('providers.index.historical_running_instances'), :sortable => false },
+ { :name => t('providers.index.historical_error_instances'), :sortable => false },
+ ]
+ end
+
+ def statistics
+ @statistics = Hash.new
+ @providers.each do |provider|
+ @statistics[provider.id] = {
+ "running_instances" => 0,
+ "pending_instances" => 0,
+ "error_instances" => 0,
+ "historical_running_instances" => 0,
+ "historical_error_instances" => 0,
+ }
+ end
+
+ # Queries are NOT permissioned by instance, as info is
+ # used purely for statistical purposes.
+
+ # current instances
+ provider_counts = ProviderAccount.joins(:instances).
+ merge(Instance.scoped).
+ select("provider_id, state, count(*) as count").
+ where(:provider_id => @providers.map{|provider| provider.id}).
+ group("provider_id, state")
+
+ provider_counts.each do |provider_count|
+ provider_id = provider_count["provider_id"]
+ state = provider_count["state"]
+ count = provider_count["count"]
+
+ if Instance::FAILED_STATES.include?(state)
+ @statistics[provider_id]["error_instances"] += count.to_i
+ elsif [Instance::STATE_RUNNING, Instance::STATE_SHUTTING_DOWN].
+ include?(state)
+ @statistics[provider_id]["running_instances"] += count.to_i
+ elsif [Instance::STATE_NEW, Instance::STATE_PENDING].
+ include?(state)
+ @statistics[provider_id]["pending_instances"] += count.to_i
+ end
+ end
+
+ # instances that were running between historical date range
+ historical_running_provider_counts = ProviderAccount.joins(:instances).
+ merge(Instance.unscoped).
+ select("provider_id, state, count(*) as count").
+ where(:provider_id => @providers.map{|provider| provider.id}).
+ where("time_last_running <= :to_date and
+ (time_last_stopped is null
+ or time_last_stopped >= :from_date)",
+ :to_date => @to_date.to_datetime.end_of_day,
+ :from_date => @from_date.to_datetime.beginning_of_day
+ ).
+ group("provider_id, state")
+
+ historical_running_provider_counts.each do |provider_count|
+ provider_id = provider_count["provider_id"]
+ count = provider_count["count"]
+
+ @statistics[provider_id]["historical_running_instances"] += count.to_i
+ end
+
+ # instances that threw an error between historical date range
+ historical_error_provider_counts = ProviderAccount.joins(:instances).
+ merge(Instance.unscoped).
+ select("provider_id, count(*) as count").
+ where(:provider_id => @providers.map{|provider| provider.id}).
+ where("instances.state" => Instance::FAILED_STATES).
+ where("instances.updated_at between :from_date and :to_date",
+ :states => Instance::FAILED_STATES,
+ :to_date => @to_date.to_datetime.end_of_day,
+ :from_date => @from_date.to_datetime.beginning_of_day
+ ).
+ group("provider_id")
+
+ historical_error_provider_counts.each do |provider_count|
+ provider_id = provider_count["provider_id"]
+ count = provider_count["count"]
+
+ @statistics[provider_id]["historical_error_instances"] += count.to_i
+ end
+
+ # all running instances during historical date range
+ historical_instances = Instance.unscoped.
+ find(:all,
+ :conditions => ["time_last_running <= ? and
+ (time_last_stopped is null
+ or time_last_stopped >= ?)",
+ @to_date.to_datetime.end_of_day,
+ @from_date.to_datetime.beginning_of_day],
+ :include => {:provider_account => [:provider]}
+ )
+
+ @datasets = Hash.new
+ counts = Hash.new
+ events = Array.new
+
+ counts["All"] = 0
+
+ historical_instances.each do |instance|
+ provider_account = instance.provider_account
+
+ if check_privilege(Privilege::VIEW, provider_account)
+ label = provider_account.nil? ?
+ 'Unknown' :
+ provider_account.provider.name +
+ " (" + provider_account.name + ")"
+
+ if !counts.has_key?(label)
+ counts[label] = 0
+ end
+
+ # see if instance started before from_date
+ if instance.time_last_running <= @from_date.to_datetime.beginning_of_day
+ counts[label] = counts[label] + 1
+ counts["All"] = counts["All"] + 1
+ else
+ events << {
+ "time" => instance.time_last_running,
+ "label" => label,
+ "increment" => 1
+ }
+ end
+
+ if !instance.time_last_stopped.nil? &&
+ instance.time_last_stopped <= @to_date.to_datetime.end_of_day
+ events << {
+ "time" => instance.time_last_stopped,
+ "label" => label,
+ "increment" => -1
+ }
+ end
+ end
+ end
+
+ counts.each.map{ |label,count|
+ @datasets[label] = [[@from_date.to_datetime.beginning_of_day.to_i * 1000,
+ count]]
+ }
+
+ events.sort_by {|event| event["time"]}.each do |event|
+ timestamp = event["time"].to_i * 1000
+ increment = event["increment"]
+
+ [ event["label"], "All" ].each { |label|
+ @datasets[label] << [timestamp - 1, counts[label]]
+ counts[label] = counts[label] + increment
+ @datasets[label] << [timestamp, counts[label]]
+ }
+ end
+
+ counts.each.map{ |label,count|
+ @datasets[label] << [@to_date.to_datetime.end_of_day.to_i * 1000, count]
+ }
+ end
end
diff --git a/src/app/views/providers/index.html.haml b/src/app/views/providers/index.html.haml
index c45d064..9939656 100644
--- a/src/app/views/providers/index.html.haml
+++ b/src/app/views/providers/index.html.haml
@@ -1,6 +1,71 @@
= render :partial => 'layouts/admin_nav'
%section.content-section.provider
- = t("providers.index.no_providers_available")
- - if check_privilege(Privilege::CREATE, Provider)
- = t("providers.index.create_one")
- = link_to t("providers.index.create_new_provider"), new_provider_path, :class => 'button', :id => "create_new_provider"
+ - content_for :form_header do
+ - if check_privilege(Privilege::CREATE, Provider)
+ %li= link_to t("providers.index.create_new_provider"), new_provider_path, :class => 'button', :id => "create_new_provider"
+
+ - content_for :filter_controls do
+ %li
+ = hidden_field_tag :current_path, request.fullpath
+ = t('filter_table.from')
+ = select_date @from_date, :prefix => :from_date
+ = t('filter_table.to')
+ = select_date @to_date, :prefix => :to_date
+ = restful_submit_tag t("filter_table.apply_filters"), "index", filter_providers_path, 'POST', :class => 'button', :id => 'apply_provider_index_filter'
+ %span.label.badge.dark= @providers.count
+ = filter_table(@header, @providers) do |provider|
+ - statistics = @statistics[provider.id]
+ %tr{:class => cycle('nostripe','stripe')}
+ %td= link_to provider.name, edit_provider_path(provider)
+ %td= provider.provider_type.name
+ %td
+ - if statistics["running_instances"] > 0
+ %font{:color => 'green'}= statistics["running_instances"]
+ - else
+ = statistics["running_instances"]
+ %td
+ - if statistics["pending_instances"] > 0
+ %font{:color => 'brown'}= statistics["pending_instances"]
+ - else
+ = statistics["pending_instances"]
+ %td
+ - if statistics["error_instances"] > 0
+ %font{:color => 'red'}= statistics["error_instances"]
+ - else
+ = statistics["error_instances"]
+ %td
+ - if statistics["historical_running_instances"] > 0
+ %font{:color => 'green'}= statistics["historical_running_instances"]
+ - else
+ = statistics["historical_running_instances"]
+ %td
+ - if statistics["historical_error_instances"] > 0
+ %font{:color => 'red'}= statistics["historical_error_instances"]
+ - else
+ = statistics["historical_error_instances"]
+
+ %br
+ %div{:id => 'provider-history-graph', :style => 'width:925px;height:250px;'}
+
+:javascript
+ $(function () {
+ var datasets = [
+ {
+ label: "All",
+ data: [#{ @datasets["All"].each.map{ |p| "[#{p[0]}, #{p[1]}]"}.join(", ") }]
+ },
+ #{ @datasets.reject{|label,data| label == "All"}.each.map{ |label,data| "{
+ label: \"" + label + "\",
+ data: [#{ data.each.map{ |p| "[#{p[0]}, #{p[1]}]"}.join(", ") }]
+ }" }.join(",
+ ") }
+ ];
+
+ $.plot($("#provider-history-graph"), datasets, {
+ xaxis: {
+ mode: "time",
+ min: #{@from_date.to_datetime.beginning_of_day.to_i * 1000},
+ max: #{@to_date.to_datetime.end_of_day.to_i * 1000}
+ }
+ });
+ });
diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml
index 42b15f5..aede674 100644
--- a/src/config/locales/en.yml
+++ b/src/config/locales/en.yml
@@ -1111,6 +1111,11 @@ en:
provider_name: Provider Name
provider_url: Provider URL
provider_type: Provider Type
+ running_instances: Running Instances (Current)
+ pending_instances: Pending (Current)
+ error_instances: Errors (Current)
+ historical_running_instances: Running (Historical)
+ historical_error_instances: Errors (Historical)
x_deltacloud_driver: X-Deltacloud-Driver
x_deltacloud_provider: X-Deltacloud-Provider
no_providers_available: No providers available.
diff --git a/src/config/routes.rb b/src/config/routes.rb
index e7f26c5..3e81885 100644
--- a/src/config/routes.rb
+++ b/src/config/routes.rb
@@ -139,6 +139,7 @@ Conductor::Application.routes.draw do
resources :providers do
delete 'multi_destroy', :on => :collection
+ post :filter, :on => :collection
resources :provider_accounts do
collection do
diff --git a/src/features/provider.feature b/src/features/provider.feature
index 2ba7081..e5ca8dc 100644
--- a/src/features/provider.feature
+++ b/src/features/provider.feature
@@ -92,17 +92,6 @@ Feature: Manage Providers
And I should see "Provider is disabled."
And provider "provider1" should have all instances stopped
- Scenario: Persist selected provider
- Given there is a provider named "provider1"
- And there is a provider named "provider2"
- When I am on the provider1's edit provider page
- And I click on the Providers icon in the menu
- Then I should be on the provider1's edit provider page
- When I am on the provider2's edit provider page
- And I click on the Providers icon in the menu
- Then I should be on the provider2's edit provider page
-
-
# Scenario: Search for hardware profiles
# Given there are these providers:
# | name | url |
--
1.7.6.5
More information about the aeolus-devel
mailing list