Merge "Fixed MySQL 5.7 not starting after restore"
This commit is contained in:
commit
b0a45c0962
@ -39,19 +39,12 @@ class MySQLRestoreMixin(object):
|
|||||||
RESET_ROOT_RETRY_TIMEOUT = 100
|
RESET_ROOT_RETRY_TIMEOUT = 100
|
||||||
RESET_ROOT_SLEEP_INTERVAL = 10
|
RESET_ROOT_SLEEP_INTERVAL = 10
|
||||||
|
|
||||||
# Reset the root password in a single transaction with 'FLUSH PRIVILEGES'
|
RESET_ROOT_MYSQL_COMMANDS = ("SET PASSWORD FOR "
|
||||||
# to ensure we never leave database wide open without 'grant tables'.
|
"'root'@'localhost'=PASSWORD('');")
|
||||||
RESET_ROOT_MYSQL_COMMANDS = ("START TRANSACTION;",
|
|
||||||
"UPDATE `mysql`.`user` SET"
|
|
||||||
" `password`=PASSWORD('')"
|
|
||||||
" WHERE `user`='root'"
|
|
||||||
" AND `host` = 'localhost';",
|
|
||||||
"FLUSH PRIVILEGES;",
|
|
||||||
"COMMIT;")
|
|
||||||
# This is a suffix MySQL appends to the file name given in
|
# This is a suffix MySQL appends to the file name given in
|
||||||
# the '--log-error' startup parameter.
|
# the '--log-error' startup parameter.
|
||||||
_ERROR_LOG_SUFFIX = '.err'
|
_ERROR_LOG_SUFFIX = '.err'
|
||||||
_ERROR_MESSAGE_PATTERN = re.compile("^ERROR:\s+.+$")
|
_ERROR_MESSAGE_PATTERN = re.compile("ERROR")
|
||||||
|
|
||||||
def mysql_is_running(self):
|
def mysql_is_running(self):
|
||||||
try:
|
try:
|
||||||
@ -80,16 +73,12 @@ class MySQLRestoreMixin(object):
|
|||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
def _start_mysqld_safe_with_init_file(self, init_file, err_log_file):
|
def _start_mysqld_safe_with_init_file(self, init_file, err_log_file):
|
||||||
child = pexpect.spawn("sudo mysqld_safe"
|
child = pexpect.spawn(
|
||||||
" --skip-grant-tables"
|
"sudo mysqld_safe --init-file=%s --log-error=%s" %
|
||||||
" --skip-networking"
|
(init_file.name, err_log_file.name))
|
||||||
" --init-file='%s'"
|
|
||||||
" --log-error='%s'" %
|
|
||||||
(init_file.name, err_log_file.name)
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
i = child.expect(['Starting mysqld daemon'])
|
index = child.expect(['Starting mysqld daemon'])
|
||||||
if i == 0:
|
if index == 0:
|
||||||
LOG.info(_("Starting MySQL"))
|
LOG.info(_("Starting MySQL"))
|
||||||
except pexpect.TIMEOUT:
|
except pexpect.TIMEOUT:
|
||||||
LOG.exception(_("Got a timeout launching mysqld_safe"))
|
LOG.exception(_("Got a timeout launching mysqld_safe"))
|
||||||
@ -110,7 +99,8 @@ class MySQLRestoreMixin(object):
|
|||||||
|
|
||||||
LOG.info(_("Root password reset successfully."))
|
LOG.info(_("Root password reset successfully."))
|
||||||
LOG.debug("Cleaning up the temp mysqld process.")
|
LOG.debug("Cleaning up the temp mysqld process.")
|
||||||
utils.execute_with_timeout("mysqladmin", "-uroot", "shutdown")
|
utils.execute_with_timeout("mysqladmin", "-uroot",
|
||||||
|
"--protocol=tcp", "shutdown")
|
||||||
LOG.debug("Polling for shutdown to complete.")
|
LOG.debug("Polling for shutdown to complete.")
|
||||||
try:
|
try:
|
||||||
utils.poll_until(self.mysql_is_not_running,
|
utils.poll_until(self.mysql_is_not_running,
|
||||||
@ -134,10 +124,10 @@ class MySQLRestoreMixin(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(mode='w') as init_file:
|
with tempfile.NamedTemporaryFile(mode='w') as init_file:
|
||||||
|
operating_system.write_file(init_file.name,
|
||||||
|
self.RESET_ROOT_MYSQL_COMMANDS)
|
||||||
operating_system.chmod(init_file.name, FileMode.ADD_READ_ALL,
|
operating_system.chmod(init_file.name, FileMode.ADD_READ_ALL,
|
||||||
as_root=True)
|
as_root=True)
|
||||||
self._writelines_one_per_line(init_file,
|
|
||||||
self.RESET_ROOT_MYSQL_COMMANDS)
|
|
||||||
# Do not attempt to delete the file as the 'trove' user.
|
# Do not attempt to delete the file as the 'trove' user.
|
||||||
# The process writing into it may have assumed its ownership.
|
# The process writing into it may have assumed its ownership.
|
||||||
# Only owners can delete temporary
|
# Only owners can delete temporary
|
||||||
@ -149,38 +139,19 @@ class MySQLRestoreMixin(object):
|
|||||||
self._start_mysqld_safe_with_init_file(init_file, err_log_file)
|
self._start_mysqld_safe_with_init_file(init_file, err_log_file)
|
||||||
finally:
|
finally:
|
||||||
err_log_file.close()
|
err_log_file.close()
|
||||||
MySQLRestoreMixin._delete_file(err_log_file.name)
|
operating_system.remove(
|
||||||
|
err_log_file.name, force=True, as_root=True)
|
||||||
def _writelines_one_per_line(self, fp, lines):
|
|
||||||
fp.write(os.linesep.join(lines))
|
|
||||||
fp.flush()
|
|
||||||
|
|
||||||
def _find_first_error_message(self, fp):
|
def _find_first_error_message(self, fp):
|
||||||
if MySQLRestoreMixin._is_non_zero_file(fp):
|
if self._is_non_zero_file(fp):
|
||||||
return MySQLRestoreMixin._find_first_pattern_match(
|
return self._find_first_pattern_match(
|
||||||
fp,
|
fp, self._ERROR_MESSAGE_PATTERN)
|
||||||
self._ERROR_MESSAGE_PATTERN
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _delete_file(self, file_path):
|
|
||||||
"""Force-remove a given file as root.
|
|
||||||
Do not raise an exception on failure.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if os.path.isfile(file_path):
|
|
||||||
try:
|
|
||||||
operating_system.remove(file_path, force=True, as_root=True)
|
|
||||||
except Exception:
|
|
||||||
LOG.exception(_("Could not remove file: '%s'") % file_path)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _is_non_zero_file(self, fp):
|
def _is_non_zero_file(self, fp):
|
||||||
file_path = fp.name
|
file_path = fp.name
|
||||||
return os.path.isfile(file_path) and (os.path.getsize(file_path) > 0)
|
return os.path.isfile(file_path) and (os.path.getsize(file_path) > 0)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _find_first_pattern_match(self, fp, pattern):
|
def _find_first_pattern_match(self, fp, pattern):
|
||||||
for line in fp:
|
for line in fp:
|
||||||
if pattern.match(line):
|
if pattern.match(line):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user