summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--files/munin/mysql_size_all179
-rw-r--r--lib/puppet/provider/mysql_grant/mysql.rb107
-rw-r--r--lib/puppet/type/mysql_grant.rb10
-rw-r--r--manifests/client/perl.pp7
-rw-r--r--manifests/client/perl/debian.pp6
-rw-r--r--manifests/server/base.pp2
-rw-r--r--manifests/server/munin/base.pp20
-rw-r--r--manifests/server/munin/debian.pp17
-rw-r--r--manifests/server/nagios.pp2
9 files changed, 328 insertions, 22 deletions
diff --git a/files/munin/mysql_size_all b/files/munin/mysql_size_all
new file mode 100644
index 0000000..f5954ad
--- /dev/null
+++ b/files/munin/mysql_size_all
@@ -0,0 +1,179 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2007 - Rodolphe Quiedeville <rodolphe@quiedeville.org>
+# Copyright (C) 2003-2004 - Andreas Buer
+#
+# 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 dated June,
+# 1991.
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Log$
+# Revision 1.1 2007/01/17 10:41:01 rodo
+# Change incorrect family
+#
+# Revision 1.0 2007/01/16 15:57:01 rodo
+# Created by Rodolphe Quiedeville
+#
+# Parameters:
+#
+# config
+# autoconf
+#
+# Configuration variables
+#
+# mysqlopts - Options to pass to mysql
+# mysqladmin - Override location of mysqladmin
+#
+#%# family=manual
+#%# capabilities=autoconf
+
+use strict;
+
+# unless ($0 =~ /mysql_size(?:_([^_]+)|)_(.+)\s*$/)
+# {
+# die "Could not parse name $0.\n";
+# }
+# my $db = $2;
+
+my $COMMAND;
+my $MYSQLADMIN = $ENV{mysqladmin} || "mysql";
+
+my %WANTED = ( "Index" => "index",
+ "Datas" => "datas",
+ );
+
+my $arg = shift();
+
+if ($arg eq 'config') {
+ print_config();
+ exit();
+} elsif ($arg eq 'autoconf') {
+ unless (test_service() ) {
+ print "yes\n";
+ } else {
+ print "no\n";
+ }
+ exit;
+}
+
+sub getDBList;
+foreach my $db (getDBList()) {
+
+ my $datas = 0;
+ my $indexes = 0;
+ my (@infos,$info,$i_data,$i_index);
+
+ $COMMAND = "$MYSQLADMIN $ENV{mysqlopts} $db -e 'show table status;' | head -n 1";
+
+ open(SERVICE, "$COMMAND |")
+ or die("Coult not execute '$COMMAND': $!");
+
+ while (<SERVICE>) {
+ (@infos) = split;
+ }
+ close(SERVICE);
+
+ my $i = 0;
+ foreach $info (@infos) {
+ $i++;
+ if ($info eq 'Data_length') {
+ $i_data = $i;
+ next;
+ }
+ if ($info eq 'Index_length') {
+ $i_index = $i;
+ last;
+ }
+ }
+ my $total_size = 0;
+ if ($i_data>0 && $i_index>0) {
+ $COMMAND = "$MYSQLADMIN $ENV{mysqlopts} $db -e 'show table status;' | cut -f $i_data,$i_index | grep -v leng";
+
+ open(SERVICE, "$COMMAND |")
+ or die("Coult not execute '$COMMAND': $!");
+
+ while (<SERVICE>) {
+ (m/(\d+).*?(\d+(?:\.\d+)?)/);
+ $datas += $1;
+ $indexes += $2;
+ }
+ close(SERVICE);
+
+ $total_size = $datas+$indexes;
+ }
+ print("$db.value $total_size\n");
+# print("datas.value $datas\n");
+# print("index.value $indexes\n");
+}
+
+
+sub print_config {
+
+ my $num = 0;
+
+ my @dbs = getDBList;
+
+ print("graph_title MySQL databases size\n");
+ print ('graph_args --base 1024 -l 0
+graph_vlabel bytes
+graph_category mysql
+graph_info Plugin available at <a href="http://rodolphe.quiedeville.org/hack/munin/">http://rodolphe.quiedeville.org/hack/munin/</a>
+');
+
+ for my $db (@dbs) {
+ my $title = "$db";
+ print("$title.label ${title}\n",
+ "$title.min 0\n",
+ "$title.type GAUGE\n",
+ "$title.draw ", ($num) ? "STACK" : "AREA" , "\n",
+ );
+ $num++;
+ }
+}
+
+
+sub test_service {
+
+ my $return = 1;
+
+ system ("$MYSQLADMIN --version >/dev/null 2>/dev/null");
+ if ($? == 0)
+ {
+ system ("$COMMAND >/dev/null 2>/dev/null");
+ if ($? == 0)
+ {
+ print "yes\n";
+ $return = 0;
+ }
+ else
+ {
+ print "no (could not connect to mysql)\n";
+ }
+ }
+ else
+ {
+ print "no (mysqladmin not found)\n";
+ }
+ exit $return;
+}
+
+sub getDBList {
+ my @dbs;
+ foreach my $f (glob("/var/lib/mysql/*")) {
+ if (-d $f) {
+ $f =~ s!.*/!!;
+ @dbs[$#dbs+1]=$f };
+ }
+ return @dbs;
+}
+
diff --git a/lib/puppet/provider/mysql_grant/mysql.rb b/lib/puppet/provider/mysql_grant/mysql.rb
index 6582523..4c41e76 100644
--- a/lib/puppet/provider/mysql_grant/mysql.rb
+++ b/lib/puppet/provider/mysql_grant/mysql.rb
@@ -11,7 +11,7 @@ MYSQL_USER_PRIVS = [ :select_priv, :insert_priv, :update_priv, :delete_priv,
:show_db_priv, :super_priv, :create_tmp_table_priv, :lock_tables_priv,
:execute_priv, :repl_slave_priv, :repl_client_priv, :create_view_priv,
:show_view_priv, :create_routine_priv, :alter_routine_priv,
- :create_user_priv
+ :create_user_priv, :trigger_priv
]
mysql_version = Facter.value(:mysql_version)
if mysql_version =~ /^5.1/ && mysql_version.split('.').last.to_i >= 6
@@ -29,6 +29,12 @@ else
]
end
+MYSQL_TABLE_PRIVS = [ :select, :insert, :update, :delete, :create, :drop,
+ :references, :index, :alter
+]
+
+MYSQL_COLUMN_PRIVS = [ :select_priv, :insert_priv, :update_priv, :references_priv ]
+
Puppet::Type.type(:mysql_grant).provide(:mysql) do
desc "Uses mysql as database."
@@ -42,7 +48,8 @@ Puppet::Type.type(:mysql_grant).provide(:mysql) do
# this parses the
def split_name(string)
- matches = /^([^@]*)@([^\/]*)(\/(.*))?$/.match(string).captures.compact
+ matches = /^([^@]*)@([^\/]*)(\/([^\/]*))?(\/([^\/]*))?$/.match(string).captures.compact
+
case matches.length
when 2
{
@@ -57,6 +64,23 @@ Puppet::Type.type(:mysql_grant).provide(:mysql) do
:host => matches[1],
:db => matches[3]
}
+ when 6
+ {
+ :type => :tables_priv,
+ :user => matches[0],
+ :host => matches[1],
+ :db => matches[3],
+ :table_name => matches[5]
+ }
+ when 8
+ {
+ :type => :table,
+ :user => matches[0],
+ :host => matches[1],
+ :db => matches[3],
+ :table => matches[5],
+ :column => matches[7]
+ }
end
end
@@ -72,6 +96,10 @@ Puppet::Type.type(:mysql_grant).provide(:mysql) do
mysql "mysql", "-e", "INSERT INTO db (host, user, db) VALUES ('%s', '%s', '%s')" % [
name[:host], name[:user], name[:db],
]
+ when :column
+ mysql "mysql", "-e", "INSERT INTO columns_priv (host, user, db, table, column_name) VALUES ('%s', '%s', '%s', '%s', '%s')" % [
+ name[:host], name[:user], name[:db], name[:table], name[:column],
+ ]
end
mysql_flush
end
@@ -87,6 +115,9 @@ Puppet::Type.type(:mysql_grant).provide(:mysql) do
if name[:type] == :db
fields << :db
end
+ if name[:type] == :column
+ fields << :column
+ end
not mysql( "mysql", "-NBe", 'SELECT "1" FROM %s WHERE %s' % [ name[:type], fields.map do |f| "%s = '%s'" % [f, name[f]] end.join(' AND ')]).empty?
end
@@ -96,6 +127,10 @@ Puppet::Type.type(:mysql_grant).provide(:mysql) do
MYSQL_USER_PRIVS
when :db
MYSQL_DB_PRIVS
+ when :tables_priv
+ MYSQL_TABLE_PRIVS
+ when :column
+ MYSQL_COLUMN_PRIVS
end
all_privs = all_privs.collect do |p| p.to_s end.sort.join("|")
privs = privileges.collect do |p| p.to_s end.sort.join("|")
@@ -112,24 +147,36 @@ Puppet::Type.type(:mysql_grant).provide(:mysql) do
privs = mysql "mysql", "-Be", 'select * from user where user="%s" and host="%s"' % [ name[:user], name[:host] ]
when :db
privs = mysql "mysql", "-Be", 'select * from db where user="%s" and host="%s" and db="%s"' % [ name[:user], name[:host], name[:db] ]
+ when :tables_priv
+ privs = mysql "mysql", "-NBe", 'select Table_priv from tables_priv where User="%s" and Host="%s" and Db="%s" and Table_name="%s"' % [ name[:user], name[:host], name[:db], name[:table_name] ]
+ privs = privs.chomp.downcase
+ return privs
+ when :columns
+ privs = mysql "mysql", "-Be", 'select * from columns_priv where User="%s" and Host="%s" and Db="%s" and Table_name="%s" and Column_name="%s"' % [ name[:user], name[:host], name[:db], name[:table], name[:column] ]
end
if privs.match(/^$/)
privs = [] # no result, no privs
else
+ case name[:type]
+ when :user, :db
# returns a line with field names and a line with values, each tab-separated
- privs = privs.split(/\n/).map! do |l| l.chomp.split(/\t/) end
- # transpose the lines, so we have key/value pairs
- privs = privs[0].zip(privs[1])
- privs = privs.select do |p| p[0].match(/_priv$/) and p[1] == 'Y' end
+ privs = privs.split(/\n/).map! do |l| l.chomp.split(/\t/) end
+ # transpose the lines, so we have key/value pairs
+ privs = privs[0].zip(privs[1])
+ privs = privs.select do |p| (/_priv$/) and p[1] == 'Y' end
+ privs.collect do |p| symbolize(p[0].downcase) end
+ end
end
-
- privs.collect do |p| symbolize(p[0].downcase) end
end
def privileges=(privs)
- unless row_exists?
- create_row
+ name = split_name(@resource[:name])
+ # don't need to create a row for tables_priv and columns_priv
+ if name[:type] == :user || name[:type] == :db
+ unless row_exists?
+ create_row
+ end
end
# puts "Setting privs: ", privs.join(", ")
@@ -146,19 +193,49 @@ Puppet::Type.type(:mysql_grant).provide(:mysql) do
stmt = 'update db set '
where = ' where user="%s" and host="%s"' % [ name[:user], name[:host] ]
all_privs = MYSQL_DB_PRIVS
+ when :tables_priv
+ currently_set = privileges
+ currently_set = currently_set.scan(/\w+/)
+ privs.map! {|i| i.to_s.downcase}
+ revoke = currently_set - privs
+
+ if !revoke.empty?
+ #puts "Revoking table privs: ", revoke
+ mysql "mysql", "-e", "REVOKE %s ON %s.%s FROM '%s'@'%s'" % [ revoke.join(", "), name[:db], name[:table_name], name[:user], name[:host] ]
+ end
+
+ set = privs - currently_set
+ stmt = 'GRANT '
+ where = ' ON %s.%s TO "%s"@"%s"' % [ name[:db], name[:table_name], name[:user], name[:host] ]
+ all_privs = MYSQL_TABLE_PRIVS
+ when :column
+ stmt = 'update columns_priv set '
+ where = ' where user="%s" and host="%s" and Db="%s" and Table_name="%s"' % [ name[:user], name[:host], name[:db], name[:table_name] ]
+ all_privs = MYSQL_COLUMN_PRIVS
end
if privs[0] == :all
privs = all_privs
end
- # puts "stmt:", stmt
- set = all_privs.collect do |p| "%s = '%s'" % [p, privs.include?(p) ? 'Y' : 'N'] end.join(', ')
- # puts "set:", set
+ #puts "stmt:", stmt
+ case name[:type]
+ when :user
+ set = all_privs.collect do |p| "%s = '%s'" % [p, privs.include?(p) ? 'Y' : 'N'] end.join(', ')
+ when :db
+ set = all_privs.collect do |p| "%s = '%s'" % [p, privs.include?(p) ? 'Y' : 'N'] end.join(', ')
+ when :tables_priv
+ set = set.join(', ')
+ end
+
+ #puts "set:", set
stmt = stmt << set << where
+ #puts "stmt:", stmt
- mysql "mysql", "-Be", stmt
- mysql_flush
+ if !set.empty?
+ mysql "mysql", "-Be", stmt
+ mysql_flush
+ end
end
end
diff --git a/lib/puppet/type/mysql_grant.rb b/lib/puppet/type/mysql_grant.rb
index 6bc7533..c6311e5 100644
--- a/lib/puppet/type/mysql_grant.rb
+++ b/lib/puppet/type/mysql_grant.rb
@@ -5,6 +5,16 @@ Puppet::Type.newtype(:mysql_grant) do
#ensurable
autorequire(:service) { 'mysqld' }
+ autorequire :mysql_table do
+ reqs = []
+ matches = self[:name].match(/^([^@]*)@([^\/]*)\/(.+)\/(.+)$/)
+ unless matches.nil?
+ reqs << matches[4]
+ end
+ # puts "Autoreq: '%s'" % reqs.join(" ")
+ reqs
+ end
+
autorequire :mysql_db do
# puts "Starting db autoreq for %s" % self[:name]
reqs = []
diff --git a/manifests/client/perl.pp b/manifests/client/perl.pp
new file mode 100644
index 0000000..09a790b
--- /dev/null
+++ b/manifests/client/perl.pp
@@ -0,0 +1,7 @@
+class mysql::client::perl {
+
+ case $operatingsystem {
+ debian: { include mysql::client::perl::debian }
+ }
+
+}
diff --git a/manifests/client/perl/debian.pp b/manifests/client/perl/debian.pp
new file mode 100644
index 0000000..790eaff
--- /dev/null
+++ b/manifests/client/perl/debian.pp
@@ -0,0 +1,6 @@
+class mysql::client::perl::debian {
+
+ package { 'libdbd-mysql-perl':
+ ensure => present,
+ }
+}
diff --git a/manifests/server/base.pp b/manifests/server/base.pp
index eb66b43..75f5725 100644
--- a/manifests/server/base.pp
+++ b/manifests/server/base.pp
@@ -52,7 +52,7 @@ class mysql::server::base {
exec { 'mysql_set_rootpw':
command => '/usr/local/sbin/setmysqlpass.sh',
- unless => "mysqladmin -uroot status > /dev/null",
+ unless => '/usr/bin/mysqladmin -uroot status > /dev/null',
require => [ File['mysql_setmysqlpass.sh'], Package['mysql-server'] ],
refreshonly => true,
}
diff --git a/manifests/server/munin/base.pp b/manifests/server/munin/base.pp
new file mode 100644
index 0000000..ad4bb8a
--- /dev/null
+++ b/manifests/server/munin/base.pp
@@ -0,0 +1,20 @@
+class mysql::server::munin::base {
+
+ file {
+ "/usr/local/share/munin-plugins/mysql_connections":
+ source => "puppet:///modules/mysql/munin/mysql_connections",
+ mode => 0755, owner => root, group => root;
+
+ "/usr/local/share/munin-plugins/mysql_qcache":
+ source => "puppet:///modules/mysql/munin/mysql_qcache",
+ mode => 0755, owner => root, group => root;
+
+ "/usr/local/share/munin-plugins/mysql_qcache_mem":
+ source => "puppet:///modules/mysql/munin/mysql_qcache_mem",
+ mode => 0755, owner => root, group => root;
+
+ "/usr/local/share/munin-plugins/mysql_size_all":
+ source => "puppet:///modules/mysql/munin/mysql_size_all",
+ mode => 0755, owner => root, group => root;
+ }
+}
diff --git a/manifests/server/munin/debian.pp b/manifests/server/munin/debian.pp
index 2b2acb4..d1636d5 100644
--- a/manifests/server/munin/debian.pp
+++ b/manifests/server/munin/debian.pp
@@ -1,9 +1,14 @@
# manifests/server/munin/debian.pp
-class mysql::server::munin::debian {
- munin::plugin {
- [mysql_bytes, mysql_queries, mysql_slowqueries, mysql_threads]:
- config => "user root\nenv.mysqlopts --defaults-file=/etc/mysql/debian.cnf",
- require => Package['mysql'],
- }
+class mysql::server::munin::debian inherits mysql::server::munin::base {
+ munin::plugin {
+ [ mysql_bytes, mysql_queries, mysql_slowqueries, mysql_threads ]:
+ config => "user root\nenv.mysqlopts --defaults-file=/etc/mysql/debian.cnf",
+ require => Package['mysql'];
+
+ [ mysql_connections, mysql_qcache, mysql_cache_mem, mysql_size_all ]:
+ config => "user root\nenv.mysqlopts --defaults-file=/etc/mysql/debian.cnf",
+ script_path_in => "/usr/local/share/munin-plugins",
+ require => Package['mysql'];
+ }
}
diff --git a/manifests/server/nagios.pp b/manifests/server/nagios.pp
index 18eef8a..26644db 100644
--- a/manifests/server/nagios.pp
+++ b/manifests/server/nagios.pp
@@ -1,3 +1,5 @@
+# manifests/server/nagios.pp
+
class mysql::server::nagios {
# Flip this variable if you need to check MySQL through check_ssh or check_nrpe,
# in that case you will have to manually define nagios::service::mysql