From 553c578923d30d0eb15ad5dbd0a2c583cae274a4 Mon Sep 17 00:00:00 2001 From: Hirotaka Wakabayashi Date: Fri, 27 Jan 2023 14:34:49 +0900 Subject: Fixes permission problem when restoring backup This PR changes the owner of the file used by the docker container that resets the mysql root password. Original problem is the failure to restore mysql:5.7.x backup. The error occurs because the container process tries to update the file that owned by the others. Story: 2010467 Task: 47017 Change-Id: I3d8ebaac4ee5e13af83c305ce28b51e4442d8c8b --- backup/Dockerfile | 2 +- trove/guestagent/datastore/mysql_common/manager.py | 90 +++++++++++++++------- 2 files changed, 62 insertions(+), 30 deletions(-) diff --git a/backup/Dockerfile b/backup/Dockerfile index 3827bfc7..0d542db2 100644 --- a/backup/Dockerfile +++ b/backup/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 LABEL maintainer="anlin.kong@gmail.com" ARG DATASTORE="mysql5.7" diff --git a/trove/guestagent/datastore/mysql_common/manager.py b/trove/guestagent/datastore/mysql_common/manager.py index cd6546a1..890981fc 100644 --- a/trove/guestagent/datastore/mysql_common/manager.py +++ b/trove/guestagent/datastore/mysql_common/manager.py @@ -205,43 +205,75 @@ class MySqlManager(manager.Manager): root_pass = utils.generate_random_password() self.app.save_password('root', root_pass) - with tempfile.NamedTemporaryFile(mode='w') as init_file, \ - tempfile.NamedTemporaryFile(suffix='.err') as err_file: - operating_system.write_file( - init_file.name, - f"ALTER USER 'root'@'localhost' IDENTIFIED BY '{root_pass}';" - ) - command = ( - f'mysqld_safe --init-file={init_file.name} ' - f'--log-error={err_file.name} ' - f'--datadir={data_dir}' - ) - extra_volumes = { - init_file.name: {"bind": init_file.name, "mode": "rw"}, - err_file.name: {"bind": err_file.name, "mode": "rw"}, - } - - # Allow database service user to access the temporary files. + init_file = tempfile.NamedTemporaryFile(mode='w') + operating_system.write_file( + init_file.name, + f"ALTER USER 'root'@'localhost' IDENTIFIED BY '{root_pass}';" + ) + err_file = tempfile.NamedTemporaryFile(suffix='.err') + + # Get the original file owner and group before changing the owner. + from pathlib import Path + init_file_path = Path(init_file.name) + init_file_owner = init_file_path.owner() + init_file_group = init_file_path.group() + + # Allow database service user to access the temporary files. + try: for file in [init_file.name, err_file.name]: - operating_system.chmod(file, - operating_system.FileMode.SET_ALL_RWX(), - force=True, as_root=True) + operating_system.chown(file, CONF.database_service_uid, + CONF.database_service_uid, force=True, + as_root=True) + except Exception as err: + LOG.error('Failed to change file owner, error: %s', str(err)) + for file in [init_file.name, err_file.name]: + LOG.debug('Reverting the %s owner to %s ' + 'before close it.', file, init_file_owner) + operating_system.chown(file, init_file_owner, + init_file_group, force=True, + as_root=True) + init_file.close() + err_file.close() + raise err + + # Allow database service user to access the temporary files. + command = ( + f'mysqld --init-file={init_file.name} ' + f'--log-error={err_file.name} ' + f'--datadir={data_dir} ' + ) + extra_volumes = { + init_file.name: {"bind": init_file.name, "mode": "rw"}, + err_file.name: {"bind": err_file.name, "mode": "rw"}, + } + # Start the database container process. + try: + self.app.start_db(ds_version=ds_version, command=command, + extra_volumes=extra_volumes) + except Exception as err: + LOG.error('Failed to reset password for restore, error: %s', + str(err)) + raise err # re-raised at the end of the finally clause + finally: try: - self.app.start_db(ds_version=ds_version, command=command, - extra_volumes=extra_volumes) - except Exception as err: - LOG.error('Failed to reset password for restore, error: %s', - str(err)) - LOG.debug('Content in init error log file: %s', - err_file.read()) - raise err - finally: LOG.debug( 'The init container log: %s', docker_util.get_container_logs(self.app.docker_client) ) docker_util.remove_container(self.app.docker_client) + except Exception as err: + LOG.error('Failed to remove container. error: %s', + str(err)) + pass + for file in [init_file.name, err_file.name]: + LOG.debug('Reverting the %s owner to %s ' + 'before close it.', file, init_file_owner) + operating_system.chown(file, init_file_owner, + init_file_group, force=True, + as_root=True) + init_file.close() + err_file.close() LOG.info('Finished to reset password for restore') -- cgit v1.2.1