Mohammed Morsi
2008-May-27 21:23 UTC
[Ovirt-devel] [Patch] Experimental Graphs Backend Code
This patch is for review only, and is not meant to be committed (partly because I didn't update before generating it and partly because I know some parts are wrong, but need feedback on how to fix them). The major changes to this patch are in the hardware controller and consist of wiring up the backend calls to generate the graphs on the hardware summary page, namely the calls to the database to generate the availability graphs and the calls to Mark's API to generate the history and snapshot graphs. Various other small interface and styling tweaks are also included. -Mo -------------- next part -------------- A non-text attachment was scrubbed... Name: graphs-backend-expir.patch Type: text/x-patch Size: 26520 bytes Desc: not available URL: <http://listman.redhat.com/archives/ovirt-devel/attachments/20080527/a024e4a5/attachment.bin>
Hugh O. Brock
2008-May-28 19:46 UTC
[Ovirt-devel] Re: [Patch] Experimental Graphs Backend Code
On Tue, May 27, 2008 at 05:23:40PM -0400, Mohammed Morsi wrote:> This patch is for review only, and is not meant to be committed (partly > because I didn't update before generating it and partly because I know some > parts are wrong, but need feedback on how to fix them). The major changes > to this patch are in the hardware controller and consist of wiring up the > backend calls to generate the graphs on the hardware summary page, namely > the calls to the database to generate the availability graphs and the calls > to Mark's API to generate the history and snapshot graphs. Various other > small interface and styling tweaks are also included.Hi Mo, thanks for this. Responses in-line below.> diff --git a/wui/src/app/controllers/application.rb b/wui/src/app/controllers/application.rb > index 5f20be3..0123b3e 100644 > --- a/wui/src/app/controllers/application.rb > +++ b/wui/src/app/controllers/application.rb > @@ -31,11 +31,12 @@ class ApplicationController < ActionController::Base > before_filter :pre_edit, :only => [:edit, :update, :destroy] > before_filter :pre_show, :only => [:show, :show_vms, :show_users, > :show_hosts, :show_storage, > - :available_graph, :history_graph, :network_traffic_graph] > + :available_graph, :history_graph, :snapshot_graph] > before_filter :authorize_admin, :only => [:new, :create, :edit, :update, :destroy] > > def get_login_user > - user_from_principal(request.env["HTTP_X_FORWARDED_USER"]) > + #user_from_principal(request.env["HTTP_X_FORWARDED_USER"]) > + 'admin'Assume this ^^^ is unintentional...> end > > def user_from_principal(principal) > diff --git a/wui/src/app/controllers/hardware_controller.rb b/wui/src/app/controllers/hardware_controller.rb > index 25201d9..1afc3e1 100644 > --- a/wui/src/app/controllers/hardware_controller.rb > +++ b/wui/src/app/controllers/hardware_controller.rb > @@ -16,6 +16,8 @@ > # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > # MA 02110-1301, USA. A copy of the GNU General Public License is > # also available at http://www.gnu.org/copyleft/gpl.html. > +# > +require 'util/stats/Stats' > > class HardwareController < ApplicationController > > @@ -98,72 +100,85 @@ class HardwareController < ApplicationController > > # retrieves data to be used by availablilty bar charts > def available_graph > + data_sets = [] > + color = 'blue' > + > target = params[:target] > - available = nil > - used = nil > - if target == 'memory' > - available = @available_memory > - used = @used_memory > - elsif target == 'storage' > - available = @available_storage > - used = @used_storage > + if target == 'cpu' > + if (@total[:cpu] > @used[:cpu]) > + # 3/4 is the critical boundry for now > + color = 'red' if (@used[:cpu].to_f / @total[:cpu].to_f) > 0.75 > + data_sets.push ({ :name => 'cpu_used', :values => [@used[:cpu]], > + :fill => color, :stroke => 'lightgray', :strokeWidth => 1 }, > + { :name => 'cpu_available', > + :values => [@available[:cpu]], :fill => 'white', > + :stroke => 'lightgray', :strokeWidth => 1}) > + else > + data_sets.push ({ :name => 'cpu_available', :values => [@available[:cpu]], > + :fill => 'white', :stroke => 'lightgray', :strokeWidth => 1 }, > + { :name => 'cpu_used', > + :values => [@used[:cpu]], :fill => 'red', > + :stroke => 'lightgray', :strokeWidth => 1}) > + endIf I'm reading this right, this will flip the bar depending on whether vcpus are overcommitted relative to physical CPUs or not, yes? If so that's good. Also it's important to somewhere make the distinction that we are talking about integer values of CPUs, at least for the moment -- we can't meaningfully assign some percentage of 1 physical CPU (yet).> + elsif target == 'memory' > + if (@total[:memory] > @used[:memory]) > + color = 'red' if (@used[:memory].to_f / @total[:memory].to_f) > 0.75 > + data_sets.push ({ :name => 'memory_used', :values => [@used[:memory]], > + :fill => color, :stroke => 'lightgray', :strokeWidth => 1 }, > + { :name => 'memory_available', > + :values => [@available[:memory]], :fill => 'white', > + :stroke => 'lightgray', :strokeWidth => 1}) > + else > + data_sets.push ({ :name => 'memory_available', :values => [@available[:memory]], > + :fill => 'white', :stroke => 'lightgray', :strokeWidth => 1 }, > + { :name => 'memory_used', > + :values => [@used[:memory]], :fill => 'red', > + :stroke => 'lightgray', :strokeWidth => 1}) > + end > +Right now we *can't* overcommit RAM, so I don't know if we want the same logic for this graph as for the cpu graph. Also, I assume that memory_available is "the sum of all memory on all machines in the pool," where "memory used" is "the sum of all memory currently in use by active VMs?" (Scott, you can probably comment on this too I'm sure)> elsif target == 'vms' > - available = @available_vms > - used = @used_vms > + total_remaining = @total[:vms] - @used[:vms] - @available[:vms] > + data_sets.push({ :name => 'vms_used', :values => [@used[:vms]], > + :fill => 'blue', :stroke => 'lightgray', :strokeWidth => 1 }, > + { :name => 'vms_available', :values => [@available[:vms]], > + :fill => 'red', :stroke => 'lightgray', :strokeWidth => 1 }, > + { :name => 'vms_remaining', :values => [total_remaining], > + :fill => 'white', :stroke => 'lightgray', :strokeWidth => 1})I think we realized the other day that there is only one useful number we can give about VMs in a hardware pool, which is "how many are currently running?" I'm not sure how to best express this. Do you suppose it would be useful to contrast the number of VMs currently running in the pool with the number of physical hosts currently in the pool? Or is that just a waste of time? Scott?> end > > - color = 'blue' > - color = 'red' if (used.to_f / (available + used).to_f) > 0.75 # 3/4 is the critical boundry for now > - > - graph_object = { > - :timepoints => [], > - :dataset => > - [ > - { > - :name => target + "used", > - :values => [used], > - :fill => color, > - :stroke => 'lightgray', > - :strokeWidth => 1 > - }, > - { > - :name => target + "available", > - :values => [available], > - :fill => 'white', > - :stroke => 'lightgray', > - :strokeWidth => 1 > - } > - ] > - } > - render :json => graph_object > + render :json => { :timepoints => [], :dataset => data_sets } > end > > # retrieves data used by history graphs > def history_graph > - today = DateTime.now > + target = params[:target] > + today = Time.now > + requestList = [ StatsRequest.new(@pool.id, target, 0, "used", today.to_i - 3600, 3600, 0), > + StatsRequest.new(@pool.id, target, 0, "peak", today.to_i - 3600, 3600, 0) ] > dates = [ Date::ABBR_MONTHNAMES[today.month] + ' ' + today.day.to_s ] > 1.upto(6){ |x| # TODO get # of days from wui > dte = today - x > dates.push ( Date::ABBR_MONTHNAMES[dte.month] + ' ' + dte.day.to_s ) > + requestList.push ( StatsRequest.new (@pool.id, target, 0, "used", dte.to_i - 3600, 3600, 0), > + StatsRequest.new (@pool.id, target, 0, "peak", dte.to_i - 3600, 3600, 0) ) > } > dates.reverse! # want in ascending order > - > - target = params[:target] > - peakvalues = nil > - avgvalues = nil > - if target == 'host_usage' > - peakvalues = [95.97, 91.80, 88.16, 86.64, 99.14, 75.14, 85.69] # TODO real values! > - avgvalues = [3.39, 2.83, 1.61, 0.00, 4.56, 1.23, 5.32] # TODO real values! > - elsif target == 'storage_usage' > - peakvalues = [11.12, 22.29, 99.12, 13.23, 54.32, 17.91, 50.1] # TODO real values! > - avgvalues = [19.23, 19.23, 19.23, 29.12, 68.96, 43.11, 0.1] # TODO real values! > - elsif target == 'vm_pool_usage_history' > - peakvalues = [42, 42, 42, 42, 42, 42, 42] # TODO real values! > - avgvalues = [0, 0, 0, 0, 0, 0, 0] # TODO real values! > - elsif target == 'overall_load' > - peakvalues = [19.68, 20.08, 19.84, 17.76, 0.0, 14.78, 9.71] # TODO real values! > - avgvalues = [0, 1, 2, 4, 8, 16, 32] # TODO real values! > - end > + requestList.reverse! > + > + statsList = getStatsData?( requestList ) > + statsList.each { |stat| > + devClass = stat.get_devClass? > + counter = stat.get_counter? > + value = stat.get_value?.to_i + 20 > + if devClass == target > + if counter == "used" > + @avg_history[:values].push value > + else > + #elsif counter == "peak" > + @peak_history[:values].push value > + end > + end > + } > > graph_object = { > :timepoints => dates, > @@ -171,14 +186,14 @@ class HardwareController < ApplicationController > [ > { > :name => target + "peak", > - :values => peakvalues, > - :stroke => @peak_color, > + :values => @peak_history[:values], > + :stroke => @peak_history[:color], > :strokeWidth => 1 > }, > { > :name => target + "average", > - :values => avgvalues, > - :stroke => @average_color, > + :values => @avg_history[:values], > + :stroke => @avg_history[:color], > :strokeWidth => 1 > } > ] > @@ -186,21 +201,25 @@ class HardwareController < ApplicationController > render :json => graph_object > end > > - def network_traffic_graph > + def snapshot_graph > target = params[:target] > - network_load = nil > - if target == 'in' > - network_load = @network_traffic['in'] > + snapshot = nil > + if target == 'overall_load' > + snapshot = @snapshots[:overall_load] > + elsif target == 'cpu' > + snapshot = @snapshots[:cpu] > + elsif target == 'in' > + snapshot = @snapshots[:in] > elsif target == 'out' > - network_load = @network_traffic['out'] > + snapshot = @snapshots[:out] > elsif target == 'io' > - network_load = @network_traffic['io'] > + snapshot = @snapshots[:io] > endThis looks exactly like what we talked about -- understand you still need feedback from Mark regarding the right way to pull this info out.> - network_load_remaining = 1024 - network_load > + snapshot_remaining = 1024 - snapshot > > color = 'blue' > - color = 'red' if (network_load.to_f / 1024.to_f) > 0.75 # 3/4 is the critical boundry for now > + color = 'red' if (snapshot.to_f / 1024.to_f) > 0.75 # 3/4 is the critical boundry for now > > graph_object = { > :timepoints => [], > @@ -208,14 +227,14 @@ class HardwareController < ApplicationController > [ > { > :name => target, > - :values => [network_load], > + :values => [snapshot], > :fill => color, > :stroke => 'lightgray', > :strokeWidth => 1 > }, > { > :name => target + "remaining", > - :values => [network_load_remaining], > + :values => [snapshot_remaining], > :fill => 'white', > :stroke => 'lightgray', > :strokeWidth => 1 > @@ -395,23 +414,56 @@ class HardwareController < ApplicationController > @perm_obj = @pool > @current_pool_id=@pool.id > > - # TODO pull real values in > - @available_memory = 18 > - @used_memory = 62 > - > - @available_storage = 183 > - @used_storage = 61 > - > - @available_vms = 1 > - @used_vms = 26 > - > - @peak_color = 'red' > - @average_color = 'blue' > + # availability graphs - used > + @used = {:cpu => 0, :memory => 0, :vms => 0} > + @pool.sub_vm_resource_pools.each { |svrp| @used[:cpu] += svrp.allocated_resources[:current][:cpus] } > + @pool.sub_vm_resource_pools.each { |svrp| @used[:memory] += svrp.allocated_resources[:current][:memory] } > + @pool.sub_vm_resource_pools.each { |svrp| @used[:vms] += svrp.allocated_resources[:current][:vms] } > + > + # availability graphs - total > + @total = {:cpu => 0, :memory => 0, :vms => 0} > + @total[:cpu] = @pool.total_resources[:cpus] > + @total[:memory] = @pool.total_resources[:memory] > + @total[:vms] = @pool.total_resources[:vms] > + @total.each_key { |k| @total[k] = 0 if @total[k] == nil } > + > + # availability graphs - available > + @available = {} > + @available[:cpu] = (@total[:cpu] - @used[:cpu]).abs > + @available[:memory] = (@total[:memory] - @used[:memory]).abs > + @available[:vms] = 5 # TODO ? > + > + # history graphs > + @peak_history = { :color => 'red', :values => [] } > + @avg_history = { :color => 'blue', :values => [] } > + > + # snapshot graphs > + ret_time = Time.now.to_i - 3600 > + @snapshots = { :overall_load => 0, :cpu => 0, :in => 0, :out => 0, :io => 0 } > + requestList = [] > + requestList << StatsRequest.new(@pool.id, "system", 0, "used", ret_time, 3600, 0) > + requestList << StatsRequest.new(@pool.id, "cpu", 0, "used", ret_time, 3600, 0) > + requestList << StatsRequest.new(@pool.id, "in", 0, "used", ret_time, 3600, 0) > + requestList << StatsRequest.new(@pool.id, "out", 0, "used", ret_time, 3600, 0) > + requestList << StatsRequest.new(@pool.id, "io", 0, "used", ret_time, 3600, 0) > + statsList = getStatsData?( requestList ) > + statsList.each { |stat| > + devClass = stat.get_devClass? > + value = stat.get_value? > + if devClass == "system" > + @snapshots[:overall_load] = value > + elsif devClass == "cpu" > + @snapshots[:cpu] = value > + elsif devClass == "in" > + @snapshots[:in] = value > + elsif devClass == "out" > + @snapshots[:out] = value > + elsif devClass == "io" > + @snapshots[:io] = value > + end > + } > + #@snapshots = { :overall_load => 500, :cpu => 10, :in => 100, :out => 1024, :io => 200 } >This also looks correct.> - # TODO pull real values in > - @network_traffic = { 'in' => 100, 'out' => 1024, 'io' => 200 } > - @network_errors = { 'in' => 0, 'out' => 4, 'io' => 2 } > - @network_trends = { 'in' => 'up', 'out' => 'down', 'io' => 'check' } > end > def pre_json > pre_show > diff --git a/wui/src/app/views/hardware/show.html.erb b/wui/src/app/views/hardware/show.html.erb > index e524f97..f164ec5 100644 > --- a/wui/src/app/views/hardware/show.html.erb > +++ b/wui/src/app/views/hardware/show.html.erb > @@ -12,31 +12,32 @@ > <div id="availability_graphs"> > <div class="availability_graph"> > <div class="availability_graph_left"> > - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'available_memory', :chartType => 'stackedColumn', :url => (url_for :controller => 'hardware', :action => 'available_graph', :target => 'memory' ) } %> > + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'available_cpu', :chartType => 'stackedColumn', :url => (url_for :controller => 'hardware', :action => 'available_graph', :target => 'cpu' ) } %> > </div> > <div class="availability_graph_right"> > - Available: <%= @available_memory %> <br/> Used: <%= @used_memory %> <br/><b><%= @available_memory + @used_memory %> GB of Memory</b><br/> > + Available: <%= @available[:cpu] %> <br/> Used: <%= @used[:cpu] %> <br/><b><%= @total[:cpu] %> CPUs</b><br/> > </div> > </div> > > <div class="availability_graph"> > <div class="availability_graph_left"> > - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'available_storage', :chartType => 'stackedColumn', :url => (url_for :controller => 'hardware', :action => 'available_graph', :target => 'storage') } %> > + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'available_memory', :chartType => 'stackedColumn', :url => (url_for :controller => 'hardware', :action => 'available_graph', :target => 'memory') } %> > </div> > <div class="availability_graph_right"> > - Available: <%= @available_storage %> <br/> Used: <%= @used_storage %> <br/><b><%= @available_storage + @used_storage %> GB of Storage</b><br/> > + Available: <%= @available[:memory] %> <br/> Used: <%= @used[:memory] %> <br/><b><%= @total[:memory] %> GB of Memory</b><br/> > </div> > </div> > > <div class="availability_graph"> > <div class="availability_graph_left"> > - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'available_vms', :chartType => 'stackedColumn', :url => (url_for :controller => 'hardware', :action => 'available_graph', :target => 'vms' ) } %> > + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'available_vms', :chartType => 'stackedColumn', :url => (url_for :controller => 'hardware', :action => 'available_graph', :target => 'vms' ) } %> > </div> > <div class="availability_graph_right"> > - Available: <%= @available_vms %> <br/> Used: <%= @used_vms %> <br/><b><%= @available_vms + @used_vms %> Virtual Machines</b><br/> > + Assigned: <%= @available[:vms] %> <br/> Active: <%= @used[:vms] %> <br/><b><%= @total[:vms] %> Virtual Machines</b><br/> > </div> > </div> > </div> > + > <div id="history_graphs"> > <div id="history_graphs_control"> > <div class="history_graphs_menu"> > @@ -49,10 +50,9 @@ > </script> > <ul> > <li><div id="history_graph_menu_header">Overall Load <%= image_tag 'icon_menu_arrow.gif' %></div></li> > - <li class="history_graph_menu_item history_graph_menu_fitem"><a href="#" onclick="swap_history_graph('host_usage_history', 'Host Usage');">Host Usage</a></li> > - <li class="history_graph_menu_item"><a href="#" onclick="swap_history_graph('storage_usage_history', 'Storage Usage');" >Storage Usage</a></li> > - <li class="history_graph_menu_item"><a href="#" onclick="swap_history_graph('vm_pool_usage_history', 'VM Pool Usage');" >VM Pool Usage</a></li> > - <li class="history_graph_menu_item history_graph_menu_litem"><a href="#" onclick="swap_history_graph('overall_load_history', 'Overall Load')" >Overall Load</a></li> > + <li class="history_graph_menu_item history_graph_menu_fitem"><a href="#" onclick="swap_history_graph('overall_load_history', 'Overall Load')" >Overall Load</a></li> > + <li class="history_graph_menu_item"><a href="#" onclick="swap_history_graph('cpu_history', 'CPU History');" >CPU History</a></li> > + <li class="history_graph_menu_item history_graph_menu_litem"><a href="#" onclick="swap_history_graph('io_history', 'I/O Usage');">I/O Usage</a></li> > </ul> > </div> > <div class="history_graphs_menu"> > @@ -61,51 +61,56 @@ > </ul> > </div> > <div class="history_graphs_legend"> > - <font color="<%= @peak_color %>">Peak </font> > - <font color="<%= @average_color %>">Average </font> > + <font color="<%= @peak_history[:color] %>">Peak </font> > + <font color="<%= @avg_history[:color] %>">Average </font> > </div> > </div> > <div id="history_graphs_graphs"> > - <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'host_usage_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'hardware', :action => 'history_graph', :target => 'host_usage' ) } %></div> > - <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'storage_usage_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'hardware', :action => 'history_graph', :target => 'storage_usage' ) } %></div> > - <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'vm_pool_usage_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'hardware', :action => 'history_graph', :target => 'vm_pool_usage_history' ) } %></div> > - <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'overall_load_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'hardware', :action => 'history_graph', :target => 'overall_load' ) } %></div> > + <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'cpu_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'hardware', :action => 'history_graph', :target => 'cpu' ) } %></div> > + <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'io_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'hardware', :action => 'history_graph', :target => 'io' ) } %></div> > + <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'overall_load_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'hardware', :action => 'history_graph', :target => 'system' ) } %></div> > </div> > </div> > -<div id="network_traffic_graphs"> > +<div id="snapshot_graphs"> > <table> > <tr> > - <th width="15%">Network Traffic</th> > - <th width="50%">Load</th> > - <th width="15%">Errors</th> > - <th width="15%">Trend</th> > + <th width="25%">Metric</th> > + <th width="70%">Load</th> > </tr> > > <tr> > + <td>Overall Load </td> > + <td> > + <div class="snapshot_graph_text"><%= @snapshots[:overall_load] %> </div> > + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'overall_load_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'hardware', :action => 'snapshot_graph', :target => 'overall_load' ) } %> > + </td> > + </tr> > + <tr> > + <td>CPU </td> > + <td> > + <div class="snapshot_graph_text"><%= @snapshots[:cpu] %> </div> > + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'cpu_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'hardware', :action => 'snapshot_graph', :target => 'cpu' ) } %> > + </td> > + </tr> > + <tr> > <td>Network In </td> > <td> > - <div class="network_traffic_load_text"><%= @network_traffic['in'] %> mb/s </div> > - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'network_traffic_in', :chartType => 'stackedRow', :url => (url_for :controller => 'hardware', :action => 'network_traffic_graph', :target => 'in' ) } %> > + <div class="snapshot_graph_text"><%= @snapshots[:in] %> mb/s </div> > + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'net_in_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'hardware', :action => 'snapshot_graph', :target => 'in' ) } %> > </td> > - <td><%= @network_errors['in'] == 0 ? 'none' : (image_tag 'network_error.png') + ' ' + @network_errors['in'].to_s %></td> > - <td><%= @network_trends['in'] == 'up' ? (image_tag 'network_trend_up.png') : (@network_trends['in'] == 'down' ? (image_tag 'network_trend_down.png') : (image_tag 'network_trend_check.png')) %></td> > </tr> > <tr> > <td>Network Out</td> > <td> > - <div class="network_traffic_load_text"><%= @network_traffic['out'] %> mb/s</div> > - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'network_traffic_out', :chartType => 'stackedRow', :url => (url_for :controller => 'hardware', :action => 'network_traffic_graph', :target => 'out' ) } %> > + <div class="snapshot_graph_text"><%= @snapshots[:out] %> mb/s</div> > + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'net_out_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'hardware', :action => 'snapshot_graph', :target => 'out' ) } %> > </td> > - <td><%= @network_errors['out'] == 0 ? 'none' : (image_tag 'network_error.png') + ' ' + @network_errors['out'].to_s %></td> > - <td><%= @network_trends['out'] == 'up' ? (image_tag 'network_trend_up.png') : (@network_trends['out'] == 'down' ? (image_tag 'network_trend_down.png') : (image_tag 'network_trend_check.png')) %></td> > </tr> > <tr> > <td>I/O </td> > <td> > - <div class="network_traffic_load_text"><%= @network_traffic['io'] %> mb/s</div> > - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'network_traffic_io', :chartType => 'stackedRow', :url => (url_for :controller => 'hardware', :action => 'network_traffic_graph', :target => 'io' ) } %> </td> > - <td><%= @network_errors['io'] == 0 ? 'none' : (image_tag 'network_error.png') + ' ' + @network_errors['io'].to_s %></td> > - <td><%= @network_trends['io'] == 'up' ? (image_tag 'network_trend_up.png') : (@network_trends['io'] == 'down' ? (image_tag 'network_trend_down.png') : (image_tag 'network_trend_check.png')) %></td> > + <div class="snapshot_graph_text"><%= @snapshots[:io] %> mb/s</div> > + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'io_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'hardware', :action => 'snapshot_graph', :target => 'io' ) } %> </td> > </tr> > > </table> > diff --git a/wui/src/public/stylesheets/components.css b/wui/src/public/stylesheets/components.css > index 0e9301b..9f6bb1d 100644 > --- a/wui/src/public/stylesheets/components.css > +++ b/wui/src/public/stylesheets/components.css > @@ -132,7 +132,7 @@ > .availability_graph { float: left; width: 33%;} > .availability_graph_left { float: left; width: 50px;} > .availability_graph_right { float: left; margin-top: 10%; margin-left: 125px; min-width: 100px;} > -#available_memory, #available_storage, #available_vms {margin-left:50px;width:100px;height:100px} > +#available_cpu, #available_memory, #available_vms {margin-left:50px;width:100px;height:100px} > > /* history graphs on hardware / resource summary tab */ > #history_graphs { height: 270px; overflow: hidden; margin-left: 40px; margin-top: 40px; } > @@ -184,20 +184,21 @@ > position: relative; > float: left; > } > -#host_usage_history, #storage_usage_history, #vm_pool_usage_history, #overall_load_history{ > +#cpu_history, #io_history, #overall_load_history{ > height: 200px; width: 1200px; position: absolute; left: -70px; > } > > > -/* network traffic graphs on hardware / resource summary tab */ > -#network_traffic_graphs { height: 150px; padding-left: 60px; } > -#network_traffic_graphs table { width: 90%; border-spacing: 0;} > -#network_traffic_graphs th { background: #CCCCCC; text-align: left; padding-left: 10px; border: 1px solid #DDDDDD;} > -#network_traffic_graphs td { padding-left: 10px; border: 1px solid #DDDDDD;} > -#network_traffic_in, #network_traffic_out, #network_traffic_io { > - width: 350px; height: 20px; float: right; > +/* snapshot graphs on hardware / resource summary tab */ > +#snapshot_graphs { height: 150px; padding-left: 60px; } > +#snapshot_graphs table { width: 90%; border-spacing: 0;} > +#snapshot_graphs th { background: #CCCCCC; text-align: left; padding-left: 10px; border: 1px solid #DDDDDD;} > +#snapshot_graphs td { padding-left: 10px; border: 1px solid #DDDDDD;} > +#overall_load_snapshot, #cpu_snapshot, #net_in_snapshot, #net_out_snapshot, #io_snapshot { > + width: 350px; height: 20px; float: left; > } > -.network_traffic_load_text { > +.snapshot_graph_text { > float: left; > padding-top: 3px; > + width: 100px; > }I'm anxious to see it in action, but subject to the comments above this looks like what we need. Take care, --Hugh