From d68fdff6708cd15a4c79d6bb2f61832191f0a248 Mon Sep 17 00:00:00 2001 From: MatthewLi Date: Fri, 1 Apr 2016 02:59:18 -0400 Subject: [PATCH] heat api management and template creation functions JIRA: BOTTLENECK-58 Change-Id: I6cf7f1a2ed02ca32a75cb54885591db6546ed41c Signed-off-by: MatthewLi --- utils/infra_setup/heat/__init__.py | 8 ++ utils/infra_setup/heat/manager.py | 86 +++++++++++++++++++++ utils/infra_setup/heat/template.py | 154 +++++++++++++++++++++++++++++++++++++ 3 files changed, 248 insertions(+) create mode 100755 utils/infra_setup/heat/__init__.py create mode 100755 utils/infra_setup/heat/manager.py create mode 100755 utils/infra_setup/heat/template.py diff --git a/utils/infra_setup/heat/__init__.py b/utils/infra_setup/heat/__init__.py new file mode 100755 index 00000000..83b8d15d --- /dev/null +++ b/utils/infra_setup/heat/__init__.py @@ -0,0 +1,8 @@ +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## diff --git a/utils/infra_setup/heat/manager.py b/utils/infra_setup/heat/manager.py new file mode 100755 index 00000000..5902e8c4 --- /dev/null +++ b/utils/infra_setup/heat/manager.py @@ -0,0 +1,86 @@ +############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from heatclient import client as heat_client +from keystoneclient.v2_0 import client as keystone_client +from heatclient.common import template_utils + +import heat.common as common + +class HeatManager: + + def __init__(self, credentials): + self.user = credentials['user'] + self.password = credentials['password'] + self.controller_ip = credentials['controller_ip'] + self.heat_url = credentials['heat_url'] + self.auth_uri = credentials['auth_uri'] + self.project_id = credentials['project'] + self.heat = None + + def heat_init(self): + keystone = keystone_client.Client(username=self.user, + password=self.password, + tenant_name=self.project_id, + auth_url=self.auth_uri) + auth_token = keystone.auth_token + self.heat_url = keystone.service_catalog.url_for( + service_type='orchestration') + self.heat = heat_client.Client('1', endpoint=self.heat_url, + token=auth_token) + + def stacks_list(self, name=None): + for stack in self.heat.stacks.list(): + if (name and stack.stack_name == name) or not name: + common.LOG.info("stack name " + stack.stack_name) + common.LOG.info("stack status " + stack.stack_status) + + def stack_generate(self, template_file, stack_name, parameters): + self.heat_init() + self.stacks_list() + tpl_files, template = template_utils.get_template_contents(template_file) + + fields = { + 'template': template, + 'files': dict(list(tpl_files.items())) + } + self.heat.stacks.create(stack_name=stack_name, files=fields['files'], + template=template, parameters=parameters) + self.stacks_list(stack_name) + + def stack_is_deployed(self, stack_name): + self.heat_init() + if stack_name in self.heat.stacks.list(): + return True + return False + + def stack_check_status(self, stack_name): + for stack in self.heat.stacks.list(): + if stack.stack_name == stack_name: + return stack.stack_status + return 'NOT_FOUND' + + def heat_validate_template(self, heat_template_file): + self.heat_init() + if not self.heat.stacks.validate(template=open(heat_template_file, + 'r').read()): + raise ValueError('The provided heat template "' + + heat_template_file + + '" is in the wrong format') + + def stack_delete(self, stack_name): + self.heat_init() + try: + for stack in self.heat.stacks.list(): + if stack.stack_name == stack_name: + self.heat.stacks.delete(stack.id) + return True + except: + pass + return False diff --git a/utils/infra_setup/heat/template.py b/utils/infra_setup/heat/template.py new file mode 100755 index 00000000..f05831de --- /dev/null +++ b/utils/infra_setup/heat/template.py @@ -0,0 +1,154 @@ +############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +"""to create heat templates from the base template +""" +import os +import json +import shutil +import common +import consts.parameters as parameters + +class TreeNode: + + def __init__(self): + self.up = None + self.down = [] + self.variable_name = '' + self.variable_value = 0 + + def add_child(self, node): + node.up = self + self.down.append(node) + + def get_parent(self): + return self.up + + def get_children(self): + if len(self.down) == 0: + return [] + return self.down + + def get_variable_name(self): + return self.variable_name + + def get_variable_value(self): + return self.variable_value + + def set_variable_name(self, name): + self.variable_name = name + + def set_variable_value(self, value): + self.variable_value = value + + def get_path(self): + ret_val = [] + if not self.up: + ret_val.append(self) + return ret_val + for node in self.up.get_path(): + ret_val.append(node) + ret_val.append(self) + return ret_val + + def __str__(self): + return str(self.variable_name) + " --> " + str(self.variable_value) + + def __repr__(self): + return str(self.variable_name) + " = " + str(self.variable_value) + + @staticmethod + def _get_leaves(node, leaves): + children = node.get_children() + if len(children) == 0: + leaves.append(node) + return + for child in children: + TreeNode._get_leaves(child, leaves) + + @staticmethod + def get_leaves(node): + leaves = list() + TreeNode._get_leaves(node, leaves) + return leaves + +template_name = parameters.TEST_TEMPLATE_NAME + +def generates_templates(base_heat_template, deployment_configuration): + # parameters loaded from file + template_dir = common.get_template_dir() + template_extension = parameters.TEMPLATE_EXTENSION + template_base_name = base_heat_template + + variables = deployment_configuration + + # Delete the templates generated in previous running + common.LOG.info("Removing the heat templates already generated") + command = "rm {}{}_*".format(template_dir, template_name) + os.system(command) + + # Creation of the tree with all the new configurations + common.LOG.info("Creation of a tree with all new configurations") + tree = TreeNode() + for variable in variables: + leaves = TreeNode.get_leaves(tree) + common.LOG.debug("LEAVES: " + str(leaves)) + common.LOG.debug("VALUES: " + str(variables[variable])) + + for value in variables[variable]: + for leaf in leaves: + new_node = TreeNode() + new_node.set_variable_name(variable) + new_node.set_variable_value(value) + leaf.add_child(new_node) + + common.LOG.debug("CONFIGURATION TREE: " + str(tree)) + + common.LOG.info("Heat Template and metadata file creation") + leaves = TreeNode.get_leaves(tree) + counter = 1 + for leaf in leaves: + heat_template_vars = leaf.get_path() + if os.path.isabs(template_base_name): + base_template = template_base_name + else: + base_template = template_dir + template_base_name + new_template = template_dir + template_name + new_template += "_" + str(counter) + template_extension + shutil.copy(base_template, new_template) + + metadata = dict() + for var in heat_template_vars: + if var.get_variable_name(): + common.replace_in_file(new_template, "#" + + var.get_variable_name(), + var.get_variable_value()) + metadata[var.get_variable_name()] = var.get_variable_value() + + # Save the metadata on a JSON file + with open(new_template + ".json", 'w') as outfile: + json.dump(metadata, outfile) + + common.LOG.debug("Heat Templates and Metadata file " + str(counter) + + " created") + counter += 1 + + # Creation of the template files + common.LOG.info(str(counter - 1) + " Heat Templates and Metadata files " + "created") + + +def get_all_heat_templates(template_dir, template_extension): + template_files = list() + for dirname, dirnames, filenames in os.walk(template_dir): + for filename in filenames: + if template_extension in filename and filename.endswith(template_extension) and template_name in filename: + template_files.append(filename) + template_files.sort() + return template_files -- 2.16.6