Fix small things for integration of ApexLake with Yardstick
[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 import json
21 import os
22 import shutil
23 from experimental_framework import common
24 from experimental_framework.constants import framework_parameters as fp
25
26
27 class TreeNode:
28     """
29     This class represent the node of the configuration tree.\
30     Each node represents a single configuration value for a single
31     configuration parameter.
32     """
33
34     def __init__(self):
35         self.up = None
36         self.down = []
37         self.variable_name = ''
38         self.variable_value = 0
39
40     def add_child(self, node):
41         """
42         Adds a node as a child for the current node
43         :param node: node to be added as a child (type: TreeNode)
44         :return: None
45         """
46         node.up = self
47         self.down.append(node)
48
49     def get_parent(self):
50         """
51         Returns the parent node of the current one
52         :return type: TreeNode
53         """
54         return self.up
55
56     def get_children(self):
57         """
58         Returns the children of the current node
59         :return type: list of TreeNode
60         """
61         if len(self.down) == 0:
62             # return [self]
63             return []
64         return self.down
65
66     def get_variable_name(self):
67         """
68         Returns the name of the variable correspondent to the current node
69         :return type: str
70         """
71         return self.variable_name
72
73     def get_variable_value(self):
74         """
75         Returns the value of the variable correspondent to the current node
76         :return type: str or int
77         """
78         return self.variable_value
79
80     def set_variable_name(self, name):
81         """
82         Sets the name of the variable for the current node
83         :param name: Name of the variable (type: str)
84         :return None
85         """
86         self.variable_name = name
87
88     def set_variable_value(self, value):
89         """
90         Sets the value of the variable for the current node
91         :param value: value of the variable (type: str)
92         :return None
93         """
94         self.variable_value = value
95
96     def get_path(self):
97         """
98         Returns all the path from the current node to the root of the tree.
99         :return type: list of TreeNode
100         """
101         ret_val = []
102         if not self.up:
103             ret_val.append(self)
104             return ret_val
105         for node in self.up.get_path():
106             ret_val.append(node)
107         ret_val.append(self)
108         return ret_val
109
110     def __str__(self):
111         return str(self.variable_name) + " --> " + str(self.variable_value)
112
113     def __repr__(self):
114         return str(self.variable_name) + " = " + str(self.variable_value)
115
116     @staticmethod
117     def _get_leaves(node, leaves):
118         """
119         Returns all the leaves of a tree.
120         It changes the "leaves" list.
121         :param node: root of the tree (type: TreeNode)
122         :param leaves: partial list of leaves (type: list of TreeNode)
123         :return type: None
124         """
125         children = node.get_children()
126         if len(children) == 0:
127             leaves.append(node)
128             return
129         for child in children:
130             TreeNode._get_leaves(child, leaves)
131
132     @staticmethod
133     def get_leaves(node):
134         """
135         Returns all the leaves of a tree.
136         :param node: root of the tree (TreeNode)
137         :return type: list
138         """
139         leaves = list()
140         TreeNode._get_leaves(node, leaves)
141         return leaves
142
143
144 template_name = fp.EXPERIMENT_TEMPLATE_NAME
145
146
147 def generates_templates(base_heat_template, deployment_configuration):
148     """
149     Generates the heat templates for the experiments
150     :return: None
151     """
152     # Load useful parameters from file
153     template_dir = common.get_template_dir()
154     template_file_extension = fp.TEMPLATE_FILE_EXTENSION
155     template_base_name = base_heat_template
156
157     variables = deployment_configuration
158
159     # Delete the templates eventually generated in previous running of the
160     # framework
161     common.LOG.info("Removing the heat templates previously generated")
162     command = "rm {}{}_*".format(template_dir, template_name)
163     os.system(command)
164
165     # Creation of the tree with all the new configurations
166     common.LOG.info("Creation of the tree with all the new configurations")
167     tree = TreeNode()
168     for variable in variables:
169         leaves = TreeNode.get_leaves(tree)
170         common.LOG.debug("LEAVES: " + str(leaves))
171         common.LOG.debug("VALUES: " + str(variables[variable]))
172
173         for value in variables[variable]:
174             for leaf in leaves:
175                 new_node = TreeNode()
176                 new_node.set_variable_name(variable)
177                 new_node.set_variable_value(value)
178                 leaf.add_child(new_node)
179
180     common.LOG.debug("CONFIGURATION TREE: " + str(tree))
181
182     common.LOG.info("Heat Template and metadata file creation")
183     leaves = TreeNode.get_leaves(tree)
184     counter = 1
185     for leaf in leaves:
186         heat_template_vars = leaf.get_path()
187         if os.path.isabs(template_base_name):
188             base_template = template_base_name
189         else:
190             base_template = template_dir + template_base_name
191         new_template = template_dir + template_name
192         new_template += "_" + str(counter) + template_file_extension
193         shutil.copy(base_template, new_template)
194
195         metadata = dict()
196         for var in heat_template_vars:
197             if var.get_variable_name():
198                 common.replace_in_file(new_template, "#" +
199                                        var.get_variable_name(),
200                                        var.get_variable_value())
201                 metadata[var.get_variable_name()] = var.get_variable_value()
202
203         # Save the metadata on a JSON file
204         with open(new_template + ".json", 'w') as outfile:
205             json.dump(metadata, outfile)
206
207         common.LOG.debug("Heat Templates and Metadata file " + str(counter) +
208                          " created")
209         counter += 1
210
211     # Creation of the template files
212     common.LOG.info(str(counter - 1) + " Heat Templates and Metadata files "
213                                        "created")
214
215
216 def get_all_heat_templates(template_dir, template_file_extension):
217     """
218     Loads and returns all the generated heat templates
219     :param template_dir: directory to search in (type: str)
220     :param template_file_extension: extension of the file for templates
221             (type: str)
222     :return: type: list
223     """
224     template_files = list()
225     for dirname, dirnames, filenames in os.walk(template_dir):
226         for filename in filenames:
227             if template_file_extension in filename and \
228                     filename.endswith(template_file_extension) and \
229                     template_name in filename:
230                 template_files.append(filename)
231     template_files.sort()
232     return template_files