tripleo-common/tripleo_common/actions/heat_capabilities.py

231 lines
8.5 KiB
Python

# Copyright 2016 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 fnmatch
import logging
import yaml
from mistral_lib import actions
from swiftclient import exceptions as swiftexceptions
from tripleo_common.actions import base
from tripleo_common import constants
from tripleo_common.utils import plan as plan_utils
from tripleo_common.utils import swift as swiftutils
LOG = logging.getLogger(__name__)
class GetCapabilitiesAction(base.TripleOAction):
"""Gets list of available heat environments
Parses the capabilities_map.yaml file in a given plan and
returns a list of environments
:param container: name of the swift container / plan name
:return: list of environment files in swift container
"""
def __init__(self, container=constants.DEFAULT_CONTAINER_NAME):
super(GetCapabilitiesAction, self).__init__()
self.container = container
def run(self, context):
try:
swift = self.get_object_client(context)
map_file = swiftutils.get_object_string(swift,
self.container,
'capabilities-map.yaml')
capabilities = yaml.safe_load(map_file)
except Exception:
err_msg = (
"Error parsing capabilities-map.yaml.")
LOG.exception(err_msg)
return actions.Result(error=err_msg)
try:
container_files = swift.get_container(self.container)
container_file_list = [entry['name'] for entry
in container_files[1]]
except Exception as swift_err:
err_msg = ("Error retrieving plan files: %s" % swift_err)
LOG.exception(err_msg)
return actions.Result(error=err_msg)
try:
env = plan_utils.get_env(swift, self.container)
except swiftexceptions.ClientException as err:
err_msg = ("Error retrieving environment for plan %s: %s" % (
self.container, err))
LOG.exception(err_msg)
return actions.Result(error=err_msg)
selected_envs = [item['path'] for item in env['environments']
if 'path' in item]
# extract environment files
plan_environments = []
for env_group in capabilities['topics']:
for envs in env_group['environment_groups']:
for files in envs['environments']:
file = files.get('file')
if file:
plan_environments.append(file)
# parse plan for environment files
env_files = fnmatch.filter(
container_file_list, '*environments/*.yaml')
env_user_files = fnmatch.filter(
container_file_list, '*user-environment.yaml')
outstanding_envs = list(set(env_files).union(
env_user_files) - set(plan_environments))
# change capabilities format
data_to_return = {}
for topic in capabilities['topics']:
title = topic.get('title', '_title_holder')
data_to_return[title] = topic
for eg in topic['environment_groups']:
for env in eg['environments']:
if selected_envs and env.get('file') in selected_envs:
env['enabled'] = True
else:
env['enabled'] = False
# add custom environment files
other_environments = []
for env in outstanding_envs:
flag = selected_envs and env in selected_envs
new_env = {
"description": "Enable %s environment" % env,
"enabled": flag,
"file": env,
"title": env,
}
other_environments.append(new_env)
other_environments.sort(key=lambda x: x['file'])
other_environment_groups = []
for group in other_environments:
new_group = {
"description": None,
"environments": [group],
"title": group['file'],
}
other_environment_groups.append(new_group)
other_environments_topic_dict = {
"description": None,
"title": "Other",
"environment_groups": other_environment_groups
}
other_environments_topic = {
"Other": other_environments_topic_dict
}
data_to_return.update(other_environments_topic)
return data_to_return
class UpdateCapabilitiesAction(base.TripleOAction):
"""Updates plan environment with selected environments
Takes a list of environment files and depending on the value of the
enabled flag, adds or removes them from the plan environment.
:param environments: map of environments {'environment_path': True}
the value passed can be false for disabled
environments, these will be removed from the
plan environment.
:param container: name of the swift container / plan name
:param purge_missing: remove any environments from the plan environment
that aren't included in the environments map
defaults to False
:param sort_environments: use the dependencies defined in the
capabilites-map.yaml file in the plan to order
the environments
:return: the updated plan environment
"""
def __init__(self, environments,
container=constants.DEFAULT_CONTAINER_NAME,
purge_missing=False, sort_environments=False):
super(UpdateCapabilitiesAction, self).__init__()
self.container = container
self.environments = environments
self.purge_missing = purge_missing
self.sort_environments = sort_environments
def run(self, context):
swift = self.get_object_client(context)
try:
env = plan_utils.get_env(swift, self.container)
except swiftexceptions.ClientException as err:
err_msg = ("Error retrieving environment for plan %s: %s" % (
self.container, err))
LOG.exception(err_msg)
return actions.Result(error=err_msg)
for k, v in self.environments.items():
found = False
if {'path': k} in env['environments']:
found = True
if v:
if not found:
env['environments'].append({'path': k})
else:
if found:
env['environments'].remove({'path': k})
if self.purge_missing:
for e in env['environments']:
if e.get('path') not in self.environments:
env['environments'].remove(e)
self.cache_delete(context, self.container, "tripleo.parameters.get")
if self.sort_environments:
# get the capabilities-map content to perform the environment
# ordering
try:
swift = self.get_object_client(context)
map_file = swiftutils.get_object_string(
swift,
self.container,
'capabilities-map.yaml')
capabilities = yaml.safe_load(map_file)
except swiftexceptions.ClientException as err:
err_msg = ("Error retrieving capabilities-map.yaml for "
"plan %s: %s" % (self.container, err))
LOG.exception(err_msg)
return actions.Result(error=err_msg)
ordered_env = plan_utils.apply_environments_order(
capabilities, env.get('environments', []))
env['environments'] = ordered_env
try:
plan_utils.put_env(swift, env)
except swiftexceptions.ClientException as err:
err_msg = "Error uploading to container: %s" % err
LOG.exception(err_msg)
return actions.Result(error=err_msg)
return env