From 5e61519ac92822b959dffe63b76956cf0e9d0383 Mon Sep 17 00:00:00 2001 From: Angie Wang Date: Fri, 22 Feb 2019 01:21:07 -0500 Subject: [PATCH] Solve the stx-openstack reapply issue on controller-1 After stx-openstack applied, the stx-openstack reapply shouldn't trigger the charts reinstallation if there has no overrides changed for charts. However, the reinstallation happens after swacting active controller to controller-1 due to the generated images overrides on controller-1 are different from before. The images overrides generation requires walking through the stx-openstack charts stored under /scratch, but charts do not exist on controller-1's /scratch as it's an unreplicated filesystem. This causes the images overrides to differ between controller-1 and controller-0. This commit updates to walk through charts and get the images for charts during application-upload, then save the images list for each chart into the existing images file under aramda directory /opt/platform/armada. The images file would be used for retrieving the images for charts to generate images overrides. Closes-Bug: 1816173 Change-Id: I4f00c3031decb063f8f126d0c837acd4dde56fc3 Signed-off-by: Angie Wang (cherry picked from commit cb4b30bf56195456ac6b8bd11abf7e23f90f81a4) --- sysinv/sysinv/centos/build_srpm.data | 2 +- .../sysinv/sysinv/conductor/kube_app.py | 87 ++++++++++++------- 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/sysinv/sysinv/centos/build_srpm.data b/sysinv/sysinv/centos/build_srpm.data index db54b8f4eb..f1416f1edb 100644 --- a/sysinv/sysinv/centos/build_srpm.data +++ b/sysinv/sysinv/centos/build_srpm.data @@ -1,2 +1,2 @@ SRC_DIR="sysinv" -TIS_PATCH_VER=305 +TIS_PATCH_VER=306 diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py b/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py index 41c3b9b961..7130d26e99 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py @@ -309,30 +309,26 @@ class AppOperator(object): image_tags = [] ids = [] for r, f in cutils.get_files_matching(path, 'values.yaml'): - with open(os.path.join(r, f), 'r') as file: + with open(os.path.join(r, f), 'r') as value_f: try: - y = yaml.load(file) + y = yaml.load(value_f) ids = y["images"]["tags"].values() except (TypeError, KeyError): pass image_tags.extend(ids) return list(set(image_tags)) - def _get_image_tags_by_charts(self, app_path, charts): - """ Mine the image tags from the chart paths. Add the converted - image tags to the overrides if the image tags from the chart - paths do not exist. Intended for system app. + def _get_image_tags_by_charts(self, app_images_file, charts): + """ Mine the image tags for charts from the images file. Add the + converted image tags to the overrides if the image tags from + the charts do not exist. Intended for system app. The image tagging conversion(local docker registry address prepended): ${LOCAL_DOCKER_REGISTRY_IP}:${REGISTRY_PORT}/ (ie..192.168.204.2:9001/docker.io/mariadb:10.2.13) """ - local_docker_registry_ip = self._dbapi.address_get_by_name( - cutils.format_address_name(constants.CONTROLLER_HOSTNAME, - constants.NETWORK_TYPE_MGMT) - ).address - + local_registry_server = self._docker.get_local_docker_registry_server() image_tags = [] for chart in charts: images_charts = {} @@ -340,23 +336,21 @@ class AppOperator(object): overrides = chart.namespace + '-' + chart.name + '.yaml' overrides_file = os.path.join(common.HELM_OVERRIDES_PATH, overrides) - chart_name = os.path.join(app_path, chart.name) - chart_path = os.path.join(chart_name, 'values.yaml') - # Get the image tags from the chart path - if os.path.exists(chart_path): - with open(chart_path, 'r') as file: + # Get the image tags by chart from the images file + if os.path.exists(app_images_file): + with open(app_images_file, 'r') as f: try: - doc = yaml.load(file) - images_charts = doc["images"]["tags"] + doc = yaml.load(f) + images_charts = doc[chart.name] except (TypeError, KeyError): pass # Get the image tags from the overrides file if os.path.exists(overrides_file): - with open(overrides_file, 'r') as file: + with open(overrides_file, 'r') as f: try: - y = yaml.load(file) + y = yaml.load(f) images_overrides = y["data"]["values"]["images"]["tags"] except (TypeError, KeyError): LOG.info("Overrides file %s has no img tags" % @@ -368,22 +362,22 @@ class AppOperator(object): tags_updated = False for key, image_tag in images_charts.items(): if (key not in images_overrides and - not image_tag.startswith(local_docker_registry_ip)): + not image_tag.startswith(local_registry_server)): images_overrides.update( - {key: '{}:{}/{}'.format(local_docker_registry_ip, common.REGISTRY_PORT, image_tag)}) + {key: '{}/{}'.format(local_registry_server, image_tag)}) tags_updated = True if tags_updated: - with open(overrides_file, 'w') as file: + with open(overrides_file, 'w') as f: try: if "images" not in y["data"]["values"]: - file.seek(0) - file.truncate() + f.seek(0) + f.truncate() y["data"]["values"]["images"] = {"tags": images_overrides} else: y["data"]["values"]["images"]["tags"] = images_overrides - yaml.safe_dump(y, file, explicit_start=True, + yaml.safe_dump(y, f, explicit_start=True, default_flow_style=False) LOG.info("Overrides file %s updated with new image tags" % overrides_file) @@ -421,9 +415,10 @@ class AppOperator(object): self._helm.generate_helm_application_overrides( app.name, cnamespace=None, armada_format=True, combined=True) app.charts = self._get_list_of_charts(app.armada_mfile_abs) + self._save_images_list_by_charts(app) # Get the list of images from the updated images overrides images_to_download = self._get_image_tags_by_charts( - app.charts_dir, app.charts) + app.imgfile_abs, app.charts) else: # For custom apps, mine image tags from application path images_to_download = self._get_image_tags_by_path(app.path) @@ -436,8 +431,31 @@ class AppOperator(object): name=app.name, reason="charts specify no docker images.") + with open(app.imgfile_abs, 'ab') as f: + yaml.safe_dump({"download_images": images_to_download}, f, + default_flow_style=False) + + def _save_images_list_by_charts(self, app): + # Mine the images from values.yaml files in the charts directory. + # The list of images for each chart are saved to the images file. + images_by_charts = {} + for chart in app.charts: + images = {} + chart_name = os.path.join(app.charts_dir, chart.name) + chart_path = os.path.join(chart_name, 'values.yaml') + + if os.path.exists(chart_path): + with open(chart_path, 'r') as f: + try: + y = yaml.load(f) + images = y["images"]["tags"] + except (TypeError, KeyError): + LOG.warn("Chart %s has no image tags" % chart_name) + if images: + images_by_charts.update({chart.name: images}) + with open(app.imgfile_abs, 'wb') as f: - yaml.safe_dump(images_to_download, f, explicit_start=True, + yaml.safe_dump(images_by_charts, f, explicit_start=True, default_flow_style=False) def _retrieve_images_list(self, app_images_file): @@ -454,16 +472,19 @@ class AppOperator(object): # between upload and apply, or between applies. Refresh the # saved images list. saved_images_list = self._retrieve_images_list(app.imgfile_abs) - combined_images_list = list(saved_images_list) + saved_download_images_list = saved_images_list.get("download_images") + combined_images_list = list(saved_download_images_list) combined_images_list.extend( - self._get_image_tags_by_charts(app.charts_dir, app.charts)) + self._get_image_tags_by_charts(app.imgfile_abs, app.charts)) images_to_download = list(set(combined_images_list)) - if saved_images_list != images_to_download: + if set(saved_download_images_list) != set(images_to_download): + saved_images_list.update({"download_images": images_to_download}) with open(app.imgfile_abs, 'wb') as f: - yaml.safe_dump(images_to_download, f, explicit_start=True, + yaml.safe_dump(saved_images_list, f, explicit_start=True, default_flow_style=False) else: - images_to_download = self._retrieve_images_list(app.imgfile_abs) + images_to_download = self._retrieve_images_list( + app.imgfile_abs).get("download_images") total_count = len(images_to_download) threads = min(MAX_DOWNLOAD_THREAD, total_count)