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 <angie.wang@windriver.com>
This commit is contained in:
Angie Wang 2019-02-22 01:21:07 -05:00
parent 234c04aee2
commit cb4b30bf56
2 changed files with 55 additions and 34 deletions

View File

@ -1,2 +1,2 @@
SRC_DIR="sysinv" SRC_DIR="sysinv"
TIS_PATCH_VER=305 TIS_PATCH_VER=306

View File

@ -309,30 +309,26 @@ class AppOperator(object):
image_tags = [] image_tags = []
ids = [] ids = []
for r, f in cutils.get_files_matching(path, 'values.yaml'): 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: try:
y = yaml.load(file) y = yaml.load(value_f)
ids = y["images"]["tags"].values() ids = y["images"]["tags"].values()
except (TypeError, KeyError): except (TypeError, KeyError):
pass pass
image_tags.extend(ids) image_tags.extend(ids)
return list(set(image_tags)) return list(set(image_tags))
def _get_image_tags_by_charts(self, app_path, charts): def _get_image_tags_by_charts(self, app_images_file, charts):
""" Mine the image tags from the chart paths. Add the converted """ Mine the image tags for charts from the images file. Add the
image tags to the overrides if the image tags from the chart converted image tags to the overrides if the image tags from
paths do not exist. Intended for system app. the charts do not exist. Intended for system app.
The image tagging conversion(local docker registry address prepended): The image tagging conversion(local docker registry address prepended):
${LOCAL_DOCKER_REGISTRY_IP}:${REGISTRY_PORT}/<image-name> ${LOCAL_DOCKER_REGISTRY_IP}:${REGISTRY_PORT}/<image-name>
(ie..192.168.204.2:9001/docker.io/mariadb:10.2.13) (ie..192.168.204.2:9001/docker.io/mariadb:10.2.13)
""" """
local_docker_registry_ip = self._dbapi.address_get_by_name( local_registry_server = self._docker.get_local_docker_registry_server()
cutils.format_address_name(constants.CONTROLLER_HOSTNAME,
constants.NETWORK_TYPE_MGMT)
).address
image_tags = [] image_tags = []
for chart in charts: for chart in charts:
images_charts = {} images_charts = {}
@ -340,23 +336,21 @@ class AppOperator(object):
overrides = chart.namespace + '-' + chart.name + '.yaml' overrides = chart.namespace + '-' + chart.name + '.yaml'
overrides_file = os.path.join(common.HELM_OVERRIDES_PATH, overrides_file = os.path.join(common.HELM_OVERRIDES_PATH,
overrides) 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 # Get the image tags by chart from the images file
if os.path.exists(chart_path): if os.path.exists(app_images_file):
with open(chart_path, 'r') as file: with open(app_images_file, 'r') as f:
try: try:
doc = yaml.load(file) doc = yaml.load(f)
images_charts = doc["images"]["tags"] images_charts = doc[chart.name]
except (TypeError, KeyError): except (TypeError, KeyError):
pass pass
# Get the image tags from the overrides file # Get the image tags from the overrides file
if os.path.exists(overrides_file): if os.path.exists(overrides_file):
with open(overrides_file, 'r') as file: with open(overrides_file, 'r') as f:
try: try:
y = yaml.load(file) y = yaml.load(f)
images_overrides = y["data"]["values"]["images"]["tags"] images_overrides = y["data"]["values"]["images"]["tags"]
except (TypeError, KeyError): except (TypeError, KeyError):
LOG.info("Overrides file %s has no img tags" % LOG.info("Overrides file %s has no img tags" %
@ -368,22 +362,22 @@ class AppOperator(object):
tags_updated = False tags_updated = False
for key, image_tag in images_charts.items(): for key, image_tag in images_charts.items():
if (key not in images_overrides and 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( images_overrides.update(
{key: '{}:{}/{}'.format(local_docker_registry_ip, common.REGISTRY_PORT, image_tag)}) {key: '{}/{}'.format(local_registry_server, image_tag)})
tags_updated = True tags_updated = True
if tags_updated: if tags_updated:
with open(overrides_file, 'w') as file: with open(overrides_file, 'w') as f:
try: try:
if "images" not in y["data"]["values"]: if "images" not in y["data"]["values"]:
file.seek(0) f.seek(0)
file.truncate() f.truncate()
y["data"]["values"]["images"] = {"tags": images_overrides} y["data"]["values"]["images"] = {"tags": images_overrides}
else: else:
y["data"]["values"]["images"]["tags"] = images_overrides 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) default_flow_style=False)
LOG.info("Overrides file %s updated with new image tags" % LOG.info("Overrides file %s updated with new image tags" %
overrides_file) overrides_file)
@ -421,9 +415,10 @@ class AppOperator(object):
self._helm.generate_helm_application_overrides( self._helm.generate_helm_application_overrides(
app.name, cnamespace=None, armada_format=True, combined=True) app.name, cnamespace=None, armada_format=True, combined=True)
app.charts = self._get_list_of_charts(app.armada_mfile_abs) 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 # Get the list of images from the updated images overrides
images_to_download = self._get_image_tags_by_charts( images_to_download = self._get_image_tags_by_charts(
app.charts_dir, app.charts) app.imgfile_abs, app.charts)
else: else:
# For custom apps, mine image tags from application path # For custom apps, mine image tags from application path
images_to_download = self._get_image_tags_by_path(app.path) images_to_download = self._get_image_tags_by_path(app.path)
@ -436,8 +431,31 @@ class AppOperator(object):
name=app.name, name=app.name,
reason="charts specify no docker images.") 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: 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) default_flow_style=False)
def _retrieve_images_list(self, app_images_file): def _retrieve_images_list(self, app_images_file):
@ -454,16 +472,19 @@ class AppOperator(object):
# between upload and apply, or between applies. Refresh the # between upload and apply, or between applies. Refresh the
# saved images list. # saved images list.
saved_images_list = self._retrieve_images_list(app.imgfile_abs) 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( 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)) 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: 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) default_flow_style=False)
else: 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) total_count = len(images_to_download)
threads = min(MAX_DOWNLOAD_THREAD, total_count) threads = min(MAX_DOWNLOAD_THREAD, total_count)