From: Vincenzo Riccobene Date: Thu, 3 Dec 2015 17:47:25 +0000 (+0000) Subject: Adds Heat Manger and tests to ApexLake X-Git-Tag: brahmaputra.1.0~144 X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=commitdiff_plain;h=83f97fbb5ec866a055a1e7e158f53ab5f01e5b2c;p=yardstick.git Adds Heat Manger and tests to ApexLake Adds to ApexLake a module that manages the connection with OpenStack Heat to trigger instantiation and termination of stacks. Also Moves tests and bin directory in the right place. JIRA: YARDSTICK-35 Change-Id: I0ea407a3129625a238fb4187896c65a2bcd02700 Signed-off-by: Vincenzo Riccobene --- diff --git a/yardstick/vTC/apexlake/experimental_framework/bin/run_tests.sh b/yardstick/vTC/apexlake/bin/run_tests.sh similarity index 100% rename from yardstick/vTC/apexlake/experimental_framework/bin/run_tests.sh rename to yardstick/vTC/apexlake/bin/run_tests.sh diff --git a/yardstick/vTC/apexlake/experimental_framework/heat_manager.py b/yardstick/vTC/apexlake/experimental_framework/heat_manager.py new file mode 100644 index 000000000..41fc585f7 --- /dev/null +++ b/yardstick/vTC/apexlake/experimental_framework/heat_manager.py @@ -0,0 +1,103 @@ +# Copyright (c) 2015 Intel Research and Development Ireland Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +__author__ = 'vmriccox' + + +from keystoneclient.v2_0 import client as keystoneClient +from heatclient import client as heatClient +from heatclient.common import template_utils + +from experimental_framework import common + + +class HeatManager: + + def __init__(self, credentials): + self.ip_controller = credentials['ip_controller'] + self.heat_url = credentials['heat_url'] + self.user = credentials['user'] + self.password = credentials['password'] + self.auth_uri = credentials['auth_uri'] + self.project_id = credentials['project'] + self.heat = None + + # TODO: verify that init_heat is useless in the constructor + # self.init_heat() + + def init_heat(self): + keystone = keystoneClient.Client(username=self.user, + password=self.password, + tenant_name=self.project_id, + auth_url=self.auth_uri) + auth_token = keystone.auth_token + self.heat = heatClient.Client('1', endpoint=self.heat_url, + token=auth_token) + + def print_stacks(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 create_stack(self, template_file, stack_name, parameters): + self.init_heat() + # self.print_stacks() + 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.print_stacks(stack_name) + + def is_stack_deployed(self, stack_name): + self.init_heat() + if stack_name in self.heat.stacks.list(): + return True + return False + + def check_stack_status(self, stack_name): + """ + Returns a string representing the status of a stack from Heat + perspective + :param stack_name: Name of the stack to be checked (type: str) + :return: (type: str) + """ + for stack in self.heat.stacks.list(): + if stack.stack_name == stack_name: + return stack.stack_status + return 'NOT_FOUND' + + def validate_heat_template(self, heat_template_file): + self.init_heat() + if not self.heat.stacks.validate(template=open(heat_template_file, + 'r').read()): + raise ValueError('The provided heat template "' + + heat_template_file + + '" is not in the correct format') + + def delete_stack(self, stack_name): + self.init_heat() + 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/yardstick/vTC/apexlake/experimental_framework/tests/generates_template_test.py b/yardstick/vTC/apexlake/tests/generates_template_test.py similarity index 100% rename from yardstick/vTC/apexlake/experimental_framework/tests/generates_template_test.py rename to yardstick/vTC/apexlake/tests/generates_template_test.py diff --git a/yardstick/vTC/apexlake/tests/heat_manager_test.py b/yardstick/vTC/apexlake/tests/heat_manager_test.py new file mode 100644 index 000000000..f89835cc7 --- /dev/null +++ b/yardstick/vTC/apexlake/tests/heat_manager_test.py @@ -0,0 +1,208 @@ +# Copyright (c) 2015 Intel Research and Development Ireland Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +__author__ = 'gpetralx' + + +import unittest +from experimental_framework import heat_manager +import mock + + +def get_mock_heat(version, *args, **kwargs): + return MockHeat() + + +class MockStacks(object): + def __init__(self, stacks): + self.stacks = stacks + + def list(self): + list_name = list() + for stack in self.stacks: + list_name.append(stack.stack_name) + print list_name + return self.stacks + + def validate(self, template=None): + return False + + def delete(self, id): + for stack in self.stacks: + if stack.id == id: + return self.stacks.remove(stack) + + def create(self, stack_name=None, files=None, template=None, + parameters=None): + print stack_name + self.stacks.append(MockStack(stack_name)) + + +class MockStacks_2(object): + def __init__(self, stacks): + self.stacks = stacks + + def list(self): + raise Exception + + +class MockStack(object): + def __init__(self, stack_name): + self.name = stack_name + + @property + def stack_status(self): + return self.stack_name + '_status' + + @property + def stack_name(self): + return self.name + + @property + def id(self): + return self.name + + def __eq__(self, other): + return self.name == other + + +class MockHeat(object): + def __init__(self): + stacks = [MockStack('stack_1'), MockStack('stack_2')] + self.stacks_list = MockStacks(stacks) + + @property + def stacks(self): + return self.stacks_list + + +class MockHeat_2(MockHeat): + def __init__(self): + stacks = [MockStack('stack_1'), MockStack('stack_2')] + self.stacks_list = MockStacks_2(stacks) + + +class HeatManagerMock(heat_manager.HeatManager): + def init_heat(self): + if self.heat is None: + self.heat = MockHeat() + + +class HeatManagerMock_2(heat_manager.HeatManager): + def init_heat(self): + if self.heat is None: + self.heat = MockHeat_2() + + +class TestHeatManager(unittest.TestCase): + + def setUp(self): + credentials = dict() + credentials['ip_controller'] = '1.1.1.1' + credentials['heat_url'] = 'http://heat_url' + credentials['user'] = 'user' + credentials['password'] = 'password' + credentials['auth_uri'] = 'auth_uri' + credentials['project'] = 'project' + self.heat_manager = HeatManagerMock(credentials) + self.heat_manager.init_heat() + + def tearDown(self): + pass + + def test_is_stack_deployed_for_success(self): + self.assertTrue(self.heat_manager.is_stack_deployed('stack_1')) + self.assertFalse(self.heat_manager.is_stack_deployed('stack_n')) + + def test_check_status_for_success(self): + self.assertEqual('stack_1_status', + self.heat_manager.check_stack_status('stack_1')) + self.assertEqual('NOT_FOUND', + self.heat_manager.check_stack_status('stack_x')) + + def test_validate_template_for_success(self): + template_file = \ + 'tests/data/test_templates/VTC_base_single_vm_wait_1.yaml' + with self.assertRaises(ValueError): + self.heat_manager.validate_heat_template(template_file) + + def test_delete_stack_for_success(self): + self.assertTrue(self.heat_manager.delete_stack('stack_1')) + self.assertFalse(self.heat_manager.delete_stack('stack_x')) + + def test_delete_stack_for_success_2(self): + self.assertTrue(self.heat_manager.delete_stack('stack_1')) + + @mock.patch('heatclient.common.template_utils.get_template_contents') + @mock.patch('heatclient.client.Client') + # @mock.patch('heatclient.client.Client', side_effect=DummyHeatClient) + def test_create_stack_for_success(self, mock_stack_create, + mock_get_template_contents): + return_value = ({'template': 'template'}, 'template') + mock_get_template_contents.return_value = return_value + self.heat_manager.create_stack('template', 'stack_n', 'parameters') + self.assertTrue(self.heat_manager.is_stack_deployed('stack_n')) + + +class TestHeatManager_2(unittest.TestCase): + + def setUp(self): + credentials = dict() + credentials['ip_controller'] = '1.1.1.1' + credentials['heat_url'] = 'http://heat_url' + credentials['user'] = 'user' + credentials['password'] = 'password' + credentials['auth_uri'] = 'auth_uri' + credentials['project'] = 'project' + self.heat_manager = HeatManagerMock_2(credentials) + + def tearDown(self): + pass + + def test_delete_stack_for_success_2(self): + self.assertFalse(self.heat_manager.delete_stack('stack_1')) + + +class KeystoneMock(object): + @property + def auth_token(self): + return 'token' + + +class TestHeatInit(unittest.TestCase): + def setUp(self): + credentials = dict() + credentials['ip_controller'] = '1.1.1.1' + credentials['heat_url'] = 'http://heat_url' + credentials['user'] = 'user' + credentials['password'] = 'password' + credentials['auth_uri'] = 'auth_uri' + credentials['project'] = 'project' + self.heat_manager = heat_manager.HeatManager(credentials) + + def tearDown(self): + pass + + @mock.patch('heatclient.client.Client') + @mock.patch('keystoneclient.v2_0.client.Client') + def test_heat_init_for_sanity(self, keystone_client, heat_client): + keystone_client.return_value = KeystoneMock() + heat_client.return_value = MockHeat() + self.heat_manager.init_heat() + keystone_client.assert_called_once_with(username='user', + tenant_name='project', + password='password', + auth_url='auth_uri') + heat_client.assert_called_once_with('1', endpoint='http://heat_url', + token='token')