[Ovirt-devel] [PATCH server] (Legit) Add audit trl for hosts join/leaving hwpools w/Rails observer class

Steve Linabery slinabery at redhat.com
Fri Jan 9 01:50:53 UTC 2009


Modify graph_controller.rb to utilize new audit feature when generating data for flexchart
---
 src/app/controllers/graph_controller.rb    |   64 +++++++++++++++++++++++++--
 src/app/models/hardware_pool.rb            |    2 +-
 src/app/models/host.rb                     |    9 ++++
 src/app/models/host_observer.rb            |   47 ++++++++++++++++++++
 src/app/models/membership_audit_event.rb   |   26 +++++++++++
 src/app/models/pool.rb                     |    1 +
 src/config/environment.rb                  |    2 +-
 src/db/migrate/033_add_pool_audit_trail.rb |   44 +++++++++++++++++++
 8 files changed, 188 insertions(+), 7 deletions(-)
 create mode 100644 src/app/models/host_observer.rb
 create mode 100644 src/app/models/membership_audit_event.rb
 create mode 100644 src/db/migrate/033_add_pool_audit_trail.rb

diff --git a/src/app/controllers/graph_controller.rb b/src/app/controllers/graph_controller.rb
index ee9425f..e8eea7e 100644
--- a/src/app/controllers/graph_controller.rb
+++ b/src/app/controllers/graph_controller.rb
@@ -6,9 +6,9 @@ class GraphController < ApplicationController
   def flexchart_data
     @id = params[:id]
     target = params[:target]
-    startTime = params[:startTime].to_i
-    endTime = params[:endTime].to_i
-    duration = endTime - startTime
+    startTime = Time.at(params[:startTime].to_i)
+    endTime = Time.at(params[:endTime].to_i)
+    duration = endTime.to_i - startTime.to_i
 
     #the maximum number of data points we want in any chart
     maxPoints = 100
@@ -29,10 +29,30 @@ class GraphController < ApplicationController
     counter = DEV_KEY_COUNTERS[target]
 
     pool = Pool.find(@id)
-    hosts = pool.hosts
+    hosts = Host.find(:all,
+                      :include=> :membership_audit_events,
+                      :conditions => ['membership_audit_events.container_target_id = ?',pool])
+
     requestList = [ ]
     hosts.each{ |host|
-      requestList.push StatsRequest.new(host.hostname, devclass, 0, counter, startTime, duration, resolution, DataFunction::Peak)
+      eventsInRange = host.membership_audit_events.from_pool(pool,
+                                                             startTime,
+                                                             endTime)
+      priorAuditEvent = host.membership_audit_events.most_recent_prior_event_from_pool(pool,startTime)
+      timeRanges = get_ranges_from_event_list(eventsInRange,
+                                              priorAuditEvent,
+                                              startTime,
+                                              endTime)
+      timeRanges.each{ |range|
+        requestList.push StatsRequest.new(host.hostname,
+                                          devclass,
+                                          0,
+                                          counter,
+                                          range[0].to_i,
+                                          range[1].to_i - range[0].to_i,
+                                          resolution,
+                                          DataFunction::Peak)
+      }
     }
     statsList = getAggregateStatsData?(requestList)
 
@@ -51,6 +71,40 @@ class GraphController < ApplicationController
     render :json => graph
   end
 
+  def get_ranges_from_event_list(list, priorEvent, startTime, endTime)
+
+    results = Array.new
+    range = [startTime,endTime]
+
+    joined = false
+    if priorEvent
+      if priorEvent.action == MembershipAuditEvent::JOIN
+        joined = true
+      end
+    end
+
+    list.each_with_index { |event,index|
+      if event.action == MembershipAuditEvent::JOIN
+        joined = true
+        range[0] = event.created_at
+      else
+        range[0] = startTime unless joined
+        joined = false
+        range[1] = event.created_at
+        results.push Array.new(range)
+        range = [startTime,endTime]
+      end
+    }
+
+    if joined
+      range[1] = endTime
+      results.push Array.new(range)
+    end
+
+    results
+  end
+
+
 
   # generate layout for availability bar graphs
   def availability_graph
diff --git a/src/app/models/hardware_pool.rb b/src/app/models/hardware_pool.rb
index d39d8e7..b72d485 100644
--- a/src/app/models/hardware_pool.rb
+++ b/src/app/models/hardware_pool.rb
@@ -54,7 +54,7 @@ class HardwarePool < Pool
     hosts = Host.find(:all, :conditions => "id in (#{host_ids.join(', ')})")
     transaction do
       hosts.each do |host|
-        host.hardware_pool_id = target_pool_id
+        host.hardware_pool = HardwarePool.find(target_pool_id)
         host.save!
       end
     end
