Mysqldump Action
Add the mysqldump and set-pxc-strict-mode actions to allow for dumping databases in text form. Change-Id: Ibb9c5e17d01c7bb1335d8a7c9087216af8d00b09
This commit is contained in:
parent
1cf3fa1ac1
commit
b73f5c4880
30
actions.yaml
30
actions.yaml
@ -34,3 +34,33 @@ bootstrap-pxc:
|
||||
https://www.percona.com/blog/2014/09/01/galera-replication-how-to-recover-a-pxc-cluster/
|
||||
notify-bootstrapped:
|
||||
descripttion: Notify the cluster of the new bootstrap uuid.
|
||||
set-pxc-strict-mode:
|
||||
description: |
|
||||
Set PXC strict mode.
|
||||
params:
|
||||
mode:
|
||||
type: string
|
||||
default: "ENFORCING"
|
||||
description: |
|
||||
PXC strict mode. Valid options are DISALBED, PERMISSIVE, ENFORCING or MASTER
|
||||
See https://www.percona.com/doc/percona-xtradb-cluster/LATEST/features/pxc-strict-mode.html
|
||||
for more detail.
|
||||
mysqldump:
|
||||
description: |
|
||||
MySQL dump of databases. Action will return mysqldump-file location of the
|
||||
requested backup in the results. If the databases parameter is unset all
|
||||
databases will be dumped. If the databases parameter is set only the
|
||||
databases specified will be dumped. Note it may be necessary to use the
|
||||
set-pxc-strict-mode action first to set either PERMISSIVE or MASTER to
|
||||
allow locking of tables for mysqldump to complete successfully.
|
||||
See https://www.percona.com/doc/percona-xtradb-cluster/LATEST/features/pxc-strict-mode.html
|
||||
for more detail.
|
||||
params:
|
||||
basedir:
|
||||
type: string
|
||||
default: "/var/backups/mysql"
|
||||
description: The base directory for backups
|
||||
databases:
|
||||
description: |
|
||||
Comma delimited database names to dump. If left unset, all databases
|
||||
will be dumped.
|
||||
|
@ -6,6 +6,9 @@ import subprocess
|
||||
import traceback
|
||||
from time import gmtime, strftime
|
||||
|
||||
import MySQLdb
|
||||
|
||||
|
||||
_path = os.path.dirname(os.path.realpath(__file__))
|
||||
_hooks = os.path.abspath(os.path.join(_path, '../hooks'))
|
||||
_root = os.path.abspath(os.path.join(_path, '..'))
|
||||
@ -167,12 +170,67 @@ def notify_bootstrapped(args):
|
||||
percona_utils.notify_bootstrapped()
|
||||
|
||||
|
||||
def set_pxc_strict_mode(args):
|
||||
"""Set PXC Strict Mode.
|
||||
"""
|
||||
mode = action_get("mode")
|
||||
try:
|
||||
percona_utils.set_pxc_strict_mode(mode)
|
||||
action_set({"outcome": "Success"})
|
||||
except (MySQLdb.OperationalError, ValueError) as e:
|
||||
action_set({
|
||||
"output": ", ".join(e.args),
|
||||
"traceback": traceback.format_exc()})
|
||||
action_fail("Setting PXC strict mode {} failed"
|
||||
.format(mode))
|
||||
|
||||
|
||||
def mysqldump(args):
|
||||
"""Execute a mysqldump backup.
|
||||
|
||||
Execute mysqldump of the database(s). The mysqldump action will take
|
||||
in the databases action parameter. If the databases parameter is unset all
|
||||
databases will be dumped, otherwise only the named databases will be
|
||||
dumped. The action will use the basedir action parameter to dump the
|
||||
database into the base directory.
|
||||
|
||||
A successful mysqldump backup will set the action results key,
|
||||
mysqldump-file, with the full path to the dump file.
|
||||
|
||||
:param args: sys.argv
|
||||
:type args: sys.argv
|
||||
:side effect: Calls instance.mysqldump
|
||||
:returns: This function is called for its side effect
|
||||
:rtype: None
|
||||
:action param basedir: Base directory to dump the db(s)
|
||||
:action param databases: Comma separated string of databases
|
||||
:action return:
|
||||
"""
|
||||
basedir = action_get("basedir")
|
||||
databases = action_get("databases")
|
||||
|
||||
try:
|
||||
filename = percona_utils.mysqldump(basedir, databases=databases)
|
||||
action_set({
|
||||
"mysqldump-file": filename,
|
||||
"outcome": "Success"}
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
action_set({
|
||||
"output": e.output,
|
||||
"return-code": e.returncode,
|
||||
"traceback": traceback.format_exc()})
|
||||
action_fail("mysqldump failed")
|
||||
|
||||
|
||||
# A dictionary of all the defined actions to callables (which take
|
||||
# parsed arguments).
|
||||
ACTIONS = {"pause": pause, "resume": resume, "backup": backup,
|
||||
"complete-cluster-series-upgrade": complete_cluster_series_upgrade,
|
||||
"bootstrap-pxc": bootstrap_pxc,
|
||||
"notify-bootstrapped": notify_bootstrapped}
|
||||
"notify-bootstrapped": notify_bootstrapped,
|
||||
"set-pxc-strict-mode": set_pxc_strict_mode,
|
||||
"mysqldump": mysqldump}
|
||||
|
||||
|
||||
def main(args):
|
||||
|
1
actions/mysqldump
Symbolic link
1
actions/mysqldump
Symbolic link
@ -0,0 +1 @@
|
||||
actions.py
|
1
actions/set-pxc-strict-mode
Symbolic link
1
actions/set-pxc-strict-mode
Symbolic link
@ -0,0 +1 @@
|
||||
actions.py
|
@ -1,5 +1,6 @@
|
||||
''' General utilities for percona '''
|
||||
import collections
|
||||
import datetime
|
||||
import subprocess
|
||||
from subprocess import Popen, PIPE
|
||||
import socket
|
||||
@ -15,6 +16,7 @@ import time
|
||||
import yaml
|
||||
|
||||
from charmhelpers.core.decorators import retry_on_exception
|
||||
from charmhelpers.core.templating import render
|
||||
from charmhelpers.core.host import (
|
||||
lsb_release,
|
||||
mkdir,
|
||||
@ -1605,3 +1607,85 @@ def maybe_notify_bootstrapped():
|
||||
cluster_state_uuid = get_wsrep_value('wsrep_cluster_state_uuid')
|
||||
if lead_cluster_state_uuid == cluster_state_uuid:
|
||||
notify_bootstrapped(cluster_uuid=cluster_state_uuid)
|
||||
|
||||
|
||||
def set_pxc_strict_mode(mode):
|
||||
"""Set PXC Strict Mode.
|
||||
|
||||
:param mode: Strict mode: DISALBED, PERMISSIVE, ENFORCING or MASTER
|
||||
:type backup_dir: str
|
||||
:raises: Raises ValueError if mode is not a valide parameter
|
||||
:raises: Raises MySQLdb.OperationalError if SQL is not successful
|
||||
:returns: None
|
||||
:rtype: None
|
||||
"""
|
||||
_VALID_PARAMS = ["DISABLED", "PERMISSIVE", "ENFORCING", "MASTER"]
|
||||
mode = mode.upper()
|
||||
if mode not in _VALID_PARAMS:
|
||||
raise ValueError(
|
||||
"'{}' is not a valid parameter for pxc_strict_mode. "
|
||||
"Valid options are {}.".format(mode, ", ".join(_VALID_PARAMS)))
|
||||
m_helper = get_db_helper()
|
||||
m_helper.connect(password=m_helper.get_mysql_root_password())
|
||||
m_helper.execute("SET GLOBAL pxc_strict_mode='{}'".format(mode))
|
||||
|
||||
|
||||
def write_root_my_cnf():
|
||||
"""Write root my.cnf
|
||||
|
||||
:side effect: calls render()
|
||||
:returns: None
|
||||
:rtype: None
|
||||
"""
|
||||
my_cnf_template = "root-my.cnf"
|
||||
root_my_cnf = "/root/.my.cnf"
|
||||
context = {"mysql_passwd": leader_get("mysql.passwd")}
|
||||
render(my_cnf_template, root_my_cnf, context, perms=0o600)
|
||||
|
||||
|
||||
def mysqldump(backup_dir, databases=None):
|
||||
"""Execute a MySQL dump
|
||||
|
||||
:param backup_dir: Path to the backup directory
|
||||
:type backup_dir: str
|
||||
:param databases: Comma delimited database names
|
||||
:type database: str
|
||||
:side effect: Calls subprocess.check_call
|
||||
:raises subprocess.CalledProcessError: If the mysqldump fails
|
||||
:returns: Path to the mysqldump file
|
||||
:rtype: str
|
||||
"""
|
||||
# In order to enable passwordless use of mysqldump
|
||||
# write out my.cnf for user root
|
||||
write_root_my_cnf()
|
||||
# Enable use of my.cnf by setting HOME env variable
|
||||
os.environ["HOME"] = "/root"
|
||||
_user = "root"
|
||||
_delimiter = ","
|
||||
if not os.path.exists(backup_dir):
|
||||
mkdir(
|
||||
backup_dir, owner="mysql", group="mysql", perms=0o750)
|
||||
|
||||
bucmd = ["/usr/bin/mysqldump", "-u", _user,
|
||||
"--column-statistics=0",
|
||||
"--default-character-set=utf8",
|
||||
"--triggers", "--routines", "--events",
|
||||
"--ignore-table=mysql.event"]
|
||||
if databases is not None:
|
||||
_filename = os.path.join(
|
||||
backup_dir,
|
||||
"mysqldump-{}-{}".format(
|
||||
"-".join(databases.split(_delimiter)),
|
||||
datetime.datetime.now().strftime("%Y%m%d%H%M")))
|
||||
bucmd.extend(["--result-file", _filename, "--databases"])
|
||||
bucmd.extend(databases.split(_delimiter))
|
||||
else:
|
||||
_filename = os.path.join(
|
||||
backup_dir,
|
||||
"mysqldump-all-databases-{}".format(
|
||||
datetime.datetime.now().strftime("%Y%m%d%H%M")))
|
||||
bucmd.extend(["--result-file", _filename, "--all-databases"])
|
||||
subprocess.check_call(bucmd)
|
||||
gzcmd = ["gzip", _filename]
|
||||
subprocess.check_call(gzcmd)
|
||||
return "{}.gz".format(_filename)
|
||||
|
4
templates/root-my.cnf
Normal file
4
templates/root-my.cnf
Normal file
@ -0,0 +1,4 @@
|
||||
[client]
|
||||
# The following password will be sent to all standard MySQL clients
|
||||
password="{{ mysql_passwd }}"
|
||||
|
Loading…
x
Reference in New Issue
Block a user