Mohammed Morsi
2008-Jun-04 23:23 UTC
[Ovirt-devel] [PATCH] integrated backend monitoring api to drive graphs on hardware pool views
Signed-off-by: Mohammed Morsi <mmorsi at redhat.com> --- wui/src/app/controllers/graph_controller.rb | 270 +- wui/src/app/util/stats/DummyData.rb |12641 ------------------------- wui/src/app/util/stats/Stats.rb | 68 +- wui/src/app/util/stats/StatsRequest.rb | 2 + wui/src/app/util/stats/StatsTypes.rb | 333 + wui/src/app/util/stats/statsTest.rb | 49 +- wui/src/app/views/graph/history_graphs.rhtml | 4 +- wui/src/app/views/graph/snapshot_graph.rhtml | 36 +- wui/src/app/views/host/_grid.rhtml | 5 +- wui/src/app/views/storage/_grid.rhtml | 6 +- wui/src/app/views/storage/addstorage.html.erb | 2 +- wui/src/app/views/vm/_grid.rhtml | 2 +- wui/src/public/stylesheets/components.css | 4 +- 13 files changed, 564 insertions(+), 12858 deletions(-) delete mode 100644 wui/src/app/util/stats/DummyData.rb create mode 100644 wui/src/app/util/stats/StatsTypes.rb diff --git a/wui/src/app/controllers/graph_controller.rb b/wui/src/app/controllers/graph_controller.rb index 80ece7e..0a7c4da 100644 --- a/wui/src/app/controllers/graph_controller.rb +++ b/wui/src/app/controllers/graph_controller.rb @@ -1,4 +1,4 @@ -# require 'util/stats/Stats' +require 'util/stats/Stats' class GraphController < ApplicationController layout nil @@ -94,44 +94,67 @@ class GraphController < ApplicationController # generate layout for history graphs def history_graphs @id = params[:id] - @peak_history = { :color => 'red', :values => [ 100, 99, 98, 93, 95, 12, 92] } - @avg_history = { :color => 'blue', :values => [12, 23, 42, 33, 12, 23, 65] } + @peak_history = { :color => 'red', :values => [0,0,0,0,0,0,0], :dataPoints => [0,0,0,0,0,0,0] } + @avg_history = { :color => 'blue', :values => [0,0,0,0,0,0,0], :dataPoints => [0,0,0,0,0,0,0] } end # retrieves data for history graphs def history_graph_data history_graphs target = params[:target] + devclass = DEV_KEY_CLASSES[target] + avgcounter = DEV_KEY_AVGCOUNTERS[target] + peakcounter = nil @pool = Pool.find(@id) today = Time.now - #requestList = [ ] + firstday = today - 6 dates = [ Date::ABBR_MONTHNAMES[today.month] + ' ' + today.day.to_s ] 0.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.to_s, target, 0, "used", dte.to_i - 3600, 3600, 0), - # StatsRequest.new (@pool.id.to_s, target, 0, "peak", dte.to_i - 3600, 3600, 0) ) + } + + requestList = [ ] + @pool.hosts.each { |host| + if target == "cpu" + 0.upto(host.num_cpus - 1){ |x| + requestList.push ( StatsRequest.new (host.hostname, devclass, x, avgcounter, 0, 0, RRDResolution::Long) ) #, # one weeks worth of data + # StatsRequest.new (@pool.id.to_s, devclass, x, peakcounter, firstday.to_i - 3600, 604800, 3600)) + } + else + requestList.push ( StatsRequest.new (host.hostname, devclass, 0, avgcounter, 0, 0, RRDResolution::Long) ) #, + # StatsRequest.new (@pool.id.to_s, devclass, 0, peakcounter, firstday.to_i - 3600, 604800, 3600)) + end } dates.reverse! # want in ascending order - #requestList.reverse! - #statsList = getStatsData?( requestList ) - #statsList.each { |stat| - # devClass = stat.get_devClass? - # counter = stat.get_counter? - # stat.get_data?.each{ |data| - # value = data.get_value?.to_i - # if devClass == target - # if counter == "used" - # @avg_history[:values].push value - # else - # #elsif counter == "peak" - # @peak_history[:values].push value - # end - # end - # } - #} + statsList = getStatsData?( requestList ) + statsList.each { |stat| + counter = stat.get_counter? + stat.get_data?.each{ |data| + timestamp = data.get_timestamp? + valueindex = ((timestamp.to_i - firstday.to_i) / 86400).to_i # 86400 secs per day + value = data.get_value? + if !value.nan? + if counter == avgcounter + @avg_history[:values][valueindex] += value.to_i + @avg_history[:dataPoints][valueindex] += 1 + elsif counter == peakcounter + @peak_history[:values][valueindex] += value.to_i + @peak_history[:dataPoints][valueindex] += 1 + end + end + } + } + + # avgerage out history for each day + 0.upto(@avg_history[:values].size - 1){ |x| + (@avg_history[:values][x] /= @avg_history[:dataPoints][x]) if (@avg_history[:dataPoints][x] != 0) + } + 0.upto(@peak_history[:values].size - 1){ |x| + (@peak_history[:values][x] /= @peak_history[:dataPoints][x]) if (@peak_history[:dataPoints][x] != 0) + } graph_object = { :timepoints => dates, @@ -192,58 +215,65 @@ class GraphController < ApplicationController # generate layout for snapshot graphs def snapshot_graph @id = params[:id] - @target = params[:target] + @host = params[:host] - #ret_time = Time.now.to_i - #@snapshots = { :avg => { :overall_load => 0, :cpu => 0, :in => 0, :out => 0, :io => 0 }, - # :peak => { :overall_load => 0, :cpu => 0, :in => 0, :out => 0, :io => 0 }} - #requestList = [] - #requestList << StatsRequest.new(@id.to_s, "system", 0, "used", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "system", 0, "peak", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "cpu", 0, "used", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "cpu", 0, "peak", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "in", 0, "used", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "in", 0, "peak", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "out", 0, "used", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "out", 0, "peak", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "io", 0, "used", ret_time, 3600, 0) - #requestList << StatsRequest.new(@id.to_s, "io", 0, "peak", ret_time, 3600, 0) - #statsList = getStatsData?( requestList ) - #statsList.each { |stat| - # devClass = stat.get_devClass? - # counter = stat.get_counter? - # stat.get_data?.each{ |data| - # value = data.get_value?.to_i - # if counter == "used" - # if devClass == "system" - # @snapshots[:avg][:overall_load] = value - # elsif devClass == "cpu" - # @snapshots[:avg][:cpu] = value - # elsif devClass == "in" - # @snapshots[:avg][:in] = value - # elsif devClass == "out" - # @snapshots[:avg][:out] = value - # elsif devClass == "io" - # @snapshots[:avg][:io] = value - # end - # else - # #elsif counter == "peak" - # if devClass == "system" - # @snapshots[:peak][:overall_load] = value.to_i - # elsif devClass == "cpu" - # @snapshots[:peak][:cpu] = value.to_i - # elsif devClass == "in" - # @snapshots[:peak][:in] = value.to_i - # elsif devClass == "out" - # @snapshots[:peak][:out] = value.to_i - # elsif devClass == "io" - # @snapshots[:peak][:io] = value.to_i - # end - # end - # } - #} - @snapshots = { :avg => { :overall_load => 500, :cpu => 10, :in => 100, :out => 1024, :io => 200 }, - :peak => { :overall_load => 100, :cpu => 50, :in => 12, :out => 72, :io => 100 } } + pool = Pool.find(@id) + + @snapshots = { :avg => { 'load' => 0, 'cpu' => 0, 'netin' => 0, 'netout' => 0, 'memory' => 0 }, + :peak => { 'load' => 0, 'cpu' => 0, 'netin' => 0, 'netout' => 0, 'memory' => 0 }} + + requestList = [] + if(@host == nil) + pool.hosts.each{ |host| + requestList += _create_host_snapshot_requests(host.hostname) + } + else + requestList += _create_host_snapshot_requests(@host.hostname) + end + + statsList = getStatsData?( requestList ) + statsList.each { |stat| + devClass = stat.get_devClass? + counter = stat.get_counter? + stat.get_data?.each{ |data| + value = data.get_value? + if !value.nan? + if devClass == DEV_KEY_CLASSES["load"] + if counter == DEV_KEY_AVGCOUNTERS["load"] + @snapshots[:avg]["load"] = value.to_i + elsif counter == DEV_KEY_PEAKCOUNTERS["load"] + @snapshots[:peak]["load"] = value.to_i + end + elsif devClass == DEV_KEY_CLASSES["cpu"] + if counter == DEV_KEY_AVGCOUNTERS["cpu"] + @snapshots[:avg]["cpu"] = value.to_i + elsif counter == DEV_KEY_PEAKCOUNTERS["cpu"] + @snapshots[:peak]["cpu"] = value.to_i + end + elsif devClass == DEV_KEY_CLASSES["netin"] + if counter == DEV_KEY_AVGCOUNTERS["netin"] + @snapshots[:avg]["netin"] = value.to_i + elsif counter == DEV_KEY_PEAKCOUNTERS["netin"] + @snapshots[:peak]["netin"] = value.to_i + end + elsif devClass == DEV_KEY_CLASSES["netout"] + if counter == DEV_KEY_AVGCOUNTERS["netout"] + @snapshots[:avg]["netout"] = value.to_i + elsif counter == DEV_KEY_PEAKCOUNTERS["netout"] + @snapshots[:peak]["netout"] = value.to_i + end + #elsif devClass == DEV_KEY_AVGCOUNTERS["io"] + # if counter == DEV_KEY_AVGCOUNTERS["io"] + # @snapshots[:peak]["io"] = value.to_i + # elsif counter == _dev_key_peak_counters["io"] + # @snapshots[:peak]["io"] = value.to_i + # end + end + end + } + } + #@snapshots = { :avg => { :overall_load => 500, :cpu => 10, :in => 100, :out => 1024, :io => 200 }, + # :peak => { :overall_load => 100, :cpu => 50, :in => 12, :out => 72, :io => 100 } } end @@ -252,18 +282,7 @@ class GraphController < ApplicationController snapshot_graph target = params[:target] - snapshot = nil - if target == 'overall_load' - snapshot = @snapshots[:avg][:overall_load] - elsif target == 'cpu' - snapshot = @snapshots[:avg][:cpu] - elsif target == 'in' - snapshot = @snapshots[:avg][:in] - elsif target == 'out' - snapshot = @snapshots[:avg][:out] - elsif target == 'io' - snapshot = @snapshots[:avg][:io] - end + snapshot = @snapshots[:avg][target] snapshot_remaining = 1024 - snapshot @@ -293,57 +312,32 @@ class GraphController < ApplicationController render :json => graph_object end - #This is static test data to show how we would format whatever we get back from the - #data api. We can pass that api: - #* node id - #* type of data we want back (things like summary, memory, storage, etc.) - #* timeframe we are interested in. This one goes into 'timepoints' - # and probably would call some rails helpers to format the date info however we want + private + + DEV_KEY_CLASSES = { 'cpu' => DevClass::CPU, 'memory' => DevClass::Memory, 'disk' => DevClass::Disk, 'load' => DevClass::Load, 'netin' => DevClass::NIC, 'netout' => DevClass::NIC } + DEV_CLASS_KEYS = DEV_KEY_CLASSES.invert + + # TODO this needs fixing / completing (cpu: more than user time? disk: ?, load: correct?, nics: correct?) + DEV_KEY_AVGCOUNTERS = { 'cpu' => CpuCounter::User, 'memory' => MemCounter::Used, 'disk' => DiskCounter::Ops_read, 'load' => LoadCounter::Load_1min, 'netin' => NicCounter::Packets_Rx, 'netout' => NicCounter::Packets_Tx } + DEV_AVGCOUNTER_KEYS = DEV_KEY_AVGCOUNTERS.invert + + # TODO + DEV_KEY_PEAKCOUNTERS = { 'cpu' => nil, 'memory' => nil, 'disk' => nil, 'load' => nil, 'netin' => nil, 'netout' => nil } + DEV_PEAKCOUNTER_KEYS = DEV_KEY_PEAKCOUNTERS.invert + + def _create_host_snapshot_requests(hostname) + requestList = [] + requestList << StatsRequest.new(hostname, DEV_KEY_CLASSES['load'], 0, DEV_KEY_AVGCOUNTERS['load'], 0, 0, RRDResolution::Default) # RRDResolution::Long ? + #requestList << StatsRequest.new(hostname, "system", 0, "peak", ret_time, 3600, 0) + requestList << StatsRequest.new(hostname, DEV_KEY_CLASSES['cpu'], 0, DEV_KEY_AVGCOUNTERS['cpu'], 0, 0, RRDResolution::Default) # TODO instance + #requestList << StatsRequest.new(hostname, "cpu", 0, "peak", ret_time, 3600, 0) + #requestList << StatsRequest.new(hostname, DEV_KEY_CLASSES['netin'],0, DEV_KEY_AVGCOUNTERS['netin'], 0, 0, RRDResolution::Default) + #requestList << StatsRequest.new(hostname, "in", 0, "peak", ret_time, 3600, 0) + #requestList << StatsRequest.new(hostname, DEV_KEY_CLASSES['netout'],0, DEV_KEY_AVGCOUNTERS['netout'], 0, 0, RRDResolution::Default) + #requestList << StatsRequest.new(hostname, "out", 0, "peak", ret_time, 3600, 0) + #requestList << StatsRequest.new(hostname, DEV_KEY_CLASSES["io"],0, DEV_KEY_AVGCOUNTERS["io"], 0, 0, RRDResolution::Default) + #requestList << StatsRequest.new(hostname, "io", 0, "peak", ret_time, 3600, 0) + return requestList + end - def graph - if params[:type] =="Memory" - graph_object = { - :timepoints => [], - :dataset => [{ - :name =>'IE', - :values => [86.64], - :fill => 'lightblue', - :stroke => 'blue', - :strokeWidth => 3 - } - ] - } - elsif params[:type] == "detail" - graph_object = { - :timepoints => ["April 1", "April 2","April 3","April 4","April 5","April 6","April 7"], - :dataset => [{ - :name =>'Peak', - :values => [75.97, 71.80, 68.16, 56.64,95.97, 81.80, 28.16], - :fill => 'lightblue', - :stroke => 'blue', - :strokeWidth => 3 - }] - } - else - graph_object = { - :timepoints => ["April 1", "April 2","April 3","April 4"], - :dataset => [{ - :name =>'Peak', - :values => [95.97, 91.80, 88.16, 86.64], - :fill => 'lightblue', - :stroke => 'blue', - :strokeWidth => 3 - }, - { - :name =>'Average', - :values => [3.39, 2.83, 1.61, 0.00], - :fill => 'pink', - :stroke => 'red', - :strokeWidth => 3 - } - ] - } - end - render :json => graph_object - end end diff --git a/wui/src/app/util/stats/Stats.rb b/wui/src/app/util/stats/Stats.rb index 0e9060b..73a6920 100644 --- a/wui/src/app/util/stats/Stats.rb +++ b/wui/src/app/util/stats/Stats.rb @@ -21,40 +21,61 @@ $: << '/usr/lib64/ruby/site_ruby/1.8/x86_64-linux' require 'RRD' +require 'util/stats/StatsTypes' require 'util/stats/StatsData' require 'util/stats/StatsDataList' require 'util/stats/StatsRequest' -require 'util/stats/DummyData' def fetchData?(node, devClass, instance, counter, startTime, duration, interval) if (interval == 0) - interval = 10 + interval = RRDResolution::Default end if (startTime == 0) - start = Time.now.to_i - duration + if (duration > 0 ) + sTime = Time.now.to_i - duration + else + sTime = Time.now.to_i - 86400 + end + eTime = Time.now.to_i else - start = startTime + sTime = startTime + eTime = sTime + duration end - endTime = start + duration + # Now mangle based on the intervals + start = (sTime / interval).to_i * interval + endTime = (eTime / interval).to_i * interval rrdBase="/var/lib/collectd/rrd/" - rrdNode=rrdBase + "/" + node + "/" + rrdNode=rrdBase + node + "/" # Now we need to mess a bit to get the right combos + case devClass + when DevClass::CPU + rrdTail = CpuCounter.getRRDPath(instance, counter) + lIndex = CpuCounter.getRRDIndex(counter) + when DevClass::Memory + rrdTail = MemCounter.getRRDPath(instance, counter) + lIndex = MemCounter.getRRDIndex(counter) + when DevClass::Load + rrdTail = LoadCounter.getRRDPath(instance, counter) + lIndex = LoadCounter.getRRDIndex(counter) + when DevClass::NIC + rrdTail = NicCounter.getRRDPath(instance, counter) + lIndex = NicCounter.getRRDIndex(counter) + when DevClass::Disk + rrdTail = DiskCounter.getRRDPath(instance, counter) + lIndex = DiskCounter.getRRDIndex(counter) + else + puts "Nothing for devClass" + end - if ( devClass <=> "cpu" ) == 0 - rrdDev = rrdNode + "cpu-" + instance.to_s - else - rrdDev = rrdNode + devClass - end - - rrd = rrdDev + "/" + devClass + "-" + counter + ".rrd" + rrd = rrdNode + rrdTail + ".rrd" returnList = StatsDataList.new(node,devClass,instance, counter) - (fstart, fend, names, data, interval) = RRD.fetch(rrd, "--start", start, "--end", endTime, "AVERAGE", "-r", interval) + (fstart, fend, names, data, interval) = RRD.fetch(rrd, "--start", start.to_s, "--end", endTime.to_s, "AVERAGE", "-r", interval.to_s) i = 0 # For some reason, we get an extra datapoint at the end. Just chop it off now... data.delete_at(-1) @@ -62,33 +83,24 @@ def fetchData?(node, devClass, instance, counter, startTime, duration, interval) # Now, lets walk the returned data and create the ojects, and put them in a list. data.each do |vdata| i += 1 - returnList.append_data( StatsData.new(fstart + interval * i, vdata[0] )) + returnList.append_data( StatsData.new(fstart + interval * i, vdata[lIndex] )) end return returnList end -# This is the Ruby entry point into the world of statistics retrieval -# for ovirt. - - -# This call takes a list of StatRequest objects. -# It returns a list of StatsData objects that contain the data -# that satisifies the request. -# -# ToDo: -# 1) There is currently no error reporting mechanisms implemented -# def getStatsData?(statRequestList) tmpList = [] + myList = [] - statRequestList.each do |request| node = request.get_node? counter = request.get_counter? - tmpList =fetchData?(request.get_node?, request.get_devClass?,request.get_instance?, request.get_counter?,request.get_starttime?, request.get_duration?,request.get_precision?) + tmpList =fetchData?(request.get_node?, request.get_devClass?,request.get_instance?, request.get_counter?,request.get_starttime?, request.get_duration?,request.get_precision?) + + # Now copy the array returned into the main array myList << tmpList end diff --git a/wui/src/app/util/stats/StatsRequest.rb b/wui/src/app/util/stats/StatsRequest.rb index 4a0ab28..24088c7 100644 --- a/wui/src/app/util/stats/StatsRequest.rb +++ b/wui/src/app/util/stats/StatsRequest.rb @@ -21,6 +21,8 @@ # This is the base level request mechanism for the ovirt statistical # interface +require 'util/stats/StatsTypes' + #define class StatsRequest class StatsRequest def initialize(node, devClass, instance, counter, starttime, duration, precision) diff --git a/wui/src/app/util/stats/StatsTypes.rb b/wui/src/app/util/stats/StatsTypes.rb new file mode 100644 index 0000000..6049a2e --- /dev/null +++ b/wui/src/app/util/stats/StatsTypes.rb @@ -0,0 +1,333 @@ +#!/usr/bin/ruby +# +# Copyright (C) 2008 Red Hat, Inc. +# Written by Mark Wagner <mwagner at redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# 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. + +$: << '/usr/lib64/ruby/site_ruby/1.8/x86_64-linux' + + +class DevClass + def DevClass.add_item(key,value) + @hash ||= {} + @hash[key]=value + end + + def DevClass.const_missing(key) + @hash[key] + end + + def DevClass.each + @hash.each {|key,value| yield(key,value)} + end + + def DevClass.getRRDDevName?(key) + return @hash.values_at(key) + end + + + DevClass.add_item :CPU, 1 + DevClass.add_item :Memory, 2 + DevClass.add_item :Disk, 3 + DevClass.add_item :Load, 4 + DevClass.add_item :NIC, 5 +end + + +class DiskCounter + def DiskCounter.add_item(key,value) + @hash ||= {} + @hash[key]=value + end + + def DiskCounter.const_missing(key) + @hash[key] + end + + def DiskCounter.each + @hash.each {|key,value| yield(key,value)} + end + + def DiskCounter.getRRDPath(instance, counter) + extension = ".rrd" + path = "disk-dm-" + instance.to_s + "/" + case counter + when DiskCounter::Merged_read, DiskCounter::Merged_write + path += "disk_merged" + when DiskCounter::Octets_read, DiskCounter::Octets_write + path += "disk_octets" + when DiskCounter::Ops_read, DiskCounter::Ops_write + path += "disk_ops" + when DiskCounter::Time_read, DiskCounter::Time_write + path += "disk_time" + else + puts "Nothing" + end + + return path + end + def DiskCounter.getRRDIndex(counter) + case counter + when DiskCounter::Merged_read, DiskCounter::Octets_read, DiskCounter::Ops_read, DiskCounter::Time_read + localIndex = 0 + when DiskCounter::Merged_read, DiskCounter::Octets_write, DiskCounter::Ops_write, DiskCounter::Time_write + localIndex = 1 + else + localIndex = 0 + end + + return localIndex + end + + DiskCounter.add_item :Merged_read, 1 + DiskCounter.add_item :Merged_write, 2 + DiskCounter.add_item :Octets_read, 3 + DiskCounter.add_item :Octets_write, 4 + DiskCounter.add_item :Ops_read, 5 + DiskCounter.add_item :Ops_write, 6 + DiskCounter.add_item :Time_read, 7 + DiskCounter.add_item :Time_write, 8 +end + +class CpuCounter + def CpuCounter.add_item(key,value) + @hash ||= {} + @hash[key]=value + end + + def CpuCounter.const_missing(key) + @hash[key] + end + + def CpuCounter.each + @hash.each {|key,value| yield(key,value)} + end + + def CpuCounter.getRRDPath(instance, counter) + extension = ".rrd" + path = "cpu-" + instance.to_s + "/cpu-" + case counter + when CpuCounter::Idle + path += "idle" + when CpuCounter::Interrupt + path += "interrupt" + when CpuCounter::Nice + path += "nice" + when CpuCounter::Softirq + path += "softirq" + when CpuCounter::Steal + path += "steal" + when CpuCounter::System + path += "system" + when CpuCounter::User + path += "user" + when CpuCounter::Wait + path += "wait" + else + puts "Nothing" + end + + return path + end + + + def CpuCounter.getRRDIndex(counter) + return 0 + end + + + CpuCounter.add_item :Idle, 1 + CpuCounter.add_item :Interrupt, 2 + CpuCounter.add_item :Nice, 3 + CpuCounter.add_item :Softirq, 4 + CpuCounter.add_item :Steal, 5 + CpuCounter.add_item :System, 6 + CpuCounter.add_item :User, 7 + CpuCounter.add_item :Wait, 8 +end + +class MemCounter + def MemCounter.add_item(key,value) + @hash ||= {} + @hash[key]=value + end + + def MemCounter.const_missing(key) + @hash[key] + end + + def MemCounter.each + @hash.each {|key,value| yield(key,value)} + end + + def MemCounter.getRRDPath(instance, counter) + path = "memory/memory-" + case counter + when MemCounter::Buffered + path += "buffered" + when CpuCounter::Cached + path += "cache" + when MemCounter::Free + path += "free" + when MemCounter::Used + path += "used" + else + puts "Nothing" + end + return path + end + + def MemCounter.getRRDIndex(counter) + return 0 + end + + + MemCounter.add_item :Buffered, 1 + MemCounter.add_item :Cached, 2 + MemCounter.add_item :Free, 3 + MemCounter.add_item :Used, 4 +end + +class NicCounter + def NicCounter.add_item(key,value) + @hash ||= {} + @hash[key]=value + end + + def NicCounter.const_missing(key) + @hash[key] + end + + def NicCounter.each + @hash.each {|key,value| yield(key,value)} + end + + def NicCounter.getRRDPath(instance, counter) + extension = ".rrd" + path = "interface/" + case counter + when NicCounter::Errors_rx, NicCounter::Errors_tx + path += "if_errors-eth" + instance.to_s + when NicCounter::Octets_rx, NicCounter::Octets_tx + path += "if_octets-eth" + instance.to_s + when NicCounter::Packets_rx, NicCounter::Packets_tx + path += "if_packets-eth" + instance.to_s + else + puts "Nothing" + end + + return path + end + + def NicCounter.getRRDIndex(counter) + case counter + when NicCounter::Errors_rx + localIndex = 0 + when NicCounter::Errors_tx + localIndex = 1 + when NicCounter::Octets_rx + localIndex = 0 + when NicCounter::Octets_tx + localIndex = 1 + when NicCounter::Packets_rx + localIndex = 0 + when NicCounter::Packets_tx + localIndex = 1 + else + localIndex = 0 + end + + return localIndex + end + + + NicCounter.add_item :Errors_rx, 1 + NicCounter.add_item :Errors_tx, 2 + NicCounter.add_item :Octets_rx, 3 + NicCounter.add_item :Octets_tx, 4 + NicCounter.add_item :Packets_rx, 5 + NicCounter.add_item :Packets_tx, 6 +end + +class LoadCounter + def LoadCounter.add_item(key,value) + @hash ||= {} + @hash[key]=value + end + + def LoadCounter.const_missing(key) + @hash[key] + end + + def LoadCounter.each + @hash.each {|key,value| yield(key,value)} + end + + def LoadCounter.getRRDPath(instance, counter) + path = "load/" + case counter + when LoadCounter::Load_1min, LoadCounter::Load_5min, LoadCounter::Load_15min + path += "load" + else + puts "Nothing" + end + return path + end + + def LoadCounter.getRRDIndex(counter) + case counter + when LoadCounter::Load_1min + localIndex = 0 + when LoadCounter::Load_5min + localIndex = 1 + when LoadCounter::Load_15min + localIndex = 2 + else + localIndex = 0 + end + + return localIndex + end + + LoadCounter.add_item :Load_1min, 1 + LoadCounter.add_item :Load_5min, 5 + LoadCounter.add_item :Load_15min, 15 +end + +class RRDResolution + def RRDResolution.add_item(key,value) + @hash ||= {} + @hash[key]=value + end + + def RRDResolution.const_missing(key) + @hash[key] + end + + def RRDResolution.each + @hash.each {|key,value| yield(key,value)} + end + + # Set up the resolutions for our rrd + RRDResolution.add_item :Default, 10 # Ten secs + RRDResolution.add_item :Short, 500 # 500 secs ( 8minute, 20 sec) + RRDResolution.add_item :Medium, 2230 + RRDResolution.add_item :Long, 26500 +end + + + diff --git a/wui/src/app/util/stats/statsTest.rb b/wui/src/app/util/stats/statsTest.rb index bf3bc60..f7ce612 100644 --- a/wui/src/app/util/stats/statsTest.rb +++ b/wui/src/app/util/stats/statsTest.rb @@ -23,43 +23,48 @@ # It shows some simple steps to build a request list and then # request and process the data. -require 'Stats' +require 'util/stats/Stats' # Retrieve the "idle" data for cpu0 from node3, node4, and node5 requestList = [] - requestList << StatsRequest.new("node3", "cpu", 0, "idle", 1211688000, 3600, 10 ) - requestList << StatsRequest.new("node4", "cpu", 0, "idle", 0, 3600, 10 ) - requestList << StatsRequest.new("node5", "cpu", 0, "idle", 1211688000, 3600, 500 ) - requestList << StatsRequest.new("node5", "memory", 0, "used", 0, 3600, 0 ) +# requestList << StatsRequest.new("node3.priv.ovirt.org", DevClass::Load, 0, LoadCounter::Load_1min, 0, 3600, 10 ) +# requestList << StatsRequest.new("node3.priv.ovirt.org", DevClass::Load, 0, LoadCounter::Load_1min, 0, 0, RRDResolution::Long ) +# requestList << StatsRequest.new("node3.priv.ovirt.org", DevClass::Load, 0, LoadCounter::Load_15min, 0, 0, RRDResolution::Long ) +# requestList << StatsRequest.new("node3.priv.ovirt.org", DevClass::NIC, 0, NicCounter::Octets_rx, 0, 0, RRDResolution::Long ) +# requestList << StatsRequest.new("node3.priv.ovirt.org", DevClass::NIC, 0, NicCounter::Octets_tx, 0, 0, RRDResolution::Long ) + requestList << StatsRequest.new("node3.priv.ovirt.org", DevClass::Disk, 0, DiskCounter::Octets_read, 0, 0, RRDResolution::Long ) + requestList << StatsRequest.new("node3.priv.ovirt.org", DevClass::Disk, 0, DiskCounter::Octets_write, 0, 0, RRDResolution::Long ) +# requestList << StatsRequest.new("node3.priv.ovirt.org", "cpu", 0, "idle", 1211688000, 3600, 10 ) +# requestList << StatsRequest.new("node4.priv.ovirt.org", DevClass::CPU, 0, CpuCounter::Idle, 0, 3600, RRDResolution::Short ) +# requestList << StatsRequest.new("node5.priv.ovirt.org", "cpu", 0, "idle", 1211688000, 3600, 500 ) +# requestList << StatsRequest.new("node5.priv.ovirt.org", DevClass::Memory, 0, MemCounter::Used, 0, 3600, 10 ) # Now send the request list and store the results in the statsList. statsListBig = getStatsData?( requestList ) tmp = "" - # Now lets loop through the returned list. It is a list of lists so take the first list - # and chomp through it. - #, pull off the statsData object and get the data from it. + # Now lets loop through the list, pull off the statsData object and get the data from it. + # Note that there is currently only one list sent back, so you need to check the node, + # device and counter for each to detect changes. We can look at using a list of lists + # if you think it is easier to process the results. +# puts statsListBig.length statsListBig.each do |statsList| - # grab the data about this list, this will be consistent for all StatData objects in this list. - myNodeName = statsList.get_node?() - myDevClass = statsList.get_devClass?() - myInstance = statsList.get_instance?() - myCounter = statsList.get_counter?() + myNodeName = statsList.get_node?() + myDevClass = statsList.get_devClass?() + myInstance = statsList.get_instance?() + myCounter = statsList.get_counter?() + - # add a newline to break up data from different nodes for readability if tmp != myNodeName then puts end - # Now grab the data that is stored in the list - # and loop through it. Note that we print it our directly - - list = statsList.get_data?() - list.each do |d| - print("\t", myNodeName, "\t", myDevClass, "\t", myInstance, "\t", myCounter, "\t",d.get_value?, "\t",d.get_timestamp?) - puts - end + list = statsList.get_data?() + list.each do |d| + print("\t", myNodeName, "\t", myDevClass, "\t", myInstance, "\t", myCounter, "\t",d.get_value?, "\t",d.get_timestamp?) + puts + end tmp = myNodeName end diff --git a/wui/src/app/views/graph/history_graphs.rhtml b/wui/src/app/views/graph/history_graphs.rhtml index 2f0026e..21b3efc 100644 --- a/wui/src/app/views/graph/history_graphs.rhtml +++ b/wui/src/app/views/graph/history_graphs.rhtml @@ -27,7 +27,7 @@ </div> <div id="history_graphs_graphs"> <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'cpu_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'graph', :action => 'history_graph_data', :id => @id, :target => 'cpu' ) } %></div> - <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'io_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'graph', :action => 'history_graph_data', :id => @id, :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 => 'graph', :action => 'history_graph_data', :id => @id, :target => 'system' ) } %></div> --> + <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'memory_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'graph', :action => 'history_graph_data', :id => @id, :target => 'memory' ) } %></div> + <div class="history_graph" ><%= render :partial => '/layouts/graph', :locals => { :div_id => 'load_history', :chartType => 'line', :yGridLines => 'lightgrey', :url => (url_for :controller => 'graph', :action => 'history_graph_data', :id => @id, :target => 'load' ) } %></div> --> </div> </div> diff --git a/wui/src/app/views/graph/snapshot_graph.rhtml b/wui/src/app/views/graph/snapshot_graph.rhtml index 2b8f58d..68d32f8 100644 --- a/wui/src/app/views/graph/snapshot_graph.rhtml +++ b/wui/src/app/views/graph/snapshot_graph.rhtml @@ -8,11 +8,11 @@ <tr> <td>Overall Load </td> <td> - <div class="snapshot_graph_text"><%= @snapshots[:avg][:overall_load] %> </div> + <div class="snapshot_graph_text"><%= @snapshots[:avg]['load'] %> </div> <div class="snapshot_graph_container"> - <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak][:overall_load] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> + <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak]['load'] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> <div class="snapshot_graph"> - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'overall_load_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :id => @id, :target => 'overall_load' ) } %> + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'load_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :id => @id, :target => 'load' ) } %> </div> </div> </td> @@ -20,9 +20,9 @@ <tr> <td>CPU </td> <td> - <div class="snapshot_graph_text"><%= @snapshots[:avg][:cpu] %> </div> + <div class="snapshot_graph_text"><%= @snapshots[:avg]['cpu'] %> </div> <div class="snapshot_graph_container"> - <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak][:cpu] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> + <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak]['cpu'] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> <div class="snapshot_graph"> <%= render :partial => '/layouts/graph', :locals => { :div_id => 'cpu_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :target => 'cpu' ) } %> </div> @@ -30,40 +30,40 @@ </td> </tr> <tr> - <td>Network In </td> + <td>Memory </td> <td> - <div class="snapshot_graph_text"><%= @snapshots[:avg][:in] %> mb/s </div> + <div class="snapshot_graph_text"><%= @snapshots[:avg]['memory'] %> </div> <div class="snapshot_graph_container"> - <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak][:in] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> + <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak]['memory'] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> <div class="snapshot_graph"> - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'net_in_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :target => 'in' ) } %> + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'memory_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :target => 'memory' ) } %> </div> </div> </td> </tr> <tr> - <td>Network Out</td> + <td>Network In </td> <td> - <div class="snapshot_graph_text"><%= @snapshots[:avg][:out] %> mb/s</div> + <div class="snapshot_graph_text"><%= @snapshots[:avg]['netin'] %> mb/s </div> <div class="snapshot_graph_container"> - <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak][:out] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> + <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak]['netin'] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> <div class="snapshot_graph"> - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'net_out_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :target => 'out' ) } %> + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'net_in_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :target => 'netin' ) } %> </div> </div> </td> </tr> <tr> - <td>I/O </td> + <td>Network Out</td> <td> - <div class="snapshot_graph_text"><%= @snapshots[:avg][:io] %> mb/s</div> + <div class="snapshot_graph_text"><%= @snapshots[:avg]['netout'] %> mb/s</div> <div class="snapshot_graph_container"> - <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak][:io] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> + <div class="snapshot_graph_arrow" style="padding-left: <%= @snapshots[:peak]['netout'] + 28 %>px;"><%= image_tag "icon_menu_arrow.gif" %></div> <div class="snapshot_graph"> - <%= render :partial => '/layouts/graph', :locals => { :div_id => 'io_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :target => 'io' ) } %> </td> + <%= render :partial => '/layouts/graph', :locals => { :div_id => 'net_out_snapshot', :chartType => 'stackedRow', :url => (url_for :controller => 'graph', :action => 'snapshot_graph_data', :target => 'netout' ) } %> </div> </div> - </td> + </td> </tr> </table> </div> diff --git a/wui/src/app/views/host/_grid.rhtml b/wui/src/app/views/host/_grid.rhtml index 0ce2a06..a3cac7c 100644 --- a/wui/src/app/views/host/_grid.rhtml +++ b/wui/src/app/views/host/_grid.rhtml @@ -11,6 +11,7 @@ ( { url: '<%= url_for :controller => "hardware", :action => "hosts_json", :id => (hwpool.nil? ? nil : hwpool.id), :exclude_id => exclude_id %>', + url: '<%= url_for :controller => "hardware", :action => "hosts_json", :id => (hwpool.nil? ? nil : hwpool.id), :exclude_id => exclude_id %>', dataType: 'json', colModel : [ {display: '', width : 20, align: 'left', process: <%= table_id %>checkbox}, @@ -27,8 +28,8 @@ ], sortname: "hostname", sortorder: "asc", - usepager: <%= (!hwpool.nil? and hwpool.hosts.size > hosts_per_page) ? 'true' : 'false' %>, - useRp: <%= (!hwpool.nil? and hwpool.hosts.size > hosts_per_page) ? 'true' : 'false' %>, + usepager: <%= (!hwpool.nil? and hwpool.hosts.size > hosts_per_page) ? 'true' : 'false' %>, + useRp: <%= (!hwpool.nil? and hwpool.hosts.size > hosts_per_page) ? 'true' : 'false' %>, rp: <%= hosts_per_page %>, showTableToggleBtn: true, onSelect: <%= on_select %>, diff --git a/wui/src/app/views/storage/_grid.rhtml b/wui/src/app/views/storage/_grid.rhtml index 15a0331..843d64d 100644 --- a/wui/src/app/views/storage/_grid.rhtml +++ b/wui/src/app/views/storage/_grid.rhtml @@ -9,7 +9,7 @@ $("#<%= table_id %>").flexigrid ( { - url: '<%= url_for :controller => "hardware", :action => "storage_pools_json", :id => (hwpool.nil? ? nil : hwpool.id), :exclude_id => exclude_id %>', + url: '<%= url_for :controller => "hardware", :action => "storage_pools_json", :id => (hwpool.nil? ? nil : hwpool.id), :exclude_id => exclude_id %>', dataType: 'json', colModel : [ {display: '', width : 20, align: 'left', process: <%= table_id %>checkbox}, @@ -20,8 +20,8 @@ ], sortname: "ip_addr", sortorder: "asc", - usepager: <%= (!hwpool.nil? and hwpool.storage_pools.size > storage_per_page) ? 'true' : 'false' %>, - useRp: <%= (!hwpool.nil? and hwpool.storage_pools.size > storage_per_page) ? 'true' : 'false' %>, + usepager: <%= (!hwpool.nil? and hwpool.storage_pools.size > storage_per_page) ? 'true' : 'false' %>, + useRp: <%= (!hwpool.nil? and hwpool.storage_pools.size > storage_per_page) ? 'true' : 'false' %>, rp: <%= storage_per_page %>, showTableToggleBtn: true, onSelect: <%= on_select %> diff --git a/wui/src/app/views/storage/addstorage.html.erb b/wui/src/app/views/storage/addstorage.html.erb index 0fb3ce1..fa49111 100644 --- a/wui/src/app/views/storage/addstorage.html.erb +++ b/wui/src/app/views/storage/addstorage.html.erb @@ -31,7 +31,7 @@ <div class="panel_header"></div> <div class="dialog_body"> <%= render :partial => "/storage/grid", :locals => { :table_id => "addstorage_grid", - :hwpool => nil, :exclude_id => @hardware_pool.id, + :hwpool => nil, :exclude_id => @hardware_pool.id, :on_select => "false" } %> </div> </div> diff --git a/wui/src/app/views/vm/_grid.rhtml b/wui/src/app/views/vm/_grid.rhtml index b0fc71a..c56e6b8 100644 --- a/wui/src/app/views/vm/_grid.rhtml +++ b/wui/src/app/views/vm/_grid.rhtml @@ -24,7 +24,7 @@ sortname: "description", sortorder: "asc", usepager: <%= pool.vms.size > vms_per_page ? 'true' : 'false' %>, - useRp: <%= pool.vms.size > vms_per_page ? 'true' : 'false' %>, + useRp: <%= pool.vms.size > vms_per_page ? 'true' : 'false' %>, rp: <%= vms_per_page %>, showTableToggleBtn: true, onSelect: <%= on_select %>, diff --git a/wui/src/public/stylesheets/components.css b/wui/src/public/stylesheets/components.css index 30730da..e2bc235 100644 --- a/wui/src/public/stylesheets/components.css +++ b/wui/src/public/stylesheets/components.css @@ -190,7 +190,7 @@ position: relative; float: left; } -#cpu_history, #io_history, #overall_load_history{ +#cpu_history, #io_history, #load_history, #memory_history{ height: 200px; width: 1200px; position: absolute; left: -70px; } @@ -199,7 +199,7 @@ #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 { +#load_snapshot, #cpu_snapshot, #net_in_snapshot, #net_out_snapshot, #io_snapshot, #memory_snapshot { width: 350px; height: 20px; float: left; } .snapshot_graph_text { -- 1.5.4.1