[Ovirt-devel] [PATCH server] Add host chart to flexchart.

Steve Linabery slinabery at redhat.com
Fri Feb 6 05:55:36 UTC 2009


Allow user to select the data function desired (min, peak, avg, rolling averages, etc.).
Add scale to y-axis.
Various changes to the class structure.
---
 src/app/controllers/graph_controller.rb            |   89 +++++++-
 src/app/util/stats/Stats.rb                        |   20 ++-
 src/app/util/stats/StatsDataList.rb                |   11 +-
 src/app/views/graph/history_graphs.rhtml           |    2 +-
 src/config/routes.rb                               |    4 +-
 src/flexchart/flexchart.mxml                       |   33 ++-
 src/flexchart/org/ovirt/ApplicationBus.as          |   10 +-
 src/flexchart/org/ovirt/DataSource.as              |   60 -----
 src/flexchart/org/ovirt/charts/BarChart.as         |  244 ++++++++++++++------
 src/flexchart/org/ovirt/charts/Chart.as            |   79 +++++--
 src/flexchart/org/ovirt/charts/HostChart.as        |  177 ++++++++++++++
 src/flexchart/org/ovirt/data/BarChartDataSource.as |   42 ++++
 src/flexchart/org/ovirt/data/DataPoint.as          |   16 ++-
 src/flexchart/org/ovirt/data/DataSeries.as         |   11 +-
 src/flexchart/org/ovirt/data/DataSource.as         |   66 ++++++
 .../org/ovirt/data/FlexchartDataTransferObject.as  |   90 +++++++
 .../org/ovirt/data/HostChartDataSource.as          |   42 ++++
 src/flexchart/org/ovirt/elements/Scale.as          |   87 +++++++
 src/flexchart/org/ovirt/elements/SingleBar.as      |    9 +-
 19 files changed, 902 insertions(+), 190 deletions(-)
 delete mode 100644 src/flexchart/org/ovirt/DataSource.as
 create mode 100644 src/flexchart/org/ovirt/charts/HostChart.as
 create mode 100644 src/flexchart/org/ovirt/data/BarChartDataSource.as
 create mode 100644 src/flexchart/org/ovirt/data/DataSource.as
 create mode 100644 src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as
 create mode 100644 src/flexchart/org/ovirt/data/HostChartDataSource.as
 create mode 100644 src/flexchart/org/ovirt/elements/Scale.as

diff --git a/src/app/controllers/graph_controller.rb b/src/app/controllers/graph_controller.rb
index e8eea7e..15fa572 100644
--- a/src/app/controllers/graph_controller.rb
+++ b/src/app/controllers/graph_controller.rb
@@ -3,13 +3,14 @@ require 'util/stats/Stats'
 class GraphController < ApplicationController
   layout nil
 
+
   def flexchart_data
     @id = params[:id]
     target = params[:target]
     startTime = Time.at(params[:startTime].to_i)
     endTime = Time.at(params[:endTime].to_i)
     duration = endTime.to_i - startTime.to_i
-
+    dataFunction = DEV_KEY_FUNCTIONS[params[:dataFunction]] ? DEV_KEY_FUNCTIONS[params[:dataFunction]] : DEV_KEY_FUNCTIONS['peak']
     #the maximum number of data points we want in any chart
     maxPoints = 100
     resolution =
@@ -51,7 +52,7 @@ class GraphController < ApplicationController
                                           range[0].to_i,
                                           range[1].to_i - range[0].to_i,
                                           resolution,
-                                          DataFunction::Peak)
+                                          dataFunction)
       }
     }
     statsList = getAggregateStatsData?(requestList)
@@ -62,15 +63,87 @@ class GraphController < ApplicationController
     data.each{ |datum|
       val = datum.get_value?
       val = 0 if (val != 0 && val.nan?)
-      vectors.push [datum.get_timestamp?.to_i, val]
+      vectors.push [datum.get_timestamp?.to_i, val, "n/a"]
     }
     graph = { :vectors => vectors,
       :max_value => stat.get_max_value?,
-      :description => target
+      :description => target,
+      :resolution => stat.get_resolution?
     }
     render :json => graph
   end
 
+  def host_chart_data
+    #expect (pool) id, resolution, startTime, target, dataFunction
+    @id = params[:id]
+    resolution = params[:resolution].to_i
+    startTime = Time.at(params[:startTime].to_i)
+    target = params[:target]
+    dataFunction = params[:dataFunction]
+
+    devclass = DEV_KEY_CLASSES[target]
+    counter = DEV_KEY_COUNTERS[target]
+
+
+    pool = Pool.find(@id)
+    hosts = Host.find(:all,
+                      :include=> :membership_audit_events,
+                      :conditions => ['membership_audit_events.container_target_id = ?',pool])
+
+    requestList = [ ]
+    hosts.each{ |host|
+
+      eventsInRange = host.membership_audit_events.from_pool(pool,
+                                                             startTime,
+                                                             Time.at(startTime.to_i + resolution))
+      excluded = false
+      if eventsInRange.empty?
+        priorAuditEvent = host.membership_audit_events.most_recent_prior_event_from_pool(pool,startTime)
+        if priorAuditEvent.nil? || priorAuditEvent.action == MembershipAuditEvent::LEAVE
+          excluded = true
+        end
+      end
+
+      if (! excluded)
+        requestList.push StatsRequest.new(host.hostname,
+                                          devclass,
+                                          0,
+                                          counter,
+                                          startTime.to_i - resolution,
+                                          resolution,
+                                          resolution,
+                                          dataFunction)
+      end
+    }
+
+    statsLists = getStatsData?(requestList)
+    vectors = [ ]
+
+    myMax = 0
+    statsLists.each { |statsList|
+      nodeName = statsList.get_node?.to_s
+      data = statsList.get_data?
+
+      myVal = data[0].get_value?
+      myTime = data[0].get_timestamp?.to_i
+      if myVal.is_a?(Float) && myVal.nan?
+        myVal = 0
+      end
+      myMax = [myMax, myVal].max
+      vectors.push [myTime, myVal, nodeName.to_s]
+    }
+
+
+    graph = { :vectors => vectors,
+      :max_value => myMax,
+      :description => target,
+      :resolution => resolution
+    }
+
+    render :json => graph
+  end
+
+
   def get_ranges_from_event_list(list, priorEvent, startTime, endTime)
 
     results = Array.new