diff --git a/src/app/models/host.rb b/src/app/models/host.rb
index 640782d..813bc1d 100644
--- a/src/app/models/host.rb
+++ b/src/app/models/host.rb
@@ -23,6 +23,15 @@ class Host < ActiveRecord::Base
   belongs_to :hardware_pool
   belongs_to :bonding_type
 
+  has_many :membership_audit_events, :as => :member_target, :dependent => :destroy, :order => "created_at ASC" do
+    def from_pool(pool,startTime,endTime)
+      find(:all, :conditions=> ['container_target_id = ? and created_at between ? and ?',pool,startTime,endTime])
+    end
+    def most_recent_prior_event_from_pool(pool,startTime)
+      find(:last, :conditions=> ['container_target_id = ? and created_at < ?',pool,startTime])
+    end
+  end
+
   has_many :cpus,     :dependent => :destroy
   has_many :nics,     :dependent => :destroy
   has_many :bondings, :dependent => :destroy
diff --git a/src/app/models/host_observer.rb b/src/app/models/host_observer.rb
new file mode 100644
index 0000000..df5efa1
--- /dev/null
+++ b/src/app/models/host_observer.rb
@@ -0,0 +1,47 @@
+#
+# 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.
+
+class HostObserver < ActiveRecord::Observer
+
+  def after_create(a_host)
+    join = MembershipAuditEvent.new({ :member_target => a_host,
+                                      :container_target => a_host.hardware_pool,
+                                      :action => MembershipAuditEvent::JOIN })
+    join.save!
+  end
+
+  def before_update(a_host)
+    if a_host.changed?
+      change = a_host.changes['hardware_pool_id']
+      if change
+        leave = MembershipAuditEvent.new({ :member_target => a_host,
+                                           :container_target => HardwarePool.find(change[0]),
+                                           :action => MembershipAuditEvent::LEAVE })
+        leave.save!
+
+        join = MembershipAuditEvent.new({ :member_target => a_host,
+                                          :container_target => HardwarePool.find(change[1]),
+                                          :action => MembershipAuditEvent::JOIN })
+        join.save!
+      end
+    end
+  end
+end
+
+HostObserver.instance
diff --git a/src/app/models/membership_audit_event.rb b/src/app/models/membership_audit_event.rb
new file mode 100644
index 0000000..b36cbee
--- /dev/null
+++ b/src/app/models/membership_audit_event.rb
@@ -0,0 +1,26 @@
+#
+# 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.
+
+class MembershipAuditEvent < ActiveRecord::Base
+  belongs_to :container_target,  :polymorphic => true
+  belongs_to :member_target,     :polymorphic => true
+
+  JOIN = "join"
+  LEAVE = "leave"
+end
diff --git a/src/app/models/pool.rb b/src/app/models/pool.rb
index 7034e79..614325a 100644
--- a/src/app/models/pool.rb
+++ b/src/app/models/pool.rb
@@ -20,6 +20,7 @@
 class Pool < ActiveRecord::Base
   acts_as_nested_set
 
+  has_many :membership_audit_events, :as => :container_target, :dependent => :destroy
   # moved associations here so that nested set :include directives work
   # TODO: find a way to put this back into vm_resource_pool.rb
   has_many :vms, :dependent => :nullify, :order => "id ASC", :foreign_key => :vm_resource_pool_id
diff --git a/src/config/environment.rb b/src/config/environment.rb
index 53edfad..66cae90 100644
--- a/src/config/environment.rb
+++ b/src/config/environment.rb
@@ -82,7 +82,7 @@ Rails::Initializer.run do |config|
 
   # Activate observers that should always be running
   # config.active_record.observers = :cacher, :garbage_collector
-
+  config.active_record.observers = :host_observer
 end
 
 # Add new inflection rules using the following format
diff --git a/src/db/migrate/033_add_pool_audit_trail.rb b/src/db/migrate/033_add_pool_audit_trail.rb
new file mode 100644
index 0000000..d4b4338
--- /dev/null
+++ b/src/db/migrate/033_add_pool_audit_trail.rb
@@ -0,0 +1,44 @@
+#
+# 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.
+
+class AddPoolAuditTrail < ActiveRecord::Migration
+  def self.up
+    create_table :membership_audit_events do |t|
+      t.timestamp :created_at
+      t.string :action
+      t.integer :container_target_id
+      t.string :container_target_type
+      t.integer :member_target_id
+      t.string :member_target_type
+      t.integer :lock_version, :default => 0
+    end
+
+    Host.transaction do
+      Host.find(:all).each do |host|
+
+        if (! host.membership_audit_events)
+          event = MembershipAuditEvent.new(:action => MembershipAuditEvent::JOIN,
+                                           :container_target => host.hardware_pool,
+                                           :member_target => host)
+          event.save!
+        end
+      end
+    end
+  end
+end
-- 
1.6.0.6




More information about the ovirt-devel mailing list