From a1038f30366f95aef7cf0b1df8f695a638fc499e Mon Sep 17 00:00:00 2001 From: Sofer Athlan-Guyot Date: Thu, 18 Oct 2018 12:21:25 +0200 Subject: [PATCH] Update stackrc to v3 auth values when --use-heat is false. During pike we have updated the deployment to use v3 authentication in stackrc. But we didn't upgrade the existing stackrc. We didn't use it in the code so it was not a problem. But in queens, when we use '--use-heat' is false, we check the status of the overcloud before starting and we load auth url from stackrc and force domain in the api request. So we have a v2 url and a v3 request. That fails. Now, we make sure that the stackrc is in v3 version before starting the undercloud upgrade in queens when we use --use-heat set to false. Change-Id: I3f008b9466408fe797ca50ebf96651a72fc9a544 Closes-Bug: #1798553 --- instack_undercloud/undercloud.py | 65 ++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/instack_undercloud/undercloud.py b/instack_undercloud/undercloud.py index eb4287bc7..4805dd6a4 100644 --- a/instack_undercloud/undercloud.py +++ b/instack_undercloud/undercloud.py @@ -25,6 +25,7 @@ import netaddr import os import platform import re +import shutil import socket import subprocess import sys @@ -66,6 +67,10 @@ class Paths(object): def ANSWERS_PATH(self): return os.path.expanduser('~/instack.answers') + @property + def STACKRC(self): + return os.path.expanduser('~/stackrc') + @property def PASSWORD_PATH(self): return os.path.expanduser('~/undercloud-passwords.conf') @@ -845,7 +850,7 @@ def _validate_passwords_file(): is missing it will break the undercloud, so we should fail-fast and let the user know about the problem. """ - if (os.path.isfile(os.path.expanduser('~/stackrc')) and + if (os.path.isfile(PATHS.STACKRC) and not os.path.isfile(PATHS.PASSWORD_PATH)): message = ('The %s file is missing. This will cause all service ' 'passwords to change and break the existing undercloud. ' % @@ -1605,13 +1610,65 @@ def _extract_from_stackrc(name): :param name: The value to be extracted. For example: OS_USERNAME or OS_AUTH_URL. """ - with open(os.path.expanduser('~/stackrc')) as f: + with open(PATHS.STACKRC) as f: for line in f: if name in line: parts = line.split('=') return parts[1].rstrip() +def _stackrc_v2_needs_upgrade(line): + number_of_seps = len(re.findall('=', line)) + if line.lstrip().startswith("#") or \ + number_of_seps != 1: + return False + (key, value) = line.split('=') + if key == 'OS_AUTH_URL' and 'v2.0' in value: + return True + if key == 'OS_TENANT_NAME': + return True + return False + + +def _stackrc_v2_v3(line): + """Change v2 auth url and parameters to v3 or return unmodified line.""" + + final_line = line + extra_v3_config = """OS_IDENTITY_API_VERSION='3' +export OS_IDENTITY_API_VERSION +OS_PROJECT_DOMAIN_NAME='Default' +export OS_PROJECT_DOMAIN_NAME +OS_USER_DOMAIN_NAME='Default' +export OS_USER_DOMAIN_NAME +""" + if _stackrc_v2_needs_upgrade(line): + LOG.info("stackrc needs upgrade, because of line {}".format(line)) + if 'OS_AUTH_URL' in line: + final_line = "OS_AUTH_URL={}\n{}".format( + line.replace('v2.0', ''), + extra_v3_config) + if 'OS_TENANT_NAME' in line: + final_line = line.replace('OS_TENANT_NAME', 'OS_PROJECT_NAME') + return final_line + + +def _stackrc_upgrade_to_v3(): + """Make sure stackrc has v3 authorisation url and paramaters.""" + + try: + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + with open(PATHS.STACKRC) as stackrc_src: + for line in stackrc_src: + tmp_file.write(_stackrc_v2_v3(line)) + + # Preserve perm and ensure atomic writing. + shutil.copystat(PATHS.STACKRC, tmp_file.name) + shutil.move(tmp_file.name, PATHS.STACKRC) + finally: + if os.path.exists(tmp_file.name): + os.remove(tmp_file.name) + + def _ensure_user_identity(id_path): if not os.path.isfile(id_path): args = ['ssh-keygen', '-t', 'rsa', '-N', '', '-f', id_path] @@ -2352,7 +2409,7 @@ def install(instack_root, upgrade=False): LOG.info(COMPLETION_MESSAGE, {'undercloud_operation': undercloud_operation, 'password_path': PATHS.PASSWORD_PATH, - 'stackrc_path': os.path.expanduser('~/stackrc')}) + 'stackrc_path': PATHS.STACKRC}) def _is_database_upgrade_needed(): @@ -2398,6 +2455,8 @@ def _is_database_upgrade_needed(): def pre_upgrade(): _configure_logging(DEFAULT_LOG_LEVEL, PATHS.LOG_FILE) + _stackrc_upgrade_to_v3() + # Don't upgrade undercloud unless overcloud is in *_COMPLETE. # As we're migrating overcloud stack to convergence in post_config, # which would fail otherwise. It's better to fail fast.