@@ -507,6 +580,14 @@ class GraphController < ApplicationController
                  'load' => LoadCounter::Load_1min, 'netin' => NicCounter::Octets_rx, 'netout' => NicCounter::Octets_tx }
       DEV_COUNTER_KEYS = DEV_KEY_COUNTERS.invert
 
+      DEV_KEY_FUNCTIONS = { 'average' => DataFunction::Average,
+        'peak' => DataFunction::Peak,
+        'min' => DataFunction::Min,
+        'rolling avg' => DataFunction::RollingAverage,
+        'rolling peak' => DataFunction::RollingPeak,
+        'rolling min' => DataFunction::RollingMin }
+      DEV_FUNCTION_KEYS = DEV_KEY_FUNCTIONS.invert
+
       def _create_host_snapshot_requests(hostname, duration, resolution)
         requestList = []
         requestList << StatsRequest.new(hostname, DEV_KEY_CLASSES['memory'], 0, DEV_KEY_COUNTERS['memory'],
diff --git a/src/app/util/stats/Stats.rb b/src/app/util/stats/Stats.rb
index f6b0c7a..f7e9dbe 100644
--- a/src/app/util/stats/Stats.rb
+++ b/src/app/util/stats/Stats.rb
@@ -27,6 +27,8 @@ require 'util/stats/StatsRequest'
 
 # This fetches a rolling average, basically average points before and after.
 
+
+
 def fetchRollingAve?(rrdPath, start, endTime, interval, myFunction, lIndex, returnList, aveLen=7)
    final = 0
    my_min = 0
@@ -255,11 +257,11 @@ def fetchData?(node, devClass, instance, counter, startTime, duration, interval,
       sTime = startTime
       eTime = sTime + duration
    end 
-
    # 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 + "/"
 
@@ -309,7 +311,7 @@ def fetchData?(node, devClass, instance, counter, startTime, duration, interval,
           myFunction="AVERAGE"
     end
 
-   returnList = StatsDataList.new(node,devClass,instance, counter, localStatus, function)
+   returnList = StatsDataList.new(node,devClass,instance, counter, localStatus, function, interval)
 
    if ( localStatus == StatsStatus::SUCCESS )
       if ( function == DataFunction::RollingPeak) || 
@@ -368,14 +370,23 @@ def  getAggregateStatsData?(statRequestList)
     my_max = 0
     value = 0
 
+    resolution = 0
+
     node = "Aggregate"
-    returnList = StatsDataList.new("Aggregate",0,0, 0, 0, 0)
+    returnList = StatsDataList.new("Aggregate", 0, 0, 0, 0, 0, 0)
     statRequestList.each do |request|
+       #all aggregates need to have the same interval/resolution/precision
+       if resolution == 0
+         resolution = request.get_precision?
+       end
        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?, request.get_function?)
-
+       #if the interval/resolution/precision varies, raise an exception
+       if request.get_precision? != resolution
+         raise
+       end
        #  Now for something completely different...
        #  The first list back will become our "master"
        #  Each successive list will be proccesed against the master
@@ -458,6 +469,7 @@ def  getAggregateStatsData?(statRequestList)
     end
     returnList.set_min_value(my_min)
     returnList.set_max_value(my_max)
+    returnList.set_resolution(resolution)
     myList << returnList
 
 return myList
diff --git a/src/app/util/stats/StatsDataList.rb b/src/app/util/stats/StatsDataList.rb
index a39bcc4..6c71400 100644
--- a/src/app/util/stats/StatsDataList.rb
+++ b/src/app/util/stats/StatsDataList.rb
@@ -20,7 +20,7 @@
 
 #define class StatsData  List
 class StatsDataList
-  def initialize(node,devClass,instance, counter, status, function)
+  def initialize(node, devClass, instance, counter, status, function, resolution)
     # Instance variables  
     @node = node
     @devClass = devClass
@@ -31,6 +31,7 @@ class StatsDataList
     @function = function
     @min_value = 0
     @max_value = 0
+    @resolution = 0
   end
   
   def get_node?()  
@@ -88,4 +89,12 @@ class StatsDataList
   def get_max_value?()
     return @max_value
   end
+
+  def set_resolution(value)
+    @resolution = value
+  end
+
+  def get_resolution?()
+    return @resolution
+  end
 end
diff --git a/src/app/views/graph/history_graphs.rhtml b/src/app/views/graph/history_graphs.rhtml
index 97ed67f..9488367 100644
--- a/src/app/views/graph/history_graphs.rhtml
+++ b/src/app/views/graph/history_graphs.rhtml
@@ -10,7 +10,7 @@ $('#flex_history_chart').flash(
           height: 300,
           wmode: 'transparent',
           menu: false,
-          flashvars: { flexchart_data: "<%= url_for :controller =>'/graph', :action => 'flexchart_data' %>/<%= @id %>/memory/<%= Time.now.to_i - 60 * 60 * 24 %>/<%= Time.now.to_i %>" }
+          flashvars: { flexchart_data: "<%= url_for :controller =>'/graph', :action => 'flexchart_data' %>/<%= @id %>/memory/<%= Time.now.to_i - 60 * 60 * 24 %>/<%= Time.now.to_i %>/peak" }
         },
         { version: 9 }
     );
diff --git a/src/config/routes.rb b/src/config/routes.rb
index 168ded5..d286c3f 100644
--- a/src/config/routes.rb
+++ b/src/config/routes.rb
@@ -42,8 +42,8 @@ ActionController::Routing::Routes.draw do |map|
   map.connect ':controller/service.wsdl', :action => 'wsdl'
 
   # Install the default route as the lowest priority.
-  map.connect 'graph/flexchart_data/:id/:target/:startTime/:endTime', :controller => 'graph', :action => 'flexchart_data'
-  map.connect 'graph/flexchart_data/:id/:target/:days', :controller => 'graph', :action => 'flexchart_data'
+  map.connect 'graph/flexchart_data/:id/:target/:startTime/:endTime/:dataFunction', :controller => 'graph', :action => 'flexchart_data'
+  map.connect 'graph/host_chart_data/:id/:target/:startTime/:resolution/:dataFunction', :controller => 'graph', :action => 'host_chart_data'
   map.connect ':controller/:action/:id.:format'
   map.connect ':controller/:action/:id'
 
diff --git a/src/flexchart/flexchart.mxml b/src/flexchart/flexchart.mxml
index c4a089f..7a86cd9 100644
--- a/src/flexchart/flexchart.mxml
+++ b/src/flexchart/flexchart.mxml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="myInit(); populate(mainChart);" styleName="plain" horizontalScrollPolicy="off" verticalScrollPolicy="off">
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="myInit();" styleName="plain" horizontalScrollPolicy="off" verticalScrollPolicy="off">
   <mx:Script>
     <![CDATA[
 
@@ -9,10 +9,9 @@
     import org.ovirt.ApplicationBus;
     import org.ovirt.charts.Chart;
     import org.ovirt.charts.BarChart;
+    import org.ovirt.charts.HostChart;
 
-    private function populate(container:VBox):void {
-        var chart:Chart = new BarChart(container, parameters['flexchart_data']);
-        chart.load();
+    private function populate(container:Box):void {
     }
 
     private var expandHistory:Resize = new Resize();
@@ -23,9 +22,10 @@
 
     private function myInit():void {
 
+      var bus:ApplicationBus = ApplicationBus.instance();
       mainChart.height = Constants.height;
       mainChart.width = Constants.width;
-      hostsChart.width = Constants.width;
+      hostChart.width = Constants.width;
 
       expandHistory.widthTo = Constants.width;
       expandHistory.heightTo = Constants.height;
@@ -37,26 +37,33 @@
 
       expandResources.widthTo = Constants.width;
       expandResources.heightTo = Constants.height * .6666;
-      expandResources.target = hostsChart;
+      expandResources.target = hostChart;
       expandResources.duration = 500;
 
       contractResources.widthTo = Constants.width;
       contractResources.heightTo = 0;
-      contractResources.target = hostsChart;
+      contractResources.target = hostChart;
       contractResources.duration = 500;
 
-      ApplicationBus.instance().barClickAction = zoomIntoSeries;
+      bus.mainChartBarClickAction = zoomIntoSeries;
+      bus.closeHostChart = zoomOutSeries;
 
+      var mChart:Chart = new BarChart(mainChart, parameters['flexchart_data']);
+      bus.mainChart = mChart as BarChart;
+      mChart.load();
+
+      var hChart:Chart = new HostChart(hostChart);
+      bus.hostChart = hChart as HostChart;
     }
 
     private function zoomOutSeries(e:Event):void {
       expandHistory.end(); expandHistory.play();
       contractResources.end(); contractResources.play();
-      hostsChart.visible = false;
+      hostChart.visible = false;
     }
 
     private function zoomIntoSeries(e:Event):void {
-      hostsChart.visible=true;
+      hostChart.visible=true;
       expandResources.end(); expandResources.play();
       contractHistory.end(); contractHistory.play();
     }
@@ -66,8 +73,8 @@
 
   </mx:Script>
 
-  <mx:VBox id="mainChart" />
-  <mx:VBox id="hostsChart" visible="false" opaqueBackground="0x00ff00" click="zoomOutSeries(event)">
-    <mx:Text text="This Space Reserved for Drill-down Hosts Chart" />
+  <mx:Box id="mainChart" />
+  <mx:VBox id="hostChart" visible="false" opaqueBackground="0xffffff" click="zoomOutSeries(event)">
+
   </mx:VBox>
 </mx:Application>
diff --git a/src/flexchart/org/ovirt/ApplicationBus.as b/src/flexchart/org/ovirt/ApplicationBus.as
index 7d6d431..24474b9 100644
--- a/src/flexchart/org/ovirt/ApplicationBus.as
+++ b/src/flexchart/org/ovirt/ApplicationBus.as
@@ -22,6 +22,10 @@
 //our ActionScript classes without needing to access Application directly
 
 package org.ovirt {
+
+  import org.ovirt.charts.BarChart;
+  import org.ovirt.charts.HostChart;
+
   public class ApplicationBus {
 
     private static var _instance:ApplicationBus;
@@ -33,7 +37,11 @@ package org.ovirt {
       return _instance;
     }
 
-    public var barClickAction:Function;
+    public var mainChartBarClickAction:Function;
+    public var closeHostChart:Function;
+
+    public var mainChart:BarChart;
+    public var hostChart:HostChart;
 
   }
 }
diff --git a/src/flexchart/org/ovirt/DataSource.as b/src/flexchart/org/ovirt/DataSource.as
deleted file mode 100644
index 4438900..0000000
--- a/src/flexchart/org/ovirt/DataSource.as
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- Copyright (C) 2008 Red Hat, Inc.
- Written by Steve Linabery <slinabery 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.
-*/
-
-package org.ovirt {
-
-  import com.adobe.serialization.json.JSON;
-  import flash.events.Event;
-  import flash.events.IOErrorEvent;
-  import flash.net.URLLoader;
-  import flash.net.URLRequest;
-  import org.ovirt.charts.Chart;
-  import org.ovirt.data.DataSeries;
-
-  public class DataSource {
-
-    private var chart:Chart;
-
-    public function DataSource(chart:Chart) {
-      this.chart = chart;
-    }
-
-    public function retrieveData(url:String):void {
-      var loader:URLLoader = new URLLoader();
-      loader.addEventListener(IOErrorEvent.IO_ERROR, this.ioError);
-      loader.addEventListener(Event.COMPLETE, dataLoaded);
-      var request:URLRequest = new URLRequest(url);
-      loader.load(request);
-    }
-
-    private function dataLoaded(event:Event):void {
-      var loader:URLLoader = URLLoader(event.target);
-      var object:Object = JSON.decode(loader.data);
-      var series:DataSeries = new DataSeries(object);
-      chart.addData(series);
-    }
-
-    private function ioError( e:IOErrorEvent ):void {
-      trace("ioError");
-      //FIXME:
-      //do something useful with this error
-    }
-  }
-}
diff --git a/src/flexchart/org/ovirt/charts/BarChart.as b/src/flexchart/org/ovirt/charts/BarChart.as
index 88a75ca..08710d2 100644
--- a/src/flexchart/org/ovirt/charts/BarChart.as
+++ b/src/flexchart/org/ovirt/charts/BarChart.as
@@ -37,9 +37,12 @@ package org.ovirt.charts {
   import org.ovirt.elements.*;
   import org.ovirt.Constants;
   import org.ovirt.ApplicationBus;
+  import mx.core.ScrollPolicy;
 
   public class BarChart extends Chart {
 
+    private var yScale:Scale;
+    private var chartFrame:HBox;
     private var chartArea:Canvas;
     private var XAxisLabelArea:Canvas;
     private var startDateField:DateField;
@@ -48,18 +51,13 @@ package org.ovirt.charts {
     private var endTimeField:TextInput;
     private var button:Button;
     private var menu:PopUpMenuButton;
+    private var functionMenu:PopUpMenuButton;
     private var dateBar:Box;
     private var datePattern:RegExp;
 
-
-    public function BarChart(container:Box,
-                             datasourceUrl:String) {
-      super(container,datasourceUrl);
-      container.setStyle("verticalGap","2");
-      datePattern = /^(\d+):(\d+)$/;
-    }
-
-
+    /*
+       Private, class-specific functions
+    */
     private function timeRangeAdjusted(event:Event):void {
       var t1:Number = startDateField.selectedDate.getTime()
                       + (parseHour(startTimeField.text) * 3600 * 1000)
@@ -69,14 +67,34 @@ package org.ovirt.charts {
                       + (parseHour(endTimeField.text) * 3600 * 1000)
                       + (parseMinute(endTimeField.text) * 60 * 1000);
       setEndTime(Math.floor(t2 / 1000));
+
+      //close the host chart when updating top chart
+      ApplicationBus.instance().closeHostChart.call(null,event);
       load();
     }
 
+
+    private function updateHostChart(event:MouseEvent):void {
+      var hostChart:HostChart = ApplicationBus.instance().hostChart;
+      hostChart.setId(id);
+      hostChart.setTarget(target);
+      hostChart.setStartTime((event.target as SingleBar).getStartTime() / 1000);
+      hostChart.setResolution((event.target as SingleBar).getResolution());
+      hostChart.setDataFunction(dataFunction);
+      hostChart.load();
+    }
+
     private function typeSelected(event:MenuEvent):void {
       target = event.label;
+      ApplicationBus.instance().closeHostChart.call(null,event);
       load();
     }
 
+    private function functionSelected(event:MenuEvent):void {
+      dataFunction = event.label;
+      ApplicationBus.instance().closeHostChart.call(null,event);
+      load();
+    }
 
     private function pad(input:int):String {
       if (input < 10) {
@@ -108,6 +126,32 @@ package org.ovirt.charts {
       return answer;
     }
 
+
+    /*
+      Constructors
+    */
+    public function BarChart(container:Box,
+                             datasourceUrl:String) {
+      super(container,datasourceUrl);
+      container.setStyle("verticalGap","2");
+      datePattern = /^(\d+):(\d+)$/;
+    }
+
+    /*
+      Overriden functions
+    */
+    override protected function initializeDataSource():void {
+      dataSource = new BarChartDataSource(this);
+    }
+
+    override protected function setRequestAttributes(dto:FlexchartDataTransferObject):void {
+      dto.setId(id);
+      dto.setTarget(target);
+      dto.setStartTime(startTime);
+      dto.setEndTime(endTime);
+      dto.setDataFunction(dataFunction);
+    }
+
     override public function addData(dataSeries:DataSeries):void {
       container.removeAllChildren();
 
@@ -123,11 +167,30 @@ package org.ovirt.charts {
         }
       }
 
+
+      var yLabelPercentWidth:int = 8;
+
+      chartFrame = new HBox();
+      chartFrame.percentHeight = 80;
+      chartFrame.percentWidth = 100;
+      chartFrame.setVisible(true);
+      chartFrame.setStyle("horizontalGap","1");
+
+      yScale = new Scale();
+      yScale.percentHeight = 100;
+      yScale.percentWidth = yLabelPercentWidth;
+      yScale.setVisible(true);
+
       chartArea = new Canvas();
-      chartArea.percentHeight = 80;
-      chartArea.percentWidth = 100;
+      chartArea.percentHeight = 100;
+      chartArea.percentWidth = 100 - yLabelPercentWidth;
       chartArea.setStyle("backgroundColor","0xbbccdd");
-      this.container.addChild(chartArea);
+
+      chartArea.verticalScrollPolicy = ScrollPolicy.OFF
+
+      chartFrame.addChild(yScale);
+      chartFrame.addChild(chartArea);
+      this.container.addChild(chartFrame);
 
       XAxisLabelArea = new Canvas();
       XAxisLabelArea.height = Constants.labelHeight;
@@ -135,6 +198,9 @@ package org.ovirt.charts {
       XAxisLabelArea.percentWidth = 100;
       this.container.addChild(XAxisLabelArea);
 
+      var t1:Date = new Date(startTime * 1000);
+      var t2:Date = new Date(endTime * 1000);
+
       try {
 
         dateBar = new HBox();
@@ -143,6 +209,7 @@ package org.ovirt.charts {
         var dataPoints:Array = dataSeries.getDataPoints();
         var maxValue:Number = dataSeries.getMaxValue();
         var scale:Number = maxValue;
+        yScale.setMax(maxValue);
         //avoid divide by zero
         if (scale == 0) {
           scale = 1;
@@ -152,8 +219,10 @@ package org.ovirt.charts {
           throw new Error("No data points in range");
         }
 
+	var calculatedWidth:Number = Constants.width * (chartArea.percentWidth / 100.0) ;
+
         //the distance between left edges of adjacent bars
-        var gridWidth:Number = Math.floor(Constants.width / size);
+        var gridWidth:Number = Math.floor(calculatedWidth / size);
 
         //the width of each SingleBar (does not including padding between bars)
         var barWidth:Number = gridWidth - Constants.barSpacing;
@@ -161,7 +230,7 @@ package org.ovirt.charts {
         //due to the discrete number of pixels, there may be space at the
         //right side of the graph that needs to be made up by padding
         //bars here and there
-	var shortfall:Number = Constants.width - (gridWidth * size);
+	var shortfall:Number = calculatedWidth - (gridWidth * size);
 	var makeup:Number = Math.round(size / shortfall);
 	var madeup:Number = 0;
 
@@ -196,7 +265,9 @@ package org.ovirt.charts {
           chartArea.addChild(bar);
           bar.width = barWidth;
           bar.addEventListener(MouseEvent.CLICK,
-                               ApplicationBus.instance().barClickAction);
+                               ApplicationBus.instance().mainChartBarClickAction);
+          bar.addEventListener(MouseEvent.CLICK,
+                               updateHostChart);
 	  bar.x = currentBarPosition;
           if (makeup > 0 && i % makeup == 0 && madeup < shortfall) {
             bar.width = bar.width + 1;
@@ -214,7 +285,7 @@ package org.ovirt.charts {
               || i == size - 1) {
             var label:XAxisLabel =
               new XAxisLabel(dateFormat.format(dataPoint.getTimestamp()));
-	    label.setCenter(currentBarPosition + bar.width / 2);
+	    label.setCenter(currentBarPosition + bar.width / 2 + Constants.width - calculatedWidth);
             label.setVisible(true);
             label.y = 6;
             XAxisLabelArea.addChild(label);
@@ -235,69 +306,90 @@ package org.ovirt.charts {
           currentBarPosition += (bar.width + Constants.barSpacing);
         }
 
-        //fill in the time range selection bar
-        var t:Date;
-        var f1:Text = new Text();
-        f1.text = "View data between";
-        dateBar.addChild(f1);
-        t = new Date(dataPoints[0].getTimestamp().getTime());
-        startDateField = new DateField();
-        startDateField.selectedDate = t;
-        startDateField.editable = true;
-        startTimeField = new TextInput();
-        startTimeField.minWidth = 50;
-        startTimeField.maxWidth = 50;
-        startTimeField.text = pad(t.hours) + ":" + pad(t.minutes);
-        dateBar.addChild(startTimeField);
-        dateBar.addChild(startDateField);
-        var f2:Text = new Text();
-        f2.text = "and";
-        dateBar.addChild(f2);
-
-        t = new Date(dataPoints[size - 1].getTimestamp().getTime());
-        endDateField = new DateField();
-        endDateField.selectedDate = t;
-        endDateField.editable = true;
-        endTimeField = new TextInput();
-        endTimeField.minWidth = 50;
-        endTimeField.maxWidth = 50;
-        endTimeField.text = pad(t.hours) + ":" + pad(t.minutes);
-        dateBar.addChild(endTimeField);
-        dateBar.addChild(endDateField);
-
-	button = new Button();
-	button.label = "go";
-	button.addEventListener(MouseEvent.CLICK,timeRangeAdjusted);
-	dateBar.addChild(button);
-
-        //FIXME: these should be fetched from the graph controller so
-        //that different types can be added (or restricted) dynamically
-        var menuItems:ArrayCollection =
-          new ArrayCollection( [{label: "memory"},
-                                {label: "cpu"},
-                                {label: "load"},
-                                {label: "netin"},
-                                {label: "netout"},
-                                {label: "disk"}
-                               ]);
-
-
-        if (menu != null) {
-          menu.removeEventListener(MenuEvent.ITEM_CLICK,typeSelected);
-        }
-
-        menu = new PopUpMenuButton();
-        menu.label = "Select Data Type";
-        menu.dataProvider = menuItems;
-        menu.addEventListener(MenuEvent.ITEM_CLICK,typeSelected);
-        dateBar.addChild(menu);
+        t1 = new Date(dataPoints[0].getTimestamp().getTime());
+        t2 = new Date(dataPoints[size - 1].getTimestamp().getTime());
 
       } catch (e:Error) {
-        var err:Text = new Text();
-        err.text = e.message;
-        err.setVisible(true);
-        chartArea.addChild(err);
+        trace(e.message);
+      }
+
+      //fill in the time range selection bar
+
+      var f1:Text = new Text();
+      f1.text = "View data between";
+      dateBar.addChild(f1);
+
+      startDateField = new DateField();
+      startDateField.selectedDate = t1;
+      startDateField.editable = true;
+      startTimeField = new TextInput();
+      startTimeField.minWidth = 50;
+      startTimeField.maxWidth = 50;
+      startTimeField.text = pad(t1.hours) + ":" + pad(t1.minutes);
+      dateBar.addChild(startTimeField);
+      dateBar.addChild(startDateField);
+      var f2:Text = new Text();
+      f2.text = "and";
+      dateBar.addChild(f2);
+
+
+      endDateField = new DateField();
+      endDateField.selectedDate = t2;
+      endDateField.editable = true;
+      endTimeField = new TextInput();
+      endTimeField.minWidth = 50;
+      endTimeField.maxWidth = 50;
+      endTimeField.text = pad(t2.hours) + ":" + pad(t2.minutes);
+      dateBar.addChild(endTimeField);
+      dateBar.addChild(endDateField);
+
+      button = new Button();
+      button.label = "go";
+      button.addEventListener(MouseEvent.CLICK,timeRangeAdjusted);
+
+      dateBar.addChild(button);
+
+      //FIXME: these should be fetched from the graph controller so
+      //that different types can be added (or restricted) dynamically
+      var menuItems:ArrayCollection =
+        new ArrayCollection( [{label: "memory"},
+                              {label: "cpu"},
+                              {label: "load"},
+                              {label: "netin"},
+                              {label: "netout"},
+                              {label: "disk"}
+                             ]);
+
+      if (menu != null) {
+        menu.removeEventListener(MenuEvent.ITEM_CLICK,typeSelected);
       }
+
+      menu = new PopUpMenuButton();
+      menu.label = "Data Type";
+      menu.dataProvider = menuItems;
+      menu.addEventListener(MenuEvent.ITEM_CLICK,typeSelected);
+      dateBar.addChild(menu);
+
+
+      var functionMenuItems:ArrayCollection =
+        new ArrayCollection( [{label: "average"},
+                              {label: "peak"},
+                              {label: "min"},
+                              {label: "rolling avg"},
+                              {label: "rolling peak"},
+                              {label: "rolling min"}
+                             ]);
+
+      if (functionMenu != null) {
+        functionMenu.removeEventListener(MenuEvent.ITEM_CLICK,functionSelected);
+      }
+
+      functionMenu = new PopUpMenuButton();
+      functionMenu.label = "Fn Type";
+      functionMenu.dataProvider = functionMenuItems;
+      functionMenu.addEventListener(MenuEvent.ITEM_CLICK,functionSelected);
+      dateBar.addChild(functionMenu);
+
     }
   }
 }
diff --git a/src/flexchart/org/ovirt/charts/Chart.as b/src/flexchart/org/ovirt/charts/Chart.as
index f2faf33..ee6992e 100644
--- a/src/flexchart/org/ovirt/charts/Chart.as
+++ b/src/flexchart/org/ovirt/charts/Chart.as
@@ -19,58 +19,87 @@
 */
 
 package org.ovirt.charts {
-    import org.ovirt.DataSource;
-    import mx.containers.Box;
-    import org.ovirt.data.DataSeries;
+  import org.ovirt.data.DataSource;
+  import mx.containers.Box;
+  import org.ovirt.data.DataSeries;
+  import org.ovirt.data.FlexchartDataTransferObject;
 
   public class Chart {
 
     protected var container:Box;
-    protected var datasourceUrl:String;
+    protected var dataSource:DataSource;
 
     protected var startTime:Number;
     protected var endTime:Number;
     protected var target:String;
     protected var id:int;
+    protected var dataFunction:String;
+    protected var resolution:int;
 
+    /*
+      Inheritable functions that generally do not need overrides
+    */
+    public function setStartTime(startTime:Number):void {
+      this.startTime = startTime;
+    }
+
+    public function setEndTime(endTime:Number):void {
+      this.endTime = endTime;
+    }
+
+    public function setTarget(target:String):void {
+      this.target = target;
+    }
+
+    public function setId(id:int):void {
+      this.id = id;
+    }
+
+    public function setDataFunction(dataFunction:String):void {
+      this.dataFunction = dataFunction;
+    }
+
+    public function setResolution(resolution:int):void {
+      this.resolution = resolution;
+    }
+
+    public function load():void {
+      var dto:FlexchartDataTransferObject = new FlexchartDataTransferObject();
+      setRequestAttributes(dto);
+      dataSource.retrieveData(dto);
+    }
+
+    /*
+      Constructors
+    */
     public function Chart(container:Box, datasourceUrl:String) {
       this.container = container;
-      this.datasourceUrl = datasourceUrl;
+      initializeDataSource();
       if (datasourceUrl != null) {
         var results:Array = datasourceUrl.split("/");
-        if (results != null && results.length > 7) {
+        if (results != null && results.length > 8) {
           setId(new int(results[4]));
           setTarget(results[5] as String);
           setStartTime(new int(results[6]));
           setEndTime(new int(results[7]));
+          setDataFunction(results[8] as String);
         }
       }
     }
 
-    public function addData(dataSeries:DataSeries):void {
-      //override me!
-    }
-
-    public function load():void {
-      var dataSource:DataSource = new DataSource(this);
-      var myString:String = "/ovirt/graph/flexchart_data/" + id + "/" + target +  "/" + startTime  + "/" + endTime;
-      dataSource.retrieveData(myString);
+    /*
+      Functions that subclasses should override
+      (ActionScript does not offer abstract methods)
+    */
+    protected function initializeDataSource():void {
     }
 
-    public function setStartTime(startTime:Number):void {
-      this.startTime = startTime;
+    //subclasses should override this
+    protected function setRequestAttributes(dto:FlexchartDataTransferObject):void {
     }
 
-    public function setEndTime(endTime:Number):void {
-      this.endTime = endTime;
-    }
-
-    public function setTarget(target:String):void {
-      this.target = target;
+    public function addData(dataSeries:DataSeries):void {
     }
 
-    public function setId(id:int):void {
-      this.id = id;
-    }
   }
 }
diff --git a/src/flexchart/org/ovirt/charts/HostChart.as b/src/flexchart/org/ovirt/charts/HostChart.as
new file mode 100644
index 0000000..ad46236
--- /dev/null
+++ b/src/flexchart/org/ovirt/charts/HostChart.as
@@ -0,0 +1,177 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+ Written by Steve Linabery <slinabery 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.
+*/
+
+package org.ovirt.charts {
+  import flash.events.Event;
+  import flash.events.MouseEvent;
+  import mx.collections.ArrayCollection;
+  import mx.containers.Box;
+  import mx.containers.HBox;
+  import mx.containers.VBox;
+  import mx.containers.Canvas;
+  import mx.controls.TextInput;
+  import mx.controls.DateField;
+  import mx.controls.Button;
+  import mx.controls.PopUpMenuButton;
+  import mx.controls.Text;
+  import mx.events.MenuEvent;
+  import mx.formatters.DateFormatter;
+  import org.ovirt.data.*;
+  import org.ovirt.elements.*;
+  import org.ovirt.Constants;
+  import org.ovirt.ApplicationBus;
+  import mx.core.ScrollPolicy;
+
+  public class HostChart extends Chart {
+
+    private var yScale:Scale;
+    private var chartFrame:HBox;
+    private var chartArea:Canvas;
+    private var XAxisLabelArea:Canvas;
+
+    /*
+      Constructors
+    */
+    public function HostChart(container:Box) {
+      super(container,null);
+    }
+
+    /*
+      Overriden functions
+    */
+    override protected function initializeDataSource():void {
+      dataSource = new HostChartDataSource(this);
+    }
+
+    override protected function setRequestAttributes(dto:FlexchartDataTransferObject):void {
+      dto.setId(id);
+      dto.setTarget(target);
+      dto.setStartTime(startTime);
+      dto.setResolution(resolution);
+      dto.setDataFunction(dataFunction);
+    }
+
+    override public function addData(dataSeries:DataSeries):void {
+      container.removeAllChildren();
+
+      var i:int;
+      var yLabelPercentWidth:int = 8;
+
+      chartFrame = new HBox();
+      chartFrame.percentHeight = 80;
+      chartFrame.percentWidth = 100;
+      chartFrame.setVisible(true);
+      chartFrame.setStyle("horizontalGap","1");
+
+      yScale = new Scale();
+      yScale.percentHeight = 100;
+      yScale.percentWidth = yLabelPercentWidth;
+      yScale.setVisible(true);
+
+      chartArea = new Canvas();
+      chartArea.percentHeight = 100;
+      chartArea.percentWidth = 100 - yLabelPercentWidth;
+      chartArea.setStyle("backgroundColor","0xbbccdd");
+
+      chartArea.verticalScrollPolicy = ScrollPolicy.OFF
+
+      chartFrame.addChild(yScale);
+      chartFrame.addChild(chartArea);
+      this.container.addChild(chartFrame);
+
+      XAxisLabelArea = new Canvas();
+      XAxisLabelArea.height = Constants.labelHeight;
+      XAxisLabelArea.minHeight = Constants.labelHeight;
+      XAxisLabelArea.percentWidth = 100;
+      this.container.addChild(XAxisLabelArea);
+
+      try {
+        var dataPoints:Array = dataSeries.getDataPoints();
+        var size:int = dataPoints.length;
+        if (size == 0) {
+          throw new Error("No data points in range");
+        }
+
+        var maxValue:Number = dataSeries.getMaxValue();
+        var scale:Number = maxValue;
+        yScale.setMax(maxValue);
+        //avoid divide by zero
+        if (scale == 0) {
+          scale = 1;
+        }
+
+	var calculatedWidth:Number = Constants.width * (chartArea.percentWidth / 100.0) ;
+
+        //the distance between left edges of adjacent bars
+        var gridWidth:Number = Math.floor(calculatedWidth / size);
+
+        //the width of each SingleBar (does not including padding between bars)
+        var barWidth:Number = gridWidth - Constants.barSpacing;
+
+        //due to the discrete number of pixels, there may be space at the
+        //right side of the graph that needs to be made up by padding
+        //bars here and there
+	var shortfall:Number = calculatedWidth - (gridWidth * size);
+	var makeup:Number = Math.round(size / shortfall);
+	var madeup:Number = 0;
+
+        //variable to hold the x-coordinate of the next bar to be added to
+        //the chart
+	var currentBarPosition:int = 0;
+
+        //add the bars & labels to the chart
+        var labelCounter:int = 0;
+        for (i = 0; i < size; i++) {
+
+          var dataPoint:DataPoint = dataPoints[i] as DataPoint;
+
+          var bar:SingleBar = new SingleBar(dataPoint,scale);
+          chartArea.addChild(bar);
+          bar.width = barWidth;
+	  bar.x = currentBarPosition;
+          if (makeup > 0 && i % makeup == 0 && madeup < shortfall) {
+            bar.width = bar.width + 1;
+            madeup++;
+          }
+
+          //if there aren't many bars, make them thinner.
+          if (size < 4) {
+            var tempWidth:Number = bar.width;
+            var tempX:Number = bar.x;
+
+            bar.width = bar.width * .8;
+            bar.x = tempX + tempWidth * .1;
+          }
+
+
+          var label:XAxisLabel =
+            new XAxisLabel(dataPoint.getNodeName());
+	  label.setCenter(bar.x + bar.width / 2);
+          label.setVisible(true);
+          label.y = 6;
+          XAxisLabelArea.addChild(label);
+          currentBarPosition += (bar.width + Constants.barSpacing);
+        }
+      } catch (e:Error) {
+        trace(e.getStackTrace())
+      }
+    }
+  }
+}
diff --git a/src/flexchart/org/ovirt/data/BarChartDataSource.as b/src/flexchart/org/ovirt/data/BarChartDataSource.as
new file mode 100644
index 0000000..69e12b1
--- /dev/null
+++ b/src/flexchart/org/ovirt/data/BarChartDataSource.as
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+ Written by Steve Linabery <slinabery 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.
+*/
+
+package org.ovirt.data {
+
+  import org.ovirt.charts.Chart;
+
+  public class BarChartDataSource extends DataSource {
+
+    public function BarChartDataSource(chart:Chart) {
+      super(chart);
+    }
+
+    override protected function getUrl(dto:FlexchartDataTransferObject):String {
+      var answer:String = "/ovirt/graph/flexchart_data/" + dto.getId() +
+        "/" + dto.getTarget() +
+        "/" + dto.getStartTime() +
+        "/" + dto.getEndTime() +
+	"/" + dto.getDataFunction();
+      return answer;
+    }
+
+  }
+
+}
diff --git a/src/flexchart/org/ovirt/data/DataPoint.as b/src/flexchart/org/ovirt/data/DataPoint.as
index 5d59de9..8b846e9 100644
--- a/src/flexchart/org/ovirt/data/DataPoint.as
+++ b/src/flexchart/org/ovirt/data/DataPoint.as
@@ -25,12 +25,17 @@ package org.ovirt.data {
     private var timestamp:Date;
     private var value:Number;
     private var description:String;
+    private var resolution:int;
+    private var nodeName:String;
 
     public function DataPoint (timestamp:Date, value:Number,
-                               description:String) {
+                               description:String, resolution:int,
+			       nodeName:String) {
       this.timestamp = timestamp;
       this.value = value;
       this.description = description;
+      this.resolution = resolution;
+      this.nodeName = nodeName;
     }
 
     public function getTimestamp():Date {
@@ -44,5 +49,14 @@ package org.ovirt.data {
     public function getDescription():String {
       return description;
     }
+
+    public function getResolution():int {
+      return resolution;
+    }
+
+    public function getNodeName():String {
+      return nodeName;
+    }
+
   }
 }
diff --git a/src/flexchart/org/ovirt/data/DataSeries.as b/src/flexchart/org/ovirt/data/DataSeries.as
index 709ceea..21db100 100644
--- a/src/flexchart/org/ovirt/data/DataSeries.as
+++ b/src/flexchart/org/ovirt/data/DataSeries.as
@@ -35,6 +35,8 @@ package org.ovirt.data {
       this.description = object["description"] as String;
       dataPoints = new Array();
       var inDataPoints:Array = object["vectors"] as Array;
+      var resolution:Number = object["resolution"] as Number;
+
       for (var i:int = 0; i < inDataPoints.length; i++) {
         var value:Number = 0;
         var valuea:Number = (inDataPoints[i] as Array)[1] as Number;
@@ -42,11 +44,17 @@ package org.ovirt.data {
           value = (inDataPoints[i] as Array)[1] as Number;
         }
         var seconds:Number = new Number((inDataPoints[i] as Array)[0]) * 1000;
+	var nodeName:String = (inDataPoints[i] as Array)[2] as String;
+
         dataPoints.push(new DataPoint(new Date(seconds),
                                       value,
-                                      description));
+                                      description,
+                                      resolution,
+				      nodeName));
+
       }
       maxValue = object["max_value"] as Number;
+
     }
 
     public function getDataPoints():Array {
@@ -56,5 +64,6 @@ package org.ovirt.data {
     public function getMaxValue():Number {
       return maxValue;
     }
+
   }
 }
diff --git a/src/flexchart/org/ovirt/data/DataSource.as b/src/flexchart/org/ovirt/data/DataSource.as
new file mode 100644
index 0000000..4fdd8e8
--- /dev/null
+++ b/src/flexchart/org/ovirt/data/DataSource.as
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2008 Red Hat, Inc.
+ Written by Steve Linabery <slinabery 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.
+*/
+
+package org.ovirt.data {
+
+  import com.adobe.serialization.json.JSON;
+  import flash.events.Event;
+  import flash.events.IOErrorEvent;
+  import flash.net.URLLoader;
+  import flash.net.URLRequest;
+  import org.ovirt.charts.Chart;
+  import org.ovirt.data.DataSeries;
+
+  public class DataSource {
+
+    private var chart:Chart;
+
+    public function DataSource(chart:Chart) {
+      this.chart = chart;
+    }
+
+    public function retrieveData(dto:FlexchartDataTransferObject):void {
+      var loader:URLLoader = new URLLoader();
+      loader.addEventListener(IOErrorEvent.IO_ERROR, this.ioError);
+      loader.addEventListener(Event.COMPLETE, dataLoaded);
+      var request:URLRequest = new URLRequest(getUrl(dto));
+      loader.load(request);
+    }
+
+    private function dataLoaded(event:Event):void {
+      var loader:URLLoader = URLLoader(event.target);
+      var object:Object = JSON.decode(loader.data);
+      var series:DataSeries = new DataSeries(object);
+      chart.addData(series);
+    }
+
+    private function ioError( e:IOErrorEvent ):void {
+      trace("ioError");
+      //FIXME:
+      //do something useful with this error
+    }
+
+    //subclasses should override
+    protected function getUrl(dto:FlexchartDataTransferObject):String {
+      return null;
+    }
+
+  }
+}
diff --git a/src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as b/src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as
new file mode 100644
index 0000000..8534501
--- /dev/null
+++ b/src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+ Written by Steve Linabery <slinabery 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.
+*/
+
+package org.ovirt.data {
+
+  public class FlexchartDataTransferObject {
+
+    private var startTime:int;
+    private var endTime:int;
+    private var id:int;
+    private var target:String;
+    private var resolution:int;
+    private var averageLength:int;
+    private var dataFunction:String;
+
+    public function setStartTime(startTime:int):void {
+      this.startTime = startTime;
+    }
+
+    public function getStartTime():int {
+      return startTime;
+    }
+
+    public function setEndTime(endTime:int):void {
+      this.endTime = endTime;
+    }
+
+    public function getEndTime():int {
+      return endTime;
+    }
+
+    public function setId(id:int):void {
+      this.id = id;
+    }
+
+    public function getId():int {
+      return id;
+    }
+
+    public function setTarget(target:String):void {
+      this.target = target;
+    }
+
+    public function getTarget():String {
+      return target;
+    }
+
+    public function setResolution(resolution:int):void {
+      this.resolution = resolution;
+    }
+
+    public function getResolution():int {
+      return resolution;
+    }
+
+    public function setAverageLength(averageLength:int):void {
+      this.averageLength = averageLength;
+    }
+
+    public function getAverageLength():int {
+      return averageLength;
+    }
+
+    public function setDataFunction(dataFunction:String):void {
+      this.dataFunction = dataFunction;
+    }
+
+    public function getDataFunction():String {
+      return dataFunction;
+    }
+
+  }
+}
diff --git a/src/flexchart/org/ovirt/data/HostChartDataSource.as b/src/flexchart/org/ovirt/data/HostChartDataSource.as
new file mode 100644
index 0000000..7b36aec
--- /dev/null
+++ b/src/flexchart/org/ovirt/data/HostChartDataSource.as
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+ Written by Steve Linabery <slinabery 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.
+*/
+
+package org.ovirt.data {
+
+  import org.ovirt.charts.Chart;
+
+  public class HostChartDataSource extends DataSource {
+
+    public function HostChartDataSource(chart:Chart) {
+      super(chart);
+    }
+
+    override protected function getUrl(dto:FlexchartDataTransferObject):String {
+      var answer:String = "/ovirt/graph/host_chart_data/" + dto.getId() +
+        "/" + dto.getTarget() +
+        "/" + dto.getStartTime() +
+        "/" + dto.getResolution() +
+	"/" + dto.getDataFunction();
+      return answer;
+    }
+
+  }
+
+}
diff --git a/src/flexchart/org/ovirt/elements/Scale.as b/src/flexchart/org/ovirt/elements/Scale.as
new file mode 100644
index 0000000..0238172
--- /dev/null
+++ b/src/flexchart/org/ovirt/elements/Scale.as
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+ Written by Steve Linabery <slinabery 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.
+*/
+
+//an object that calculates/displays tickmarks for axis scales.
+
+package org.ovirt.elements {
+  import mx.containers.Box;
+  import flash.events.Event;
+  import mx.events.FlexEvent;
+  import mx.events.ResizeEvent;
+  import mx.controls.Label;
+
+  public class Scale extends Box {
+
+    private var max:Number;
+    private var maxLabel:Label;
+    private var midLabel:Label;
+
+    public function Scale() {
+      super();
+      opaqueBackground = 0xffffff;
+      max = 0;
+      addEventListener(ResizeEvent.RESIZE,myResize);
+      addEventListener(FlexEvent.CREATION_COMPLETE,myResize);
+      addEventListener(Event.RENDER,myResize);
+      addEventListener(FlexEvent.INITIALIZE,myResize);
+      addEventListener(FlexEvent.UPDATE_COMPLETE,myResize);
+
+      maxLabel = new Label();
+      this.addChild(maxLabel);
+      maxLabel.setVisible(true);
+
+      midLabel = new Label();
+      this.addChild(midLabel);
+      midLabel.setVisible(true);
+
+
+    }
+
+    public function setMax(max:Number):void {
+      this.max = max;
+      maxLabel.text = max.toExponential(1);
+      midLabel.text = (max / 2.0).toExponential(1);
+    }
+
+    private function myResize(event:Event):void {
+
+      this.height = parent.height * .90 * -1;
+      this.y = parent.height;
+      graphics.clear();
+      graphics.beginFill(0x000000);
+      graphics.lineStyle(1);
+
+      graphics.moveTo(width - 1,-1);
+      graphics.lineTo(width - 1,height);
+
+
+      graphics.moveTo(width - 4,height);
+      graphics.lineTo(width - 1,height);
+
+      graphics.moveTo(width - 4,height / 2);
+      graphics.lineTo(width - 1,height / 2);
+      graphics.endFill();
+
+      maxLabel.y = height;
+      midLabel.y = height / 2;
+
+    }
+  }
+}
diff --git a/src/flexchart/org/ovirt/elements/SingleBar.as b/src/flexchart/org/ovirt/elements/SingleBar.as
index e7caf93..40ae651 100644
--- a/src/flexchart/org/ovirt/elements/SingleBar.as
+++ b/src/flexchart/org/ovirt/elements/SingleBar.as
@@ -63,7 +63,6 @@ package org.ovirt.elements {
 
 
     private function myResize(event:Event):void {
-       trace(event.type);
        this.height = (dataPoint.getValue() / scale) * parent.height * .9 * -1;
        this.y = parent.height;
     }
@@ -90,5 +89,13 @@ package org.ovirt.elements {
     private function destroyTip(event:Event):void {
       ToolTipManager.destroyToolTip(tip);
     }
+
+    public function getResolution():Number {
+      return dataPoint.getResolution();
+    }
+
+    public function getStartTime():Number {
+      return dataPoint.getTimestamp().getTime();
+    }
   }
 }
-- 
1.6.0.6




More information about the ovirt-devel mailing list