This Patch is Dependent on these patches/patch series

Updated Data Service for All Quota Graphs - June 14th
Added No Limits on Quota, force Quota Creation on Parent Create - June 14th

Thanks

Martyn
----- Original Message -----
From: [email protected]
To: [email protected]
Cc: "martyntaylor" <[email protected]>
Sent: Thursday, June 17, 2010 4:17:17 PM GMT +00:00 GMT Britain, Ireland, 
Portugal
Subject: [PATCH aggregator] Generalized Quota Usage graph methods for creation 
of all Quota Usage Graphs

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

Reply via email to