From: martyntaylor <[email protected]>
---
src/app/controllers/dashboard_controller.rb | 14 ++-
src/app/models/graph.rb | 28 ++++
src/app/services/data_service.rb | 44 ++++---
src/app/services/graph_service.rb | 213 +++++++++++++++------------
src/app/views/dashboard/summary.haml | 2 +-
5 files changed, 185 insertions(+), 116 deletions(-)
diff --git a/src/app/controllers/dashboard_controller.rb
b/src/app/controllers/dashboard_controller.rb
index bcd2073..f971728 100644
--- a/src/app/controllers/dashboard_controller.rb
+++ b/src/app/controllers/dashboard_controller.rb
@@ -39,9 +39,17 @@ class DashboardController < ApplicationController
end
end
- def account_quota_graph
- params[:account] = CloudAccount.find(params[:id])
- graph = GraphService.dashboard_quota(current_user,
params)[params[:account]][Graph::QUOTA_INSTANCES_IN_USE]
+ def quota_usage_graph
+ if params[:cloud_account_id]
+ params[:parent] = CloudAccount.find(params[:cloud_account_id])
+ elsif params[:pool_id]
+ params[:parent] = Pool.find(params[:pool_id])
+ else
+ return nil
+ end
+
+ graphs = GraphService.dashboard_quota_usage(current_user, params)
+ graph =
graphs[params[:parent]][Graph.get_quota_usage_graph_name(params[:resource_name])]
respond_to do |format|
format.svg { render :xml => graph.svg}
end
diff --git a/src/app/models/graph.rb b/src/app/models/graph.rb
index 1c20dc3..cf1b498 100644
--- a/src/app/models/graph.rb
+++ b/src/app/models/graph.rb
@@ -4,7 +4,35 @@ class Graph
QOS_AVG_TIME_TO_SUBMIT = "qos_avg_time_to_submit"
QUOTA_INSTANCES_IN_USE = "quota_instances_in_use"
INSTANCES_BY_PROVIDER_PIE = "instances_by_provider_pie"
+
+ # Quota Usage Graphs
+ QUOTA_USAGE_RUNNING_INSTANCES = "quota_utilization_running_instances"
+ QUOTA_USAGE_RUNNING_MEMORY = "quota_utilization_running_memory"
+ QUOTA_USAGE_RUNNING_CPUS = "quota_utilization_running_cpus"
+ QUOTA_USAGE_TOTAL_INSTANCES = "quota_utilization_total_instances"
+ QUOTA_USAGE_TOTAL_STORAGE = "quota_utilization_total_storage"
+ QUOTA_USAGE_OVERALL = "quota_utilization_overall"
+
def initialize
@svg = ""
end
+
+ def self.get_quota_usage_graph_name(resource_name)
+ case resource_name
+ when Quota::RESOURCE_RUNNING_INSTANCES
+ return QUOTA_USAGE_RUNNING_INSTANCES
+ when Quota::RESOURCE_RUNNING_MEMORY
+ return QUOTA_USAGE_RUNNING_MEMORY
+ when Quota::RESOURCE_RUNNING_CPUS
+ return QUOTA_USAGE_RUNNING_CPUS
+ when Quota::RESOURCE_TOTAL_INSTANCES
+ return QUOTA_USAGE_TOTAL_INSTANCES
+ when Quota::RESOURCE_TOTAL_STORAGE
+ return QUOTA_USAGE_TOTAL_STORAGE
+ when Quota::RESOURCE_OVERALL
+ return QUOTA_USAGE_OVERALL
+ else
+ return nil
+ end
+ end
end
diff --git a/src/app/services/data_service.rb b/src/app/services/data_service.rb
index 776fef7..40968ef 100644
--- a/src/app/services/data_service.rb
+++ b/src/app/services/data_service.rb
@@ -62,24 +62,28 @@ class DataService
# Returns the Used and Maximum Resource Usage
def self.quota_utilisation(parent, resource_name)
- quota = parent.quota
-
- case resource_name
- when Quota::RESOURCE_RUNNING_INSTANCES
- return QuotaUsagePoint.new(quota.running_instances,
quota.maximum_running_instances)
- when Quota::RESOURCE_RUNNING_MEMORY
- return QuotaUsagePoint.new(quota.running_memory.to_f,
quota.maximum_running_memory.to_f)
- when Quota::RESOURCE_RUNNING_CPUS
- return QuotaUsagePoint.new(quota.running_cpus.to_f,
quota.maximum_running_cpus.to_f)
- when Quota::RESOURCE_TOTAL_INSTANCES
- return QuotaUsagePoint.new(quota.total_instances,
quota.maximum_total_instances)
- when Quota::RESOURCE_TOTAL_STORAGE
- return QuotaUsagePoint.new(quota.total_storage.to_f,
quota.maximum_total_storage.to_f)
- when Quota::RESOURCE_OVERALL
- return self.overall_usage(parent)
- else
- return nil
+ if parent
+ quota = parent.quota
+ if quota
+ case resource_name
+ when Quota::RESOURCE_RUNNING_INSTANCES
+ return QuotaUsagePoint.new(quota.running_instances,
quota.maximum_running_instances)
+ when Quota::RESOURCE_RUNNING_MEMORY
+ return QuotaUsagePoint.new(quota.running_memory.to_f,
quota.maximum_running_memory.to_f)
+ when Quota::RESOURCE_RUNNING_CPUS
+ return QuotaUsagePoint.new(quota.running_cpus.to_f,
quota.maximum_running_cpus.to_f)
+ when Quota::RESOURCE_TOTAL_INSTANCES
+ return QuotaUsagePoint.new(quota.total_instances,
quota.maximum_total_instances)
+ when Quota::RESOURCE_TOTAL_STORAGE
+ return QuotaUsagePoint.new(quota.total_storage.to_f,
quota.maximum_total_storage.to_f)
+ when Quota::RESOURCE_OVERALL
+ return self.overall_usage(parent)
+ else
+ return nil
+ end
+ end
end
+ return nil
end
def self.overall_usage(parent)
@@ -91,7 +95,11 @@ class DataService
worst_case = nil
usage_points.each do |usage_point|
if worst_case
- if ((worst_case.max / 100) * worst_case.used) < ((usage_point.max /
100) * usage_point.used)
+ if worst_case.max == Quota::NO_LIMIT
+ worst_case = usage_point
+ elsif usage_point.max == Quota::NO_LIMIT
+ # DO Nothing
+ elsif ((worst_case.max / 100) * worst_case.used) < ((usage_point.max /
100) * usage_point.used)
worst_case = usage_point
end
else
diff --git a/src/app/services/graph_service.rb
b/src/app/services/graph_service.rb
index 11da01c..22e45f1 100644
--- a/src/app/services/graph_service.rb
+++ b/src/app/services/graph_service.rb
@@ -24,6 +24,15 @@ class GraphService
graphs
end
+ def self.dashboard_quota_usage(user, opts = {})
+ parent = opts[:parent]
+
+ graphs = Hash.new
+ graphs[parent] = quota_usage_graph(parent, opts)
+
+ return graphs
+ end
+
def self.dashboard_qos (user,opts = {})
#FIXME add permission checks to filter what graphs user can get
graphs = Hash.new
@@ -58,104 +67,27 @@ class GraphService
output_stream = IO::popen( cmd, "r+")
end
- def self.quota_instances_in_use_graph (cloud_account, opts = {})
- #things we're checking for in opts: :max_value, :height, :width
-
- unless max_value = opts[:max_value]
- max_value = 100 unless max_value =
Quota.maximum('maximum_running_instances')
- end
- height = 80 unless opts[:height].nil? ? nil : height = opts[:height].to_i
- width = 150 unless opts[:width].nil? ? nil : width = opts[:width].to_i
-
-
- raw_svg = ""
- gp = gnuplot_open
- Gnuplot::Plot.new( gp ) do |plot|
- plot.terminal "svg size #{width},#{height}"
- plot.arbitrary_lines << "unset xtics"
- plot.arbitrary_lines << "unset x2tics"
- plot.arbitrary_lines << "unset ytics"
- plot.arbitrary_lines << "unset y2tics"
- plot.arbitrary_lines << "unset border"
-
- plot.set "bmargin","0"
- plot.set "lmargin","0"
- plot.set "rmargin","0"
- plot.set "tmargin","0"
- plot.set "boxwidth 0.9"
- plot.set "style fill solid 1.0"
- plot.set "xrange [.25:2.75]"
- plot.set "yrange [0:#{max_value * 1.5}]" #we want to scale maxvalue 50%
larger to leave room for label
-
- x = [1,2]
- #we'll just have zero values for the unexpected case where cloud_account
has no quota
- y = x.collect { |v| 0 }
- if cloud_account.quota
- quota = cloud_account.quota
- y = [quota.running_instances,quota.maximum_running_instances]
- end
-
-
- #The two arrays above are three columns of data for gnuplot.
- plot.data << Gnuplot::DataSet.new( [[x[0]], [y[0]]] ) do |ds|
- ds.using = "1:2"
- ds.with = 'boxes linecolor rgb "#8cc63f"'
- ds.notitle
- end
-
- #The two arrays above are three columns of data for gnuplot.
- plot.data << Gnuplot::DataSet.new( [[x[1]], [y[1]]] ) do |ds|
- ds.using = "1:2"
- ds.with = 'boxes linecolor rgb "#cccccc"'
- ds.notitle
- end
-
-
- plot.data << Gnuplot::DataSet.new( [x, y] ) do |ds|
- ds.using = "1:2:2"
- ds.with = "labels left offset 0,.15 rotate"
- ds.notitle
- end
- end
- gp.flush
- gp.close_write
- gp.read(nil,raw_svg)
- gp.close_read
-
- #massage the svg so that the histogram's bars are oriented horizontally
- xml = Nokogiri::XML(raw_svg)
-
- nodes = xml.root.children
- wrapper = Nokogiri::XML::Node.new "g", xml.root
-
- nodes.each do |node|
- node.parent = wrapper if node.name != "desc" && node.name != "defs"
- end
-
- wrapper.parent = xml.root
- wrapper.set_attribute 'transform',"translate(#{width},0) rotate(90)
scale(#{height * 1.0 / width},#{width * 1.0/ height})"
-
- text_nodes = []
- xml.root.traverse do |node|
- if node.name == 'text' && node.inner_text.strip =~ /^\d+$/
- if node.parent.name == 'g'
- pparent = node.parent
- text_nodes << pparent
- end
+ def self.quota_usage_graph (parent, opts = {})
+ x = [1,2]
+
+ #we'll just have zero values for the unexpected case where cloud_account
has no quota
+ y = x.collect { |v| 0 }
+ if parent.quota
+ quota = parent.quota
+ data_point = DataService::quota_utilisation(parent, opts[:resource_name])
+ #Handle No Limit case
+ if data_point.max == Quota::NO_LIMIT
+ y = [data_point.used, nil]
+ else
+ y = [data_point.used, data_point.max]
end
end
- text_nodes.each do |node|
- attr = node.get_attribute 'transform'
- node.remove_attribute 'transform'
- node.set_attribute 'transform',"#{attr} scale (#{height * 1.0 /
width},#{width * 1.0/ height})"
- end
-
- modified_svg = xml.to_s
- graph = Graph.new
- graph.svg = modified_svg
- graph
+ chart_opts = {:x => x, :y => y}
+ graphs = Hash.new
+ graphs[Graph.get_quota_usage_graph_name(opts[:resource_name])] =
draw_bar_chart(opts, chart_opts)
+ return graphs
end
def self.qos_avg_time_to_submit_graph (provider, opts = {})
@@ -256,4 +188,97 @@ class GraphService
graph
end
+ def self.draw_bar_chart(opts, chart_opts)
+
+ #things we're checking for in opts: :max_value, :height, :width
+
+ unless max_value = opts[:max_value]
+ max_value = 100 unless max_value =
Quota.maximum('maximum_running_instances')
+ end
+ height = 80 unless opts[:height].nil? ? nil : height = opts[:height].to_i
+ width = 150 unless opts[:width].nil? ? nil : width = opts[:width].to_i
+
+ raw_svg = ""
+ gp = gnuplot_open
+ Gnuplot::Plot.new( gp ) do |plot|
+ plot.terminal "svg size #{width},#{height}"
+ plot.arbitrary_lines << "unset xtics"
+ plot.arbitrary_lines << "unset x2tics"
+ plot.arbitrary_lines << "unset ytics"
+ plot.arbitrary_lines << "unset y2tics"
+ plot.arbitrary_lines << "unset border"
+
+ plot.set "bmargin","0"
+ plot.set "lmargin","0"
+ plot.set "rmargin","0"
+ plot.set "tmargin","0"
+ plot.set "boxwidth 0.9"
+ plot.set "style fill solid 1.0"
+ plot.set "xrange [.25:2.75]"
+ plot.set "yrange [0:#{max_value * 1.5}]" #we want to scale maxvalue 50%
larger to leave room for label
+
+ x = chart_opts[:x]
+ y = chart_opts[:y]
+
+ #The two arrays above are three columns of data for gnuplot.
+ plot.data << Gnuplot::DataSet.new( [[x[0]], [y[0]]] ) do |ds|
+ ds.using = "1:2"
+ ds.with = 'boxes linecolor rgb "#8cc63f"'
+ ds.notitle
+ end
+
+ #The two arrays above are three columns of data for gnuplot.
+ plot.data << Gnuplot::DataSet.new( [[x[1]], [y[1]]] ) do |ds|
+ ds.using = "1:2"
+ ds.with = 'boxes linecolor rgb "#cccccc"'
+ ds.notitle
+ end
+
+
+ plot.data << Gnuplot::DataSet.new( [x, y] ) do |ds|
+ ds.using = "1:2:2"
+ ds.with = "labels left offset 0,.15 rotate"
+ ds.notitle
+ end
+ end
+ gp.flush
+ gp.close_write
+ gp.read(nil,raw_svg)
+ gp.close_read
+
+ #massage the svg so that the histogram's bars are oriented horizontally
+ xml = Nokogiri::XML(raw_svg)
+
+ nodes = xml.root.children
+ wrapper = Nokogiri::XML::Node.new "g", xml.root
+
+ nodes.each do |node|
+ node.parent = wrapper if node.name != "desc" && node.name != "defs"
+ end
+
+ wrapper.parent = xml.root
+ wrapper.set_attribute 'transform',"translate(#{width},0) rotate(90)
scale(#{height * 1.0 / width},#{width * 1.0/ height})"
+
+ text_nodes = []
+ xml.root.traverse do |node|
+ if node.name == 'text' && node.inner_text.strip =~ /^\d+$/
+ if node.parent.name == 'g'
+ pparent = node.parent
+ text_nodes << pparent
+ end
+ end
+ end
+
+ text_nodes.each do |node|
+ attr = node.get_attribute 'transform'
+ node.remove_attribute 'transform'
+ node.set_attribute 'transform',"#{attr} scale (#{height * 1.0 /
width},#{width * 1.0/ height})"
+ end
+
+ modified_svg = xml.to_s
+ graph = Graph.new
+ graph.svg = modified_svg
+ graph
+ end
+
end
diff --git a/src/app/views/dashboard/summary.haml
b/src/app/views/dashboard/summary.haml
index ccbe9aa..a0d6179 100644
--- a/src/app/views/dashboard/summary.haml
+++ b/src/app/views/dashboard/summary.haml
@@ -108,7 +108,7 @@
.account_quota_usage_graph_summary
= account.provider.name + ": " + account.name
.account_quota_usage_current_graph
- %object{ :data => url_for(:action => :account_quota_graph, :id =>
account.id, :width => 100, :height => 50), :type => 'image/svg+xml'}
+ %object{ :data => url_for(:action => :quota_usage_graph,
:cloud_account_id => account.id, :resource_name =>
Quota::RESOURCE_RUNNING_INSTANCES, :width => 100, :height => 50), :type =>
'image/svg+xml'}
<div style="clear: both;" />
:javascript
--
1.6.6.1
_______________________________________________
deltacloud-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/deltacloud-devel