2013-07-30 16:59:32 +02:00
|
|
|
#!/usr/bin/python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
Ansible module to manage mysql variables
|
|
|
|
(c) 2013, Balazs Pocze <banyek@gawker.com>
|
|
|
|
Certain parts are taken from Mark Theunissen's mysqldb module
|
|
|
|
|
|
|
|
This file is part of Ansible
|
|
|
|
|
|
|
|
Ansible 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, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
"""
|
|
|
|
|
|
|
|
DOCUMENTATION = '''
|
|
|
|
---
|
|
|
|
module: mysql_variables
|
|
|
|
|
|
|
|
short_description: Manage MySQL global variables
|
|
|
|
description:
|
|
|
|
- Query / Set MySQL variables
|
2013-09-06 19:31:43 +02:00
|
|
|
version_added: 1.3
|
2013-07-30 16:59:32 +02:00
|
|
|
options:
|
|
|
|
variable:
|
|
|
|
description:
|
|
|
|
- Variable name to operate
|
|
|
|
required: True
|
|
|
|
value:
|
|
|
|
description:
|
|
|
|
- If set, then sets variable value to this
|
|
|
|
required: False
|
|
|
|
login_user:
|
|
|
|
description:
|
|
|
|
- username to connect mysql host, if defined login_password also needed.
|
|
|
|
required: False
|
|
|
|
login_password:
|
|
|
|
description:
|
|
|
|
- password to connect mysql host, if defined login_user also needed.
|
|
|
|
required: False
|
|
|
|
login_host:
|
|
|
|
description:
|
|
|
|
- mysql host to connect
|
|
|
|
required: False
|
|
|
|
login_unix_socket:
|
|
|
|
description:
|
|
|
|
- unix socket to connect mysql server
|
|
|
|
'''
|
2013-08-08 11:28:26 +02:00
|
|
|
EXAMPLES = '''
|
|
|
|
# Check for sync_binary_log setting
|
|
|
|
- mysql_variables: variable=sync_binary_log
|
|
|
|
|
|
|
|
# Set read_only variable to 1
|
|
|
|
- mysql_variables: variable=read_only value=1
|
|
|
|
'''
|
2013-07-30 16:59:32 +02:00
|
|
|
|
|
|
|
|
|
|
|
import ConfigParser
|
|
|
|
import os
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
try:
|
|
|
|
import MySQLdb
|
|
|
|
except ImportError:
|
|
|
|
mysqldb_found = False
|
|
|
|
else:
|
|
|
|
mysqldb_found = True
|
|
|
|
|
|
|
|
|
|
|
|
def getvariable(cursor, mysqlvar):
|
|
|
|
cursor.execute("SHOW VARIABLES LIKE '" + mysqlvar + "'")
|
|
|
|
mysqlvar_val = cursor.fetchall()
|
|
|
|
return mysqlvar_val
|
|
|
|
|
|
|
|
def setvariable(cursor, mysqlvar, value):
|
|
|
|
try:
|
|
|
|
cursor.execute("SET GLOBAL " + mysqlvar + "=" + value)
|
|
|
|
cursor.fetchall()
|
|
|
|
result = True
|
|
|
|
except Exception, e:
|
|
|
|
result = str(e)
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
def strip_quotes(s):
|
|
|
|
""" Remove surrounding single or double quotes
|
|
|
|
|
|
|
|
>>> print strip_quotes('hello')
|
|
|
|
hello
|
|
|
|
>>> print strip_quotes('"hello"')
|
|
|
|
hello
|
|
|
|
>>> print strip_quotes("'hello'")
|
|
|
|
hello
|
|
|
|
>>> print strip_quotes("'hello")
|
|
|
|
'hello
|
|
|
|
|
|
|
|
"""
|
|
|
|
single_quote = "'"
|
|
|
|
double_quote = '"'
|
|
|
|
|
|
|
|
if s.startswith(single_quote) and s.endswith(single_quote):
|
|
|
|
s = s.strip(single_quote)
|
|
|
|
elif s.startswith(double_quote) and s.endswith(double_quote):
|
|
|
|
s = s.strip(double_quote)
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
def config_get(config, section, option):
|
|
|
|
""" Calls ConfigParser.get and strips quotes
|
|
|
|
|
|
|
|
See: http://dev.mysql.com/doc/refman/5.0/en/option-files.html
|
|
|
|
"""
|
|
|
|
return strip_quotes(config.get(section, option))
|
|
|
|
|
|
|
|
|
|
|
|
def load_mycnf():
|
|
|
|
config = ConfigParser.RawConfigParser()
|
|
|
|
mycnf = os.path.expanduser('~/.my.cnf')
|
|
|
|
if not os.path.exists(mycnf):
|
|
|
|
return False
|
|
|
|
try:
|
|
|
|
config.readfp(open(mycnf))
|
|
|
|
except (IOError):
|
|
|
|
return False
|
|
|
|
# We support two forms of passwords in .my.cnf, both pass= and password=,
|
|
|
|
# as these are both supported by MySQL.
|
|
|
|
try:
|
|
|
|
passwd = config_get(config, 'client', 'password')
|
|
|
|
except (ConfigParser.NoOptionError):
|
|
|
|
try:
|
|
|
|
passwd = config_get(config, 'client', 'pass')
|
|
|
|
except (ConfigParser.NoOptionError):
|
|
|
|
return False
|
|
|
|
|
|
|
|
# If .my.cnf doesn't specify a user, default to user login name
|
|
|
|
try:
|
|
|
|
user = config_get(config, 'client', 'user')
|
|
|
|
except (ConfigParser.NoOptionError):
|
|
|
|
user = getpass.getuser()
|
|
|
|
creds = dict(user=user, passwd=passwd)
|
|
|
|
return creds
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
module = AnsibleModule(
|
|
|
|
argument_spec = dict(
|
|
|
|
login_user=dict(default=None),
|
|
|
|
login_password=dict(default=None),
|
|
|
|
login_host=dict(default="localhost"),
|
|
|
|
login_unix_socket=dict(default=None),
|
|
|
|
variable=dict(default=None),
|
|
|
|
value=dict(default=None)
|
|
|
|
|
|
|
|
)
|
|
|
|
)
|
|
|
|
user = module.params["login_user"]
|
|
|
|
password = module.params["login_password"]
|
|
|
|
host = module.params["login_host"]
|
|
|
|
mysqlvar = module.params["variable"]
|
|
|
|
value = module.params["value"]
|
|
|
|
if not mysqldb_found:
|
|
|
|
module.fail_json(msg="the python mysqldb module is required")
|
|
|
|
else:
|
|
|
|
warnings.filterwarnings('error', category=MySQLdb.Warning)
|
|
|
|
|
|
|
|
# Either the caller passes both a username and password with which to connect to
|
|
|
|
# mysql, or they pass neither and allow this module to read the credentials from
|
|
|
|
# ~/.my.cnf.
|
|
|
|
login_password = module.params["login_password"]
|
|
|
|
login_user = module.params["login_user"]
|
|
|
|
if login_user is None and login_password is None:
|
|
|
|
mycnf_creds = load_mycnf()
|
|
|
|
if mycnf_creds is False:
|
|
|
|
login_user = "root"
|
|
|
|
login_password = ""
|
|
|
|
else:
|
|
|
|
login_user = mycnf_creds["user"]
|
|
|
|
login_password = mycnf_creds["passwd"]
|
|
|
|
elif login_password is None or login_user is None:
|
|
|
|
module.fail_json(msg="when supplying login arguments, both login_user and login_password must be provided")
|
|
|
|
try:
|
|
|
|
if module.params["login_unix_socket"]:
|
|
|
|
db_connection = MySQLdb.connect(host=module.params["login_host"], unix_socket=module.params["login_unix_socket"], user=login_user, passwd=login_password, db="mysql")
|
|
|
|
else:
|
|
|
|
db_connection = MySQLdb.connect(host=module.params["login_host"], user=login_user, passwd=login_password, db="mysql")
|
|
|
|
cursor = db_connection.cursor()
|
|
|
|
except Exception, e:
|
|
|
|
module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or ~/.my.cnf has the credentials")
|
|
|
|
if mysqlvar is None:
|
|
|
|
module.fail_json(msg="Cannot run without variable to operate with")
|
2013-10-17 19:13:58 +02:00
|
|
|
mysqlvar_val = getvariable(cursor, mysqlvar)
|
|
|
|
if value is None:
|
2013-07-30 16:59:32 +02:00
|
|
|
module.exit_json(msg=mysqlvar_val)
|
|
|
|
else:
|
2013-10-17 19:13:58 +02:00
|
|
|
if value == mysqlvar_val[0][1]:
|
|
|
|
module.exit_json(msg="Variable already set to requested value", changed=False)
|
2013-07-30 16:59:32 +02:00
|
|
|
result = setvariable(cursor, mysqlvar, value)
|
|
|
|
if result is True:
|
|
|
|
module.exit_json(msg="Variable change succeeded", changed=True)
|
|
|
|
else:
|
|
|
|
module.fail_json(msg=result, changed=False)
|
|
|
|
|
|
|
|
# this is magic, see lib/ansible/module_common.py
|
|
|
|
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
|
|
|
|
main()
|