[Ovirt-devel] [PATCH server] Add qpid reconnect and logger to dbomatic
Ian Main
imain at redhat.com
Wed Feb 18 00:03:37 UTC 2009
This patch does the same as we did for taskomatic to dbomatic, making it
reconnect to qpidd on loss of connection as well as using the Logger
class to do logging.
This update changes the logging format and adds the qpidd connection
check to the main loop.
Signed-off-by: Ian Main <imain at redhat.com>
---
src/db-omatic/db_omatic.rb | 162 +++++++++++++++++++++++++++++---------------
1 files changed, 106 insertions(+), 56 deletions(-)
diff --git a/src/db-omatic/db_omatic.rb b/src/db-omatic/db_omatic.rb
index 845a714..f620a47 100755
--- a/src/db-omatic/db_omatic.rb
+++ b/src/db-omatic/db_omatic.rb
@@ -8,9 +8,26 @@ require 'monitor'
require 'dutils'
require 'daemons'
require 'optparse'
+require 'logger'
+
include Daemonize
+# This sad and pathetic readjustment to ruby logger class is
+# required to fix the formatting because rails does the same
+# thing but overrides it to just the message.
+#
+# See eg: http://osdir.com/ml/lang.ruby.rails.core/2007-01/msg00082.html
+#
+class Logger
+ def format_message(severity, timestamp, progname, msg)
+ "#{severity} #{timestamp} (#{$$}) #{msg}\n"
+ end
+end
+
+$logfile = '/var/log/ovirt-server/db-omatic.log'
+
+
class DbOmatic < Qpid::Qmf::Console
# Use monitor mixin for mutual exclusion around checks to heartbeats
@@ -22,18 +39,92 @@ class DbOmatic < Qpid::Qmf::Console
super()
@cached_objects = {}
@heartbeats = {}
+ @broker = nil
+ @session = Qpid::Qmf::Session.new()
+
+ do_daemon = true
+
+ opts = OptionParser.new do |opts|
+ opts.on("-h", "--help", "Print help message") do
+ puts opts
+ exit
+ end
+ opts.on("-n", "--nodaemon", "Run interactively (useful for debugging)") do |n|
+ do_daemon = false
+ end
+ end
+ begin
+ opts.parse!(ARGV)
+ rescue OptionParser::InvalidOption
+ puts opts
+ exit
+ end
+
+ if do_daemon
+ # XXX: This gets around a problem with paths for the database stuff.
+ # Normally daemonize would chdir to / but the paths for the database
+ # stuff are relative so it breaks it.. It's either this or rearrange
+ # things so the db stuff is included after daemonizing.
+ pwd = Dir.pwd
+ daemonize
+ Dir.chdir(pwd)
+ @logger = Logger.new($logfile)
+ else
+ @logger = Logger.new(STDERR)
+ end
+ @logger.info "dbomatic started."
+
+ get_credentials('qpidd')
database_connect
+ qpid_ensure_connected
+
end
- def log(s)
- puts "#{Time.now}: #{s}"
+
+ # FIXME: This should move into a library but I think we'll need
+ # to make some sort of singleton class for these applications so we can
+ # share the logger and qpid variables etc. It's getting to show itself
+ # as a problem but I don't want to go crazy right now as we're supposed
+ # to be in freeze. :)
+ def qpid_ensure_connected()
+
+ return if @broker and @broker.connected?
+
+ sleepy = 2
+
+ while true do
+ begin
+ server, port = get_srv('qpidd', 'tcp')
+ raise "Unable to determine qpid server from DNS SRV record" if not server
+
+ @broker = @session.add_broker("amqp://#{server}:#{port}", :mechanism => 'GSSAPI')
+
+ # Connection succeeded, go about our business.
+ @logger.info "Connected to amqp://#{server}:#{port}"
+ return
+
+ rescue Exception => msg
+ @logger.error "Error connecting to qpidd: #{msg}"
+ @logger.error msg.backtrace
+ end
+ sleep(sleepy)
+ sleepy *= 2
+ sleepy = 120 if sleepy > 120
+
+ begin
+ # Could also be a credentials problem? Try to get them again..
+ get_credentials('qpidd')
+ rescue Exception => msg
+ @logger.error "Error getting qpidd credentials: #{msg}"
+ end
+ end
end
def update_domain_state(domain, state_override = nil)
vm = Vm.find(:first, :conditions => [ "uuid = ?", domain['uuid'] ])
if vm == nil
- log "VM Not found in database, must be created by user; ignoring."
+ @logger.info "VM Not found in database, must be created by user; ignoring."
#XXX: I mark this one as 'synced' here even though we couldn't sync
#it because there really should be a db entry for every vm unless it
@@ -67,7 +158,7 @@ class DbOmatic < Qpid::Qmf::Console
end
end
- log "Updating VM #{domain['name']} to state #{state}"
+ @logger.info "Updating VM #{domain['name']} to state #{state}"
vm.state = state
vm.save
@@ -77,7 +168,7 @@ class DbOmatic < Qpid::Qmf::Console
def update_host_state(host_info, state)
db_host = Host.find(:first, :conditions => [ "hostname = ?", host_info['hostname'] ])
if db_host
- log "Marking host #{host_info['hostname']} as state #{state}."
+ @logger.info "Marking host #{host_info['hostname']} as state #{state}."
db_host.state = state
db_host.hypervisor_type = host_info['hypervisorType']
db_host.arch = host_info['model']
@@ -92,7 +183,7 @@ class DbOmatic < Qpid::Qmf::Console
host_info[:synced] = true
else
# FIXME: This would be a newly registered host. We could put it in the database.
- log "Unknown host, probably not registered yet??"
+ @logger.info "Unknown host, probably not registered yet??"
# XXX: So it turns out this can happen as there is a race condition on bootup
# where the registration takes longer than libvirt-qpid does to relay information.
# So in this case, we mark this object as not synced so it will get resynced
@@ -124,7 +215,7 @@ class DbOmatic < Qpid::Qmf::Console
values[:class_type] = obj.klass_key[1]
values[:timed_out] = false
values[:synced] = false
- log "New object type #{type}"
+ @logger.info "New object type #{type}"
new_object = true
end
@@ -134,7 +225,7 @@ class DbOmatic < Qpid::Qmf::Console
obj.properties.each do |key, newval|
if values[key.to_s] != newval
values[key.to_s] = newval
- #log "new value for property #{key} : #{newval}"
+ #puts "new value for property #{key} : #{newval}"
if type == "domain" and key.to_s == "state"
domain_state_change = true
end
@@ -173,7 +264,7 @@ class DbOmatic < Qpid::Qmf::Console
obj.statistics.each do |key, newval|
if values[key.to_s] != newval
values[key.to_s] = newval
- #log "new value for statistic #{key} : #{newval}"
+ #puts "new value for statistic #{key} : #{newval}"
end
end
end
@@ -200,7 +291,7 @@ class DbOmatic < Qpid::Qmf::Console
@cached_objects[objkey][:agent_bank] == agent.agent_bank
values = @cached_objects[objkey]
- log "Marking object of type #{values[:class_type]} as timed out."
+ @logger.info "Marking object of type #{values[:class_type]} as timed out."
if values[:timed_out] == false
if values[:class_type] == 'node'
update_host_state(values, Host::STATE_UNAVAILABLE)
@@ -223,7 +314,7 @@ class DbOmatic < Qpid::Qmf::Console
values = @cached_objects[objkey]
if values[:timed_out] == true or values[:synced] == false
- log "Marking object of type #{values[:class_type]} as in service."
+ @logger.info "Marking object of type #{values[:class_type]} as in service."
if values[:class_type] == 'node'
update_host_state(values, Host::STATE_AVAILABLE)
elsif values[:class_type] == 'domain'
@@ -240,14 +331,14 @@ class DbOmatic < Qpid::Qmf::Console
def db_init_cleanup()
db_host = Host.find(:all)
db_host.each do |host|
- log "Marking host #{host.hostname} unavailable"
+ @logger.info "Marking host #{host.hostname} unavailable"
host.state = Host::STATE_UNAVAILABLE
host.save
end
db_vm = Vm.find(:all)
db_vm.each do |vm|
- log "Marking vm #{vm.description} as stopped."
+ @logger.info "Marking vm #{vm.description} as stopped."
vm.state = Vm::STATE_STOPPED
vm.save
end
@@ -260,6 +351,8 @@ class DbOmatic < Qpid::Qmf::Console
def check_heartbeats()
while true
sleep(5)
+
+ qpid_ensure_connected
synchronize do
# Get seconds from the epoch
@@ -287,53 +380,10 @@ class DbOmatic < Qpid::Qmf::Console
end
-$logfile = '/var/log/ovirt-server/db-omatic.log'
-
def main()
- do_daemon = true
-
- opts = OptionParser.new do |opts|
- opts.on("-h", "--help", "Print help message") do
- puts opts
- exit
- end
- opts.on("-n", "--nodaemon", "Run interactively (useful for debugging)") do |n|
- do_daemon = false
- end
- end
- begin
- opts.parse!(ARGV)
- rescue OptionParser::InvalidOption
- puts opts
- exit
- end
-
- if do_daemon
- # XXX: This gets around a problem with paths for the database stuff.
- # Normally daemonize would chdir to / but the paths for the database
- # stuff are relative so it breaks it.. It's either this or rearrange
- # things so the db stuff is included after daemonizing.
- pwd = Dir.pwd
- daemonize
- Dir.chdir(pwd)
-
- lf = open($logfile, 'a')
- $stdout = lf
- $stderr = lf
- puts "#{Time.now}: db_omatic started."
- end
-
- get_credentials('qpidd')
-
dbsync = DbOmatic.new()
- server, port = get_srv('qpidd', 'tcp')
- raise "Unable to determine qpid server from DNS SRV record" if not server
-
- s = Qpid::Qmf::Session.new(:console => dbsync, :rcv_events => false)
- b = s.add_broker("amqp://#{server}:#{port}", :mechanism => 'GSSAPI')
-
dbsync.db_init_cleanup()
# Call into mainloop..
--
1.6.0.6
More information about the ovirt-devel
mailing list