From 4c207bc0399f024f24c05446a6924875c0f7aaef Mon Sep 17 00:00:00 2001 From: Jeffrey Zhang Date: Mon, 10 Oct 2016 22:37:05 +0800 Subject: [PATCH] Fix rabbitmq upgrade permission issue During the upgrade from Mitaka to Newton, the uid/gid may change for the same image. Especially on Ubuntu, we moved to Ubuntu Xenial in Newton and it added systemd related user which break all the uid/gid during an upgrade. It will the permissions in all docker named volumes. This fix extends set_config.py to set the proper permission during container start. This is super light then add commands in extend_start.sh file or add ansible tasks. This patch just fixes rabbitmq case. Other services will be fixed in following patches. Partial-Bug: #1631503 Change-Id: Ib17027b97abbc9bf4e3cd503601b8010325b5c5b --- .../roles/rabbitmq/templates/rabbitmq.json.j2 | 12 +++++ docker/base/set_configs.py | 50 +++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/ansible/roles/rabbitmq/templates/rabbitmq.json.j2 b/ansible/roles/rabbitmq/templates/rabbitmq.json.j2 index 4e99cc2183..07987def37 100644 --- a/ansible/roles/rabbitmq/templates/rabbitmq.json.j2 +++ b/ansible/roles/rabbitmq/templates/rabbitmq.json.j2 @@ -25,5 +25,17 @@ "owner": "rabbitmq", "perm": "0600" } + ], + "permissions": [ + { + "path": "/var/lib/rabbitmq", + "owner": "rabbitmq:rabbitmq", + "recurse": true + }, + { + "path": "/var/log/kolla/rabbitmq", + "owner": "rabbitmq:rabbitmq", + "recurse": true + } ] } diff --git a/docker/base/set_configs.py b/docker/base/set_configs.py index 94bf24a6be..cd89992e08 100644 --- a/docker/base/set_configs.py +++ b/docker/base/set_configs.py @@ -14,6 +14,7 @@ import argparse import glob +import grp import json import logging import os @@ -29,7 +30,8 @@ LOG.setLevel(logging.INFO) def validate_config(config): - required_keys = {'source', 'dest', 'owner', 'perm'} + config_files_required_keys = {'source', 'dest', 'owner', 'perm'} + permissions_required_keys = {'path', 'owner'} if 'command' not in config: LOG.error('Config is missing required "command" key') @@ -38,7 +40,11 @@ def validate_config(config): # Validate config sections for data in config.get('config_files', list()): # Verify required keys exist. - if not data.viewkeys() >= required_keys: + if not data.viewkeys() >= config_files_required_keys: + LOG.error("Config is missing required keys: %s", data) + sys.exit(1) + for data in config.get('permissions', list()): + if not data.viewkeys() >= permissions_required_keys: LOG.error("Config is missing required keys: %s", data) sys.exit(1) @@ -189,6 +195,36 @@ def copy_config(config): f.write(config['command']) +def handle_permissions(config): + for permission in config.get('permissions', list()): + path = permission.get('path') + owner = permission.get('owner') + recurse = permission.get('recurse', False) + + if ':' in owner: + user, group = owner.split(':', 1) + if not group: + group = user + else: + user, group = owner, owner + + uid = pwd.getpwnam(user).pw_uid + gid = grp.getgrnam(group).gr_gid + + def set_perms(path, uid, gid): + LOG.info('Setting permission for %s', path) + os.chown(path, uid, gid) + + for dest in glob.glob(path): + set_perms(dest, uid, gid) + if recurse and os.path.isdir(dest): + for root, dirs, files in os.walk(dest): + for dir_ in dirs: + set_perms(os.path.join(root, dir_), uid, gid) + for file_ in files: + set_perms(os.path.join(root, file_), uid, gid) + + def execute_config_strategy(): config_strategy = os.environ.get("KOLLA_CONFIG_STRATEGY") LOG.info("Kolla config strategy set to: %s", config_strategy) @@ -196,12 +232,14 @@ def execute_config_strategy(): if config_strategy == "COPY_ALWAYS": copy_config(config) + handle_permissions(config) elif config_strategy == "COPY_ONCE": if os.path.exists('/configured'): LOG.info("The config strategy prevents copying new configs") sys.exit(0) else: copy_config(config) + handle_permissions(config) os.mknod('/configured') else: LOG.error('KOLLA_CONFIG_STRATEGY is not set properly') @@ -262,4 +300,10 @@ def main(): if __name__ == "__main__": - sys.exit(main()) + try: + exit_code = main() + except Exception: + exit_code = 1 + LOG.exception('Unexpected error:') + finally: + sys.exit(exit_code)