Report abuse

lib/puppet/reports/logcache.rb


			
# $Id:$
require 'puppet'

Puppet::Reports.register_report(:logcache) do
    Puppet.settings.use(:reporting)

    desc "Record the last 1000 lines of log messages per server."

    def mkclientdir(client, dir)
        config = Puppet::Util::Settings.new
        config.setdefaults("reportclient-#{client}",
            "clientdir-#{client}" => { :default => dir,
                :mode => 0750,
                :desc => "Client dir for %s" % client,
                :owner => Puppet[:user],
                :group => Puppet[:group]
            }
        )

        config.use("reportclient-#{client}")
    end

    def getconfig
        # Create a new config object and read in configurations related to
        # reports
        config = Puppet::Util::Settings.new
        config.setdefaults(:reporting,
            :reportdir => {:default => "/var/lib/puppet/reports",
                :mode => 0750,
                :owner => "$user",
                :group => "$group",
                :desc => "The directory in which to store reports
                    received from the client.  Each client gets a separate
                    subdirectory."},
            :reportlocation => ["file",
                "Indicate if reports should be stored to file or database."],
            :reportdbserver => ["localhost",
                "Database server that hosts the reports database."],
            :reportdbuser => ["puppetmaster",
                "Username to connect to reports database with."],
            :reportdbpw => ["dbpassword",
                "Password to connect to reports database with."],
            :reportdb => ["puppetreports",
                "Database name of the reports database."]
        )

        config.parse(Puppet[:reportconfig])

        return config
    end

    def tablegood(db)
        isgood = false
        begin
            query = db.query("SHOW TABLES LIKE 'logcache'")
            if query.num_rows == 0 then
                db.query("CREATE TABLE `logcache` (
                    `pid` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
                    `node` VARCHAR( 255 ) NOT NULL COMMENT 'FQDN of node',
                    `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                    `logline` VARCHAR( 4096 ) NOT NULL COMMENT 'Log lines',
                    INDEX ( `node` ));")
                Puppet.warning "Created table 'logcache' in reports database"
                isgood = true
            elsif query.num_rows == 1 then
                isgood = true
            else
                Puppet.warning "Found more than one logcache table???"
                isgood = false
            end
        rescue
            Puppet.warning "Had problems checking for logcache table"
            isgood = false
        end
        return isgood
    end

    def writefile(config)
        # We don't want any tracking back in the fs.  Unlikely, but there
        # you go.
        client = self.host.gsub("..",".")

        # Create the directory for reports if it doesn't exist
        dir = File.join(Puppet[:reportdir], client)
        unless FileTest.exists?(dir)
            mkclientdir(client, dir)
        end

        file = File.join(dir, "logcache")

        # Read in the exist log cache
        if File.exists?(file)
            cache = IO.readlines(file)
            cache.collect! { |line| line.chomp }
        else
            cache = []
        end

        # Collect all the log messages
        messages = self.logs.collect { |m| m.to_report }
        cache.concat(messages)
        cache = cache.last(1000)

        begin
            File.open(file, "w", 0640) do |f|
                f.puts cache.join("\n")
            end
        rescue => detail
            if Puppet[:trace]
                puts detail.backtrace
            end
            Puppet.warning "Could not write report for %s at %s: %s" %
                [client, file, detail]
        end
    end
    def writedb(config)
        # We don't want any tracking back in the fs.  Unlikely, but there
        # you go.
        client = self.host.gsub("..",".")

        db = Mysql.connect(config[:reportdbserver],
            config[:reportdbuser],
            config[:reportdbpw], config[:reportdb])

        if tablegood(db) then
            messages = self.logs.collect { |m| m.to_report }
            messages.each { |line|
                cleanline = Mysql.escape_string(line)
                db.query("INSERT INTO logcache(node,logline) VALUES(\'%s\', \'%s\')" %
                    [client, cleanline])
            }
            Puppet.debug "Stored logcache report to database for %s" % client
        else
            Puppet.warning "Had problems with logcache table"
        end
        db.close
    end

    def process
        config = getconfig
        now = Time.now.getlocal

        if config[:reportlocation] == "file" then
            writefile(config)
        elsif config[:reportlocation] == "mysql" then
            writedb(config)
        end

        # Only testing cares about the return value
        return
    end
end