Action to always populate container image parameters

Currently the UI cannot deploy with containers because the mandatory
container parameters are not set. Also a CLI will not deploy unless
passed an environment generated by the "images prepare" call.

This change adds an action in the create_deployment_plan and
update_deployment_plan workflows which does a container prepare with
the default options, so that the mandatory image parameters are always
populated with values which will work.

Change-Id: Ibce7658468c1b3689a7481deb94dd43e1f3ead52
Closes-Bug: #1716778
This commit is contained in:
Steve Baker 2017-09-12 21:50:55 +00:00
parent ba469be286
commit b7ddde426a
5 changed files with 236 additions and 4 deletions

View File

@ -77,6 +77,7 @@ mistral.actions =
tripleo.baremetal.probe_node = tripleo_common.actions.baremetal:ProbeNode tripleo.baremetal.probe_node = tripleo_common.actions.baremetal:ProbeNode
tripleo.config.download_config = tripleo_common.actions.config:DownloadConfigAction tripleo.config.download_config = tripleo_common.actions.config:DownloadConfigAction
tripleo.config.get_overcloud_config = tripleo_common.actions.config:GetOvercloudConfig tripleo.config.get_overcloud_config = tripleo_common.actions.config:GetOvercloudConfig
tripleo.container_images.prepare = tripleo_common.actions.container_images:PrepareContainerImageEnv
tripleo.deployment.config = tripleo_common.actions.deployment:OrchestrationDeployAction tripleo.deployment.config = tripleo_common.actions.deployment:OrchestrationDeployAction
tripleo.deployment.deploy = tripleo_common.actions.deployment:DeployStackAction tripleo.deployment.deploy = tripleo_common.actions.deployment:DeployStackAction
tripleo.deployment.overcloudrc = tripleo_common.actions.deployment:OvercloudRcAction tripleo.deployment.overcloudrc = tripleo_common.actions.deployment:OvercloudRcAction

View File

@ -0,0 +1,83 @@
# Copyright 2017 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import os
import sys
from mistral_lib import actions
from swiftclient import exceptions as swiftexceptions
import yaml
from tripleo_common.actions import base
from tripleo_common.actions import heat_capabilities
from tripleo_common import constants
from tripleo_common.image import kolla_builder
LOG = logging.getLogger(__name__)
class PrepareContainerImageEnv(base.TripleOAction):
"""Populates env parameters with results from container image prepare
:param container: Name of the Swift container / plan name
"""
def __init__(self, container):
super(PrepareContainerImageEnv, self).__init__()
self.container = container
def run(self, context):
def ffunc(entry):
return entry
template_file = os.path.join(sys.prefix, 'share', 'tripleo-common',
'container-images',
'overcloud_containers.yaml.j2')
builder = kolla_builder.KollaImageBuilder([template_file])
result = builder.container_images_from_template(filter=ffunc)
params = {}
for entry in result:
imagename = entry.get('imagename', '')
if 'params' in entry:
for p in entry.pop('params'):
params[p] = imagename
swift = self.get_object_client(context)
try:
swift.put_object(
self.container,
constants.CONTAINER_DEFAULTS_ENVIRONMENT,
yaml.safe_dump(
{'parameter_defaults': params},
default_flow_style=False
)
)
except swiftexceptions.ClientException as err:
err_msg = ("Error updating %s for plan %s: %s" % (
constants.CONTAINER_DEFAULTS_ENVIRONMENT,
self.container, err))
LOG.exception(err_msg)
return actions.Result(error=err_msg)
environments = {constants.CONTAINER_DEFAULTS_ENVIRONMENT: True}
update_action = heat_capabilities.UpdateCapabilitiesAction(
environments, container=self.container)
return update_action.run(context)

View File

@ -127,6 +127,10 @@ DEFAULT_VOLUME_API_VERSION = '3'
# import/export # import/export
PLAN_ENVIRONMENT = 'plan-environment.yaml' PLAN_ENVIRONMENT = 'plan-environment.yaml'
# The name of the file which holds container image default parameters
CONTAINER_DEFAULTS_ENVIRONMENT = ('environments/'
'containers-default-parameters.yaml')
DEFAULT_DEPLOY_KERNEL_NAME = 'bm-deploy-kernel' DEFAULT_DEPLOY_KERNEL_NAME = 'bm-deploy-kernel'
DEFAULT_DEPLOY_RAMDISK_NAME = 'bm-deploy-ramdisk' DEFAULT_DEPLOY_RAMDISK_NAME = 'bm-deploy-ramdisk'

View File

