1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
18 from heatclient.client import Client
19 from heatclient.common.template_format import yaml_loader
20 from oslo_serialization import jsonutils
22 from snaps import file_utils
23 from snaps.domain.stack import Stack
25 from snaps.openstack.utils import keystone_utils
27 __author__ = 'spisarski'
29 logger = logging.getLogger('heat_utils')
32 def heat_client(os_creds):
34 Retrieves the Heat client
35 :param os_creds: the OpenStack credentials
38 logger.debug('Retrieving Nova Client')
39 return Client(os_creds.heat_api_version,
40 session=keystone_utils.keystone_session(os_creds))
43 def get_stack_by_name(heat_cli, stack_name):
45 Returns a domain Stack object
46 :param heat_cli: the OpenStack heat client
47 :param stack_name: the name of the heat stack
48 :return: the Stack domain object else None
50 stacks = heat_cli.stacks.list(**{'name': stack_name})
52 return Stack(name=stack.identifier, stack_id=stack.id)
57 def get_stack_by_id(heat_cli, stack_id):
59 Returns a domain Stack object for a given ID
60 :param heat_cli: the OpenStack heat client
61 :param stack_id: the ID of the heat stack to retrieve
62 :return: the Stack domain object else None
64 stack = heat_cli.stacks.get(stack_id)
65 return Stack(name=stack.identifier, stack_id=stack.id)
68 def get_stack_status(heat_cli, stack_id):
70 Returns the current status of the Heat stack
71 :param heat_cli: the OpenStack heat client
72 :param stack_id: the ID of the heat stack to retrieve
75 return heat_cli.stacks.get(stack_id).stack_status
78 def get_stack_outputs(heat_cli, stack_id):
80 Returns a domain Stack object for a given ID
81 :param heat_cli: the OpenStack heat client
82 :param stack_id: the ID of the heat stack to retrieve
83 :return: the Stack domain object else None
85 stack = heat_cli.stacks.get(stack_id)
89 def create_stack(heat_cli, stack_settings):
91 Executes an Ansible playbook to the given host
92 :param heat_cli: the OpenStack heat client object
93 :param stack_settings: the stack configuration
94 :return: the Stack domain object
98 if stack_settings.template:
99 args['template'] = stack_settings.template
101 args['template'] = parse_heat_template_str(
102 file_utils.read_file(stack_settings.template_path))
103 args['stack_name'] = stack_settings.name
105 if stack_settings.env_values:
106 args['parameters'] = stack_settings.env_values
108 stack = heat_cli.stacks.create(**args)
110 return get_stack_by_id(heat_cli, stack_id=stack['stack']['id'])
113 def delete_stack(heat_cli, stack):
115 Deletes the Heat stack
116 :param heat_cli: the OpenStack heat client object
117 :param stack: the OpenStack Heat stack object
119 heat_cli.stacks.delete(stack.id)
122 def parse_heat_template_str(tmpl_str):
124 Takes a heat template string, performs some simple validation and returns a
125 dict containing the parsed structure. This function supports both JSON and
126 YAML Heat template formats.
128 if tmpl_str.startswith('{'):
129 tpl = jsonutils.loads(tmpl_str)
132 tpl = yaml.load(tmpl_str, Loader=yaml_loader)
133 except yaml.YAMLError as yea:
134 raise ValueError(yea)
138 # Looking for supported version keys in the loaded template
139 if not ('HeatTemplateFormatVersion' in tpl or
140 'heat_template_version' in tpl or
141 'AWSTemplateFormatVersion' in tpl):
142 raise ValueError("Template format version not found.")