Changes required for running CI tests (Pike pod).
[snaps.git] / snaps / openstack / utils / heat_utils.py
1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 #                    and others.  All rights reserved.
3 #
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:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
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.
15 import logging
16
17 import yaml
18 from heatclient.client import Client
19 from heatclient.common.template_format import yaml_loader
20 from oslo_serialization import jsonutils
21
22 from snaps import file_utils
23 from snaps.domain.stack import Stack
24
25 from snaps.openstack.utils import keystone_utils
26
27 __author__ = 'spisarski'
28
29 logger = logging.getLogger('heat_utils')
30
31
32 def heat_client(os_creds):
33     """
34     Retrieves the Heat client
35     :param os_creds: the OpenStack credentials
36     :return: the client
37     """
38     logger.debug('Retrieving Nova Client')
39     return Client(os_creds.heat_api_version,
40                   session=keystone_utils.keystone_session(os_creds))
41
42
43 def get_stack_by_name(heat_cli, stack_name):
44     """
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
49     """
50     stacks = heat_cli.stacks.list(**{'name': stack_name})
51     for stack in stacks:
52         return Stack(name=stack.identifier, stack_id=stack.id)
53
54     return None
55
56
57 def get_stack_by_id(heat_cli, stack_id):
58     """
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
63     """
64     stack = heat_cli.stacks.get(stack_id)
65     return Stack(name=stack.identifier, stack_id=stack.id)
66
67
68 def get_stack_status(heat_cli, stack_id):
69     """
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
73     :return:
74     """
75     return heat_cli.stacks.get(stack_id).stack_status
76
77
78 def get_stack_outputs(heat_cli, stack_id):
79     """
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
84     """
85     stack = heat_cli.stacks.get(stack_id)
86     return stack.outputs
87
88
89 def create_stack(heat_cli, stack_settings):
90     """
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
95     """
96     args = dict()
97
98     if stack_settings.template:
99         args['template'] = stack_settings.template
100     else:
101         args['template'] = parse_heat_template_str(
102             file_utils.read_file(stack_settings.template_path))
103     args['stack_name'] = stack_settings.name
104
105     if stack_settings.env_values:
106         args['parameters'] = stack_settings.env_values
107
108     stack = heat_cli.stacks.create(**args)
109
110     return get_stack_by_id(heat_cli, stack_id=stack['stack']['id'])
111
112
113 def delete_stack(heat_cli, stack):
114     """
115     Deletes the Heat stack
116     :param heat_cli: the OpenStack heat client object
117     :param stack: the OpenStack Heat stack object
118     """
119     heat_cli.stacks.delete(stack.id)
120
121
122 def parse_heat_template_str(tmpl_str):
123     """
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.
127     """
128     if tmpl_str.startswith('{'):
129         tpl = jsonutils.loads(tmpl_str)
130     else:
131         try:
132             tpl = yaml.load(tmpl_str, Loader=yaml_loader)
133         except yaml.YAMLError as yea:
134             raise ValueError(yea)
135         else:
136             if tpl is None:
137                 tpl = {}
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.")
143     return tpl