diff --git a/setup.cfg b/setup.cfg index 0b6a635dc..2ae449ca7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -99,6 +99,7 @@ mistral.actions = tripleo.deployment.get_deployment_status = tripleo_common.actions.deployment:DeploymentStatusAction tripleo.deployment.convert_status = tripleo_common.actions.deployment:ConvertStatusAction tripleo.deployment.overcloudrc = tripleo_common.actions.deployment:OvercloudRcAction + tripleo.deployment.createcloudsyaml = tripleo_common.actions.deployment:CreateCloudsYamlAction tripleo.derive_params.convert_number_to_range_list = tripleo_common.actions.derive_params:ConvertNumberToRangeListAction tripleo.derive_params.convert_range_to_number_list = tripleo_common.actions.derive_params:ConvertRangeToNumberListAction tripleo.derive_params.get_dpdk_nics_numa_info = tripleo_common.actions.derive_params:GetDpdkNicsNumaInfoAction @@ -181,4 +182,4 @@ exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,releasenotes builtins = _ [pycodestyle] -exclude = .eggs,.tox \ No newline at end of file +exclude = .eggs,.tox diff --git a/tripleo_common/actions/deployment.py b/tripleo_common/actions/deployment.py index 1e6a3ad0c..2ca847c1d 100644 --- a/tripleo_common/actions/deployment.py +++ b/tripleo_common/actions/deployment.py @@ -12,6 +12,7 @@ # 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 json import logging import os @@ -322,6 +323,45 @@ class OvercloudRcAction(base.TripleOAction): region_name) +class CreateCloudsYamlAction(base.TripleOAction): + """Generate the overcloud clouds.yaml contents for a plan + + Given the name of a container, generate the overcloud clouds.yaml + contents needed to access the overcloud via the CLI. + """ + + def __init__(self, container): + super(CreateCloudsYamlAction, self).__init__() + self.container = container + + def run(self, context): + orchestration_client = self.get_orchestration_client(context) + swift = self.get_object_client(context) + stack = orchestration_client.stacks.get(self.container) + env = plan_utils.get_env(swift, self.container) + parameter_defaults = env['parameter_defaults'] + passwords = env['passwords'] + # Retrive values for cloud from a stack + admin_pass = parameter_defaults.get('AdminPassword', + passwords['AdminPassword']) + region_name = parameter_defaults.get('KeystoneRegion', 'regionOne') + cloud_name = stack.stack_name + auth_url = overcloudrc.get_overcloud_endpoint(stack).replace('/v2.0', + '') + + # Create a dict needed for creating clouds.yaml + cloud = {cloud_name: {'auth': {'auth_url': auth_url, + 'project_name': 'admin', + 'project_domain_name': 'Default', + 'username': 'admin', + 'user_domain_name': 'Default', + 'password': admin_pass}, + 'region_name': region_name, + 'identity_api_version': 3}} + + return cloud + + class DeploymentFailuresAction(base.TripleOAction): """Return all of the failures (if any) from deploying the plan diff --git a/tripleo_common/constants.py b/tripleo_common/constants.py index 194d86997..2779711f2 100644 --- a/tripleo_common/constants.py +++ b/tripleo_common/constants.py @@ -215,3 +215,7 @@ MISTRAL_WORK_DIR = '/var/lib/mistral' EXCLUSIVE_NEUTRON_DRIVERS = ['ovn', 'openvswitch'] UPGRADE_STEPS_MAX = 6 + +# Global Directories for clouds.yaml +GLOBAL_OS_DIR = '/etc/openstack' +CLOUDS_YAML_FILE = 'clouds.yaml' diff --git a/tripleo_common/utils/clouds_yaml.py b/tripleo_common/utils/clouds_yaml.py new file mode 100644 index 000000000..1749830c6 --- /dev/null +++ b/tripleo_common/utils/clouds_yaml.py @@ -0,0 +1,74 @@ +# Copyright 2018, 2019 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 yaml + +from tripleo_common import constants + + +def _create_clouds_yaml(clouds_yaml): + if not os.path.isfile(clouds_yaml): + with open(clouds_yaml, "w") as f: + yaml.safe_dump({"clouds": {}}, f, default_flow_style=False) + os.chmod(clouds_yaml, 0o600) + + +def _create_clouds_yaml_dir(dir_path, user_id, group_id): + if not os.path.isdir(dir_path): + os.makedirs(dir_path) + os.chown(dir_path, user_id, group_id) + + +def _read_clouds_yaml(clouds_yaml): + with open(clouds_yaml, "r") as f: + clouds = yaml.safe_load(f) + if "clouds" not in clouds: + clouds.update({"clouds": {}}) + + return clouds + + +def _write_clouds_yaml(clouds_yaml, clouds): + with open(clouds_yaml, "w") as f: + yaml.safe_dump(clouds, f, default_flow_style=False) + + +def create_clouds_yaml(**kwargs): + """Generates clouds.yaml file + + :param cloud: dict containing cloud data + :param clouds_yaml_dir: Directory to create clouds.yaml file + :param user_id: User id of the user owning the file + :param group_id: Group id of the user owning the file + """ + + cloud = kwargs.get("cloud", None) + dir_path = kwargs.get("cloud_yaml_dir", constants.GLOBAL_OS_DIR) + clouds_yaml = os.path.join(dir_path, constants.CLOUDS_YAML_FILE) + user_id = kwargs.get("user_id", 0) + group_id = kwargs.get("group_id", 0) + + try: + _create_clouds_yaml_dir(dir_path, user_id, group_id) + _create_clouds_yaml(clouds_yaml) + user_clouds = _read_clouds_yaml(clouds_yaml) + user_clouds["clouds"].update(cloud) + _write_clouds_yaml(clouds_yaml, user_clouds) + os.chown(clouds_yaml, user_id, group_id) + print("The clouds.yaml file is at {0}".format(clouds_yaml)) + + except Exception as e: + print("Create clouds.yaml failed: {}".format(e)) diff --git a/workbooks/deployment.yaml b/workbooks/deployment.yaml index b7e5bd10d..8ff943ee5 100644 --- a/workbooks/deployment.yaml +++ b/workbooks/deployment.yaml @@ -754,6 +754,40 @@ workflows: execution: <% execution() %> message: <% $.get('message', '') %> + createcloudsyaml: + description: > + Generates the overcloud clouds.yaml + It requires container and queue name as a input. + + tags: + - tripleo-common-managed + + input: + - container: overcloud + - queue_name: tripleo + + tasks: + generate_cloudyaml: + action: tripleo.deployment.createcloudsyaml + input: + container: <% $.container %> + on-complete: send_message + publish-on-error: + status: FAILED + message: <% task().result %> + publish: + status: SUCCESS + message: <% task().result %> + + send_message: + workflow: tripleo.messaging.v1.send + input: + queue_name: <% $.queue_name %> + type: <% execution().name %> + status: <% $.status %> + execution: <% execution() %> + message: <% $.get('message', '') %> + get_deployment_status: description: > Get deployment status and update it if needed based on stack and