@ -0,0 +1,118 @@
# Copyright 2017 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import sys
import mock
from swiftclient import exceptions as swiftexceptions
import yaml
from mistral_lib import actions
from tripleo_common.actions import container_images
from tripleo_common.tests import base
image_entries = [{
'imagename': 't/cb-nova-compute:liberty',
'params': ['DockerNovaComputeImage', 'DockerNovaLibvirtConfigImage']
}, {
'imagename': 't/cb-nova-libvirt:liberty',
'params': ['DockerNovaLibvirtImage']
}]
class PrepareContainerImageEnvTest(base.TestCase):
def setUp(self):
super(PrepareContainerImageEnvTest, self).setUp()
self.ctx = mock.MagicMock()
@mock.patch("tripleo_common.actions.container_images."
"PrepareContainerImageEnv.get_object_client")
@mock.patch("tripleo_common.actions.heat_capabilities."
"UpdateCapabilitiesAction")
@mock.patch("tripleo_common.image.kolla_builder.KollaImageBuilder")
def test_run(self, kib, update_action, goc):
swift = goc.return_value
builder = kib.return_value
builder.container_images_from_template.return_value = image_entries
final_env = {'environments': [
{'path': 'overcloud-resource-registry-puppet.yaml'},
{'path': 'environments/containers-default-parameters.yaml'},
{'path': 'user-environment.yaml'}
]}
update_action.return_value.run.return_value = final_env
action = container_images.PrepareContainerImageEnv(
container='overcloud')
self.assertEqual(final_env, action.run(self.ctx))
kib.assert_called_once_with(
[os.path.join(sys.prefix, 'share', 'tripleo-common',
'container-images', 'overcloud_containers.yaml.j2')]
)
params = {
'DockerNovaComputeImage': 't/cb-nova-compute:liberty',
'DockerNovaLibvirtConfigImage': 't/cb-nova-compute:liberty',
'DockerNovaLibvirtImage': 't/cb-nova-libvirt:liberty',
}
expected_env = yaml.safe_dump(
{'parameter_defaults': params},
default_flow_style=False
)
swift.put_object.assert_called_once_with(
'overcloud',
'environments/containers-default-parameters.yaml',
expected_env
)
update_action.assert_called_once_with(
{'environments/containers-default-parameters.yaml': True},
container='overcloud'
)
@mock.patch("tripleo_common.actions.container_images."
"PrepareContainerImageEnv.get_object_client")
@mock.patch("tripleo_common.actions.heat_capabilities."
"UpdateCapabilitiesAction")
@mock.patch("tripleo_common.image.kolla_builder.KollaImageBuilder")
def test_run_failed(self, kib, update_action, goc):
swift = goc.return_value
builder = kib.return_value
builder.container_images_from_template.return_value = image_entries
final_env = {'environments': [
{'path': 'overcloud-resource-registry-puppet.yaml'},
{'path': 'environments/containers-default-parameters.yaml'},
{'path': 'user-environment.yaml'}
]}
update_action.return_value.run.return_value = final_env
action = container_images.PrepareContainerImageEnv(
container='overcloud')
self.assertEqual(final_env, action.run(self.ctx))
update_action.return_value.run.return_value = actions.Result(
error='Error updating environment for plan overcloud: ouch')
self.assertEqual(
'Error updating environment for plan overcloud: ouch',
action.run(self.ctx).error
)
swift.put_object.side_effect = swiftexceptions.ClientException('nope')
self.assertEqual(
'Error updating environments/containers-default-parameters.yaml '
'for plan overcloud: nope',
action.run(self.ctx).error
)

View File

@ -123,14 +123,21 @@ workflows:
action: tripleo.plan.migrate plan=<% $.container %> action: tripleo.plan.migrate plan=<% $.container %>
on-success: on-success:
- ensure_passwords_exist: <% $.generate_passwords = true %> - ensure_passwords_exist: <% $.generate_passwords = true %>
- process_templates: <% $.generate_passwords != true %> - container_images_prepare: <% $.generate_passwords != true %>
on-error: migrate_plan_set_status_failed on-error: migrate_plan_set_status_failed
ensure_passwords_exist: ensure_passwords_exist:
action: tripleo.parameters.generate_passwords container=<% $.container %> action: tripleo.parameters.generate_passwords container=<% $.container %>
on-success: process_templates on-success: container_images_prepare
on-error: ensure_passwords_exist_set_status_failed on-error: ensure_passwords_exist_set_status_failed
container_images_prepare:
description: >
Populate all container image parameters with default values.
action: tripleo.container_images.prepare container=<% $.container %>
on-success: process_templates
on-error: container_images_prepare_set_status_failed
process_templates: process_templates:
action: tripleo.templates.process container=<% $.container %> action: tripleo.templates.process container=<% $.container %>
on-success: set_status_success on-success: set_status_success
@ -184,6 +191,12 @@ workflows:
status: FAILED status: FAILED
message: <% task(create_plan).result %> message: <% task(create_plan).result %>
container_images_prepare_set_status_failed:
on-success: notify_zaqar
publish:
status: FAILED
message: <% task(create_plan).result %>
notify_zaqar: notify_zaqar:
action: zaqar.queue_post action: zaqar.queue_post
retry: count=5 delay=1 retry: count=5 delay=1
@ -244,14 +257,21 @@ workflows:
action: tripleo.plan.migrate plan=<% $.container %> action: tripleo.plan.migrate plan=<% $.container %>
on-success: on-success:
- ensure_passwords_exist: <% $.generate_passwords = true %> - ensure_passwords_exist: <% $.generate_passwords = true %>
- process_templates: <% $.generate_passwords != true %> - container_images_prepare: <% $.generate_passwords != true %>
on-error: migrate_plan_set_status_failed on-error: migrate_plan_set_status_failed
ensure_passwords_exist: ensure_passwords_exist:
action: tripleo.parameters.generate_passwords container=<% $.container %> action: tripleo.parameters.generate_passwords container=<% $.container %>
on-success: process_templates on-success: container_images_prepare
on-error: ensure_passwords_exist_set_status_failed on-error: ensure_passwords_exist_set_status_failed
container_images_prepare:
description: >
Populate all container image parameters with default values.
action: tripleo.container_images.prepare container=<% $.container %>
on-success: process_templates
on-error: container_images_prepare_set_status_failed
process_templates: process_templates:
action: tripleo.templates.process container=<% $.container %> action: tripleo.templates.process container=<% $.container %>
on-success: set_status_success on-success: set_status_success
@ -299,6 +319,12 @@ workflows:
status: FAILED status: FAILED
message: <% task(update_plan).result %> message: <% task(update_plan).result %>
container_images_prepare_set_status_failed:
on-success: notify_zaqar
publish:
status: FAILED
message: <% task(create_plan).result %>
notify_zaqar: notify_zaqar:
action: zaqar.queue_post action: zaqar.queue_post
retry: count=5 delay=1 retry: count=5 delay=1