Merge "pktgen: speedup unittest, mock time.sleep"
[yardstick.git] / yardstick / vTC / apexlake / experimental_framework / heat_template_generation.py
1 # Copyright (c) 2015 Intel Research and Development Ireland Ltd.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15
16 """
17 Generation of the heat templates from the base template
18 """
19
20 from __future__ import absolute_import
21 import os
22 import shutil
23
24 from oslo_serialization import jsonutils
25
26 from experimental_framework import common
27 from experimental_framework.constants import framework_parameters as fp
28
29
30 class TreeNode:
31     """
32     This class represent the node of the configuration tree.\
33     Each node represents a single configuration value for a single
34     configuration parameter.
35     """
36
37     def __init__(self):
38         self.up = None
39         self.down = []
40         self.variable_name = ''
41         self.variable_value = 0
42
43     def add_child(self, node):
44         """
45         Adds a node as a child for the current node
46         :param node: node to be added as a child (type: TreeNode)
47         :return: None
48         """
49         node.up = self
50         self.down.append(node)
51
52     def get_parent(self):
53         """
54         Returns the parent node of the current one
55         :return type: TreeNode
56         """
57         return self.up
58
59     def get_children(self):
60         """
61         Returns the children of the current node
62         :return type: list of TreeNode
63         """
64         if len(self.down) == 0:
65             # return [self]
66             return []
67         return self.down
68
69     def get_variable_name(self):
70         """
71         Returns the name of the variable correspondent to the current node
72         :return type: str
73         """
74         return self.variable_name
75
76     def get_variable_value(self):
77         """
78         Returns the value of the variable correspondent to the current node
79         :return type: str or int
80         """
81         return self.variable_value
82
83     def set_variable_name(self, name):
84         """
85         Sets the name of the variable for the current node
86         :param name: Name of the variable (type: str)
87         :return None
88         """
89         self.variable_name = name
90
91     def set_variable_value(self, value):
92         """
93         Sets the value of the variable for the current node
94         :param value: value of the variable (type: str)
95         :return None
96         """
97         self.variable_value = value
98
99     def get_path(self):
100         """
101         Returns all the path from the current node to the root of the tree.
102         :return type: list of TreeNode
103         """
104         ret_val = []
105         if not self.up:
106             ret_val.append(self)
107             return ret_val
108         for node in self.up.get_path():
109             ret_val.append(node)
110         ret_val.append(self)
111         return ret_val
112
113     def __str__(self):
114         return str(self.variable_name) + " --> " + str(self.variable_value)
115
116     def __repr__(self):
117         return str(self.variable_name) + " = " + str(self.variable_value)
118
119     @staticmethod
120     def _get_leaves(node, leaves):
121         """
122         Returns all the leaves of a tree.
123         It changes the "leaves" list.
124         :param node: root of the tree (type: TreeNode)
125         :param leaves: partial list of leaves (type: list of TreeNode)
126         :return type: None
127         """
128         children = node.get_children()
129         if len(children) == 0:
130             leaves.append(node)
131             return
132         for child in children:
133             TreeNode._get_leaves(child, leaves)
134
135     @staticmethod
136     def get_leaves(node):
137         """
138         Returns all the leaves of a tree.
139         :param node: root of the tree (TreeNode)
140         :return type: list
141         """
142         leaves = list()
143         TreeNode._get_leaves(node, leaves)
144         return leaves
145
146
147 template_name = fp.EXPERIMENT_TEMPLATE_NAME
148
149
150 def generates_templates(base_heat_template, deployment_configuration):
151     """
152     Generates the heat templates for the experiments
153     :return: None
154     """
155     # Load useful parameters from file
156     template_dir = common.get_template_dir()
157     template_file_extension = fp.TEMPLATE_FILE_EXTENSION
158     template_base_name = base_heat_template
159
160     variables = deployment_configuration
161
162     # Delete the templates eventually generated in previous running of the
163     # framework
164     common.LOG.info("Removing the heat templates previously generated")
165     command = "rm {}{}_*".format(template_dir, template_name)
166     os.system(command)
167
168     # Creation of the tree with all the new configurations
169     common.LOG.info("Creation of the tree with all the new configurations")
170     tree = TreeNode()
171     for variable in variables:
172         leaves = TreeNode.get_leaves(tree)
173         common.LOG.debug("LEAVES: " + str(leaves))
174         common.LOG.debug("VALUES: " + str(variables[variable]))
175
176         for value in variables[variable]:
177             for leaf in leaves:
178                 new_node = TreeNode()
179                 new_node.set_variable_name(variable)
180                 new_node.set_variable_value(value)
181                 leaf.add_child(new_node)
182
183     common.LOG.debug("CONFIGURATION TREE: " + str(tree))
184
185     common.LOG.info("Heat Template and metadata file creation")
186     leaves = TreeNode.get_leaves(tree)
187     counter = 1
188     for leaf in leaves:
189         heat_template_vars = leaf.get_path()
190         if os.path.isabs(template_base_name):
191             base_template = template_base_name
192         else:
193             base_template = template_dir + template_base_name
194         new_template = template_dir + template_name
195         new_template += "_" + str(counter) + template_file_extension
196         shutil.copy(base_template, new_template)
197
198         metadata = {}
199         for var in heat_template_vars:
200             if var.get_variable_name():
201                 common.replace_in_file(new_template, "#" +
202                                        var.get_variable_name(),
203                                        var.get_variable_value())
204                 metadata[var.get_variable_name()] = var.get_variable_value()
205
206         # Save the metadata on a JSON file
207         with open(new_template + ".json", 'w') as outfile:
208             # sort keys to maintain persistent order for git
209             jsonutils.dump(metadata, outfile, sort_keys=True)
210
211         common.LOG.debug("Heat Templates and Metadata file " + str(counter) +
212                          " created")
213         counter += 1
214
215     # Creation of the template files
216     common.LOG.info(str(counter - 1) + " Heat Templates and Metadata files "
217                                        "created")
218
219
220 def get_all_heat_templates(template_dir, template_file_extension):
221     """
222     Loads and returns all the generated heat templates
223     :param template_dir: directory to search in (type: str)
224     :param template_file_extension: extension of the file for templates
225             (type: str)
226     :return: type: list
227     """
228     template_files = []
229     for dirname, dirnames, filenames in os.walk(template_dir):
230         for filename in filenames:
231             if template_file_extension in filename and \
232                     filename.endswith(template_file_extension) and \
233                     template_name in filename:
234                 template_files.append(filename)
235     template_files.sort()
236     return template_files