Add Deployment Unit to ApexLake 37/5137/3
authorVincenzo Riccobene <vincenzox.m.riccobene@intel.com>
Wed, 23 Dec 2015 13:26:15 +0000 (13:26 +0000)
committerJörgen Karlsson <jorgen.w.karlsson@ericsson.com>
Wed, 23 Dec 2015 14:17:25 +0000 (14:17 +0000)
Includes the deployment unit module used for deployment by Apexlake
Also includes tests

JIRA: YARDSTICK-35

Change-Id: Ia5c89f3cd03d53b1fc4e418215955fd91aff9d03
Signed-off-by: Vincenzo Riccobene <vincenzox.m.riccobene@intel.com>
yardstick/vTC/apexlake/experimental_framework/deployment_unit.py [new file with mode: 0644]
yardstick/vTC/apexlake/tests/deployment_unit_test.py [new file with mode: 0644]

diff --git a/yardstick/vTC/apexlake/experimental_framework/deployment_unit.py b/yardstick/vTC/apexlake/experimental_framework/deployment_unit.py
new file mode 100644 (file)
index 0000000..186258f
--- /dev/null
@@ -0,0 +1,119 @@
+# 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.
+
+import os
+import time
+
+from experimental_framework import heat_manager
+from experimental_framework import common
+
+MAX_RETRY = 3
+
+
+class DeploymentUnit:
+    """
+    This unit is in charge to manage the deployment of the workloads under
+    test and any other workloads necessary to
+    the benchmark
+    """
+
+    def __init__(self, openstack_credentials):
+        self.heat_manager = heat_manager.HeatManager(openstack_credentials)
+        self.deployed_stacks = list()
+
+    def destroy_heat_template(self, stack_name):
+        """
+        Destroys a stack
+        :param stack_name: Stack of the name to be destroyed (sting)
+        :return: None
+        """
+        try:
+            if self.heat_manager.check_stack_status(stack_name):
+                if stack_name in self.deployed_stacks:
+                    self.deployed_stacks.remove(stack_name)
+                self.heat_manager.delete_stack(stack_name)
+
+            status = self.heat_manager.check_stack_status(stack_name)
+            while status and 'DELETE_IN_PROGRESS' in status:
+                common.LOG.info(status)
+                time.sleep(5)
+                status = self.heat_manager.check_stack_status(stack_name)
+            return True
+        except:
+            return False
+
+    def destroy_all_deployed_stacks(self):
+        """
+        Destroys all the stacks currently deployed
+        :return: None
+        """
+        for stack in self.deployed_stacks:
+            if self.heat_manager.is_stack_deployed(stack):
+                self.destroy_heat_template(stack)
+
+    def deploy_heat_template(self, template_file, stack_name, parameters,
+                             attempt=0):
+        """
+        Deploys a heat template and in case of failure retries 3 times
+        :param template_file: full path file name of the heat template
+        :param stack_name: name of the stack to deploy
+        :param parameters: parameters to be given to the heat template
+        :param attempt: number of current attempt
+        :return: returns True in case the creation is completed
+                 returns False in case the creation is failed
+        """
+        if not os.path.isfile(template_file):
+            raise ValueError('The specified file does not exist ("' +
+                             template_file + '")')
+        self.heat_manager.validate_heat_template(template_file)
+        try:
+            self.heat_manager.create_stack(template_file, stack_name,
+                                           parameters)
+            deployed = True
+        except:
+            deployed = False
+
+        if not deployed and 'COMPLETE' in \
+                self.heat_manager.check_stack_status(stack_name):
+            try:
+                self.destroy_heat_template(stack_name)
+            except:
+                pass
+
+        status = self.heat_manager.check_stack_status(stack_name)
+        while status and 'CREATE_IN_PROGRESS' in status:
+            time.sleep(5)
+            status = self.heat_manager.check_stack_status(stack_name)
+        if status and ('FAILED' in status or 'NOT_FOUND' in status):
+            if attempt < MAX_RETRY:
+                attempt += 1
+                try:
+                    self.destroy_heat_template(stack_name)
+                except Exception as e:
+                    common.LOG.debug(e.message)
+                    pass
+                return self.deploy_heat_template(template_file, stack_name,
+                                                 parameters, attempt)
+            else:
+                try:
+                    self.destroy_heat_template(stack_name)
+                except Exception as e:
+                    common.LOG.debug(e.message)
+                finally:
+                    return False
+        if self.heat_manager.check_stack_status(stack_name) and \
+            'COMPLETE' in self.heat_manager.\
+                check_stack_status(stack_name):
+            self.deployed_stacks.append(stack_name)
+            return True
diff --git a/yardstick/vTC/apexlake/tests/deployment_unit_test.py b/yardstick/vTC/apexlake/tests/deployment_unit_test.py
new file mode 100644 (file)
index 0000000..4c70102
--- /dev/null
@@ -0,0 +1,272 @@
+# 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'
+
+
+import unittest
+import mock
+import experimental_framework.deployment_unit as mut
+
+
+class DummyHeatManager:
+
+    def __init__(self, param):
+        self.counts = 0
+        pass
+
+    def validate_heat_template(self, template_file):
+        return True
+
+    def check_stack_status(self, stack_name):
+        # return 'CREATE_COMPLETE'
+        self.counts += 1
+        if self.counts >= 3:
+            return 'CREATE_COMPLETE'
+        else:
+            return 'CREATE_IN_PROGRESS'
+
+    def delete_stack(self, stack_name):
+        pass
+
+
+class DummyHeatManagerFailed(DummyHeatManager):
+
+    def check_stack_status(self, stack_name):
+        return 'CREATE_FAILED'
+
+    def create_stack(self, template_file, stack_name, parameters):
+        pass
+
+
+class DummyHeatManagerComplete(DummyHeatManager):
+
+    def check_stack_status(self, stack_name):
+        return 'CREATE_COMPLETE'
+
+    def create_stack(self, template_file, stack_name, parameters):
+        raise Exception()
+
+
+class DummyHeatManagerFailedException(DummyHeatManagerFailed):
+
+    def create_stack(self, template_file, stack_name, parameters):
+        raise Exception
+
+    def check_stack_status(self, stack_name):
+        return ''
+
+
+class DummyHeatManagerDestroy:
+
+    def __init__(self, credentials):
+        self.delete_stack_counter = 0
+        self.check_stack_status_counter = 0
+
+    def check_stack_status(self, stack_name):
+        if self.check_stack_status_counter < 2:
+            self.check_stack_status_counter += 1
+            return 'DELETE_IN_PROGRESS'
+        else:
+            return 'DELETE_COMPLETE'
+
+    def create_stack(self, template_file, stack_name, parameters):
+        pass
+
+    def delete_stack(self, stack_name=None):
+        if stack_name == 'stack':
+            self.delete_stack_counter += 1
+        else:
+            return self.delete_stack_counter
+
+    def is_stack_deployed(self, stack_name):
+        return True
+
+
+class DummyHeatManagerDestroyException(DummyHeatManagerDestroy):
+
+    def delete_stack(self, stack_name=None):
+        raise Exception
+
+
+class DummyHeatManagerReiteration:
+
+    def __init__(self, param):
+        self.counts = 0
+
+    def validate_heat_template(self, template_file):
+        return True
+
+    def check_stack_status(self, stack_name):
+        return 'CREATE_FAILED'
+
+    def delete_stack(self, stack_name):
+        pass
+
+    def create_stack(self, template_file=None, stack_name=None,
+                     parameters=None):
+        if template_file == 'template_reiteration' and \
+            stack_name == 'stack_reiteration' and \
+                parameters == 'parameters_reiteration':
+            self.counts += 1
+
+
+class DummyDeploymentUnit(mut.DeploymentUnit):
+
+    def destroy_heat_template(self, stack_name):
+        raise Exception
+
+
+class TestDeploymentUnit(unittest.TestCase):
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManager)
+    def test_constructor_for_sanity(self, mock_heat_manager):
+        du = mut.DeploymentUnit(dict())
+        self.assertTrue(isinstance(du.heat_manager, DummyHeatManager))
+        mock_heat_manager.assert_called_once_with(dict())
+        self.assertEqual(du.deployed_stacks, list())
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManager)
+    @mock.patch('os.path.isfile')
+    def test_deploy_heat_template_for_failure(self, mock_os_is_file,
+                                              mock_heat_manager):
+        mock_os_is_file.return_value = False
+        du = mut.DeploymentUnit(dict())
+        template_file = ''
+        stack_name = ''
+        parameters = ''
+        self.assertRaises(ValueError, du.deploy_heat_template, template_file,
+                          stack_name, parameters, 0)
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManager)
+    @mock.patch('os.path.isfile')
+    def test_deploy_heat_template_for_success(self, mock_os_is_file,
+                                              mock_heat_manager):
+        mock_os_is_file.return_value = True
+        du = mut.DeploymentUnit(dict())
+        template_file = ''
+        stack_name = ''
+        parameters = ''
+        output = du.deploy_heat_template(template_file, stack_name,
+                                         parameters, 0)
+        self.assertEqual(output, True)
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManagerComplete)
+    @mock.patch('os.path.isfile')
+    def test_deploy_heat_template_2_for_success(self, mock_os_is_file,
+                                                mock_heat_manager):
+        mock_os_is_file.return_value = True
+        du = mut.DeploymentUnit(dict())
+        template_file = ''
+        stack_name = ''
+        parameters = ''
+        output = du.deploy_heat_template(template_file, stack_name,
+                                         parameters, 0)
+        self.assertEqual(output, True)
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManagerComplete)
+    @mock.patch('os.path.isfile')
+    @mock.patch('experimental_framework.deployment_unit.DeploymentUnit',
+                side_effect=DummyDeploymentUnit)
+    def test_deploy_heat_template_3_for_success(self, mock_dep_unit,
+                                                mock_os_is_file,
+                                                mock_heat_manager):
+        mock_os_is_file.return_value = True
+        du = mut.DeploymentUnit(dict())
+        template_file = ''
+        stack_name = ''
+        parameters = ''
+        output = du.deploy_heat_template(template_file, stack_name,
+                                         parameters, 0)
+        self.assertEqual(output, True)
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManagerFailed)
+    @mock.patch('os.path.isfile')
+    def test_deploy_heat_template_for_success_2(self, mock_os_is_file,
+                                                mock_heat_manager):
+        mock_os_is_file.return_value = True
+        du = DummyDeploymentUnit(dict())
+        template_file = ''
+        stack_name = ''
+        parameters = ''
+        output = du.deploy_heat_template(template_file, stack_name,
+                                         parameters, 0)
+        self.assertEqual(output, False)
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManagerDestroy)
+    @mock.patch('experimental_framework.common.LOG')
+    def test_destroy_heat_template_for_success(self, mock_log,
+                                               mock_heat_manager):
+        openstack_credentials = dict()
+        du = mut.DeploymentUnit(openstack_credentials)
+        du.deployed_stacks = ['stack']
+        stack_name = 'stack'
+        self.assertTrue(du.destroy_heat_template(stack_name))
+        self.assertEqual(du.heat_manager.delete_stack(None), 1)
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManagerDestroyException)
+    @mock.patch('experimental_framework.common.LOG')
+    def test_destroy_heat_template_for_success_2(self, mock_log,
+                                                 mock_heat_manager):
+        openstack_credentials = dict()
+        du = mut.DeploymentUnit(openstack_credentials)
+        du.deployed_stacks = ['stack']
+        stack_name = 'stack'
+        self.assertFalse(du.destroy_heat_template(stack_name))
+
+    def test_destroy_all_deployed_stacks_for_success(self):
+        du = DeploymentUnitDestroy()
+        du.destroy_all_deployed_stacks()
+        self.assertTrue(du.destroy_heat_template())
+
+    @mock.patch('experimental_framework.heat_manager.HeatManager',
+                side_effect=DummyHeatManagerReiteration)
+    @mock.patch('os.path.isfile')
+    def test_deploy_heat_template_for_success_3(self, mock_os_is_file,
+                                                mock_heat_manager):
+        mock_os_is_file.return_value = True
+        du = mut.DeploymentUnit(dict())
+        template = 'template_reiteration'
+        stack = 'stack_reiteration'
+        parameters = 'parameters_reiteration'
+        output = du.deploy_heat_template(template, stack, parameters, 0)
+        self.assertFalse(output)
+        self.assertEqual(du.heat_manager.counts, 4)
+
+
+class DeploymentUnitDestroy(mut.DeploymentUnit):
+
+    def __init__(self):
+        self.deployed_stacks = ['stack']
+        self.heat_manager = DummyHeatManagerDestroy(dict())
+        self.destroy_all_deployed_stacks_called_correctly = False
+
+    def destroy_heat_template(self, template_name=None):
+        if template_name == 'stack':
+            self.destroy_all_deployed_stacks_called_correctly = True
+        return self.destroy_all_deployed_stacks_called_correctly