diff --git a/doc/base_tests.rst b/doc/base_tests.rst index 0c85e8268..e936b29e5 100644 --- a/doc/base_tests.rst +++ b/doc/base_tests.rst @@ -337,6 +337,16 @@ Test Daemon Resource Allocation Control .. automodule:: fuelweb_test.tests.test_cgroups :members: +Test LCM base +------------- +.. automodule:: fuelweb_test.tests.tests_lcm.base_lcm_test + :members: + +Test task idempotency +--------------------- +.. automodule:: fuelweb_test.tests.tests_lcm.test_idempotency + :members: + Gating tests ============ diff --git a/fuelweb_test/helpers/fuel_actions.py b/fuelweb_test/helpers/fuel_actions.py index cfc33b65c..55a3077f5 100644 --- a/fuelweb_test/helpers/fuel_actions.py +++ b/fuelweb_test/helpers/fuel_actions.py @@ -14,17 +14,17 @@ import os import re -import yaml +from six.moves import cStringIO from devops.helpers.helpers import wait from devops.models import DiskDevice from devops.models import Node from devops.models import Volume from proboscis.asserts import assert_equal +import yaml from fuelweb_test import logger from fuelweb_test import logwrap - from fuelweb_test.helpers.regenerate_repo import regenerate_centos_repo from fuelweb_test.helpers.regenerate_repo import regenerate_ubuntu_repo from fuelweb_test.helpers import replace_repos @@ -324,6 +324,19 @@ class AdminActions(BaseActions): assert_equal(result['exit_code'], 0, "Saving Fuel settings failed: {0}!".format(result)) + @logwrap + def get_tasks_description(self, release=None): + """Get tasks description + + :param release: a string with release name + :return: a dictionary of tasks description + """ + if not release: + release = '' + cmd = "cat `find /etc/puppet/{} -name tasks.yaml`".format(release) + data = self.ssh_manager.execute_on_remote(self.admin_ip, cmd) + return yaml.load(cStringIO(''.join(data['stdout']))) + class NailgunActions(BaseActions): """NailgunActions.""" # TODO documentation diff --git a/fuelweb_test/tests/tests_lcm/__init__.py b/fuelweb_test/tests/tests_lcm/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/fuelweb_test/tests/tests_lcm/base_lcm_test.py b/fuelweb_test/tests/tests_lcm/base_lcm_test.py new file mode 100644 index 000000000..2a0dccae4 --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/base_lcm_test.py @@ -0,0 +1,509 @@ +# Copyright 2016 Mirantis, Inc. +# +# 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 fileinput +import os + +from devops.helpers.helpers import TimeoutError +from proboscis import asserts +from proboscis import test +import yaml + +from fuelweb_test import logger +from fuelweb_test.helpers.decorators import log_snapshot_after_test +from fuelweb_test.helpers.ssh_manager import SSHManager +from fuelweb_test.settings import NEUTRON +from fuelweb_test.settings import DEPLOYMENT_MODE +from fuelweb_test.settings import NEUTRON_SEGMENT +from fuelweb_test.tests.base_test_case import SetupEnvironment +from fuelweb_test.tests.base_test_case import TestBasic + + +# NOTE: Setup yaml to work with puppet report +def construct_ruby_object(loader, suffix, node): + """Define a specific constructor""" + return loader.construct_yaml_map(node) + + +def construct_ruby_sym(loader, node): + """Define a specific multi constructor""" + return loader.construct_yaml_str(node) + + +TASKS_BLACKLIST = [ + "reboot_provisioned_nodes", + "hiera", + "configure_default_route", + "netconfig"] + + +class DeprecatedFixture(Exception): + def __init__(self): + msg = ('Please update fixtires in the fuel-qa repo with ' + 'according to generated fixtures') + super(DeprecatedFixture, self).__init__(msg) + + +class LCMTestBasic(TestBasic): + """LCMTestBasic.""" # TODO documentation + + def __init__(self): + super(LCMTestBasic, self).__init__() + yaml.add_multi_constructor(u"!ruby/object:", construct_ruby_object) + yaml.add_constructor(u"!ruby/sym", construct_ruby_sym) + + # FIXME: after implementation of the main functional of PROD-2510 + @staticmethod + def get_nodes_tasks(node_id): + """ + :param node_id: an integer number of node id + :return: a set of deployment tasks for corresponding node + """ + tasks = set() + ssh = SSHManager() + + result = ssh.execute_on_remote(ssh.admin_ip, "ls /var/log/astute") + filenames = [filename.strip() for filename in result['stdout']] + + for filename in filenames: + ssh.download_from_remote( + ssh.admin_ip, + destination="/var/log/astute/{0}".format(filename), + target="/tmp/{0}".format(filename)) + + data = fileinput.FileInput( + files=["/tmp/{0}".format(filename) for filename in filenames], + openhook=fileinput.hook_compressed) + for line in data: + if "Task time summary" in line \ + and "node {}".format(node_id) in line: + # FIXME: define an exact search of task + task_name = line.split("Task time summary: ")[1].split()[0] + check = any([excluded_task in task_name + for excluded_task in TASKS_BLACKLIST]) + if check: + continue + tasks.add(task_name) + return tasks + + @staticmethod + def get_task_type(tasks, task_id): + """Get task type + + :param tasks: a list of dictionaries with task description + :param task_id: a string, name of deployment task + :return: a string of task type or a boolean value "False" + """ + for task in tasks: + if task.get('id', '') == task_id: + return task.get('type', False) + return False + + @staticmethod + def get_puppet_report(node): + """Get puppet run report from corresponding node + + :param node: a dictionary with node description + :return: a dictionary with puppet report data + """ + ssh = SSHManager() + ip = node['ip'] + report_file = "/var/lib/puppet/state/last_run_report.yaml" + asserts.assert_true(ssh.isfile_on_remote(ip, report_file), + 'File {!r} not found on node {!r}' + .format(report_file, node['id'])) + with ssh.open_on_remote(ip, report_file) as f: + data = yaml.load(f) + ssh.rm_rf_on_remote(ip, report_file) + return data + + @staticmethod + def load_fixture(deployment_type, role): + """Load fixture for corresponding kind of deployment + + :param deployment_type: a string, name of the deployment kind + :param role: a string, node role + :return: a dictionary with loaded fixture data + """ + fixture_path = os.path.join( + os.path.dirname(__file__), "fixtures", + deployment_type, "{}.yaml".format(role)) + with open(fixture_path) as f: + fixture = yaml.load(f) + + default_attrs = {"no_puppet_run": False, + "type": "puppet", + "skip": []} + + # NOTE: Populate fixture with default values + for task in fixture['tasks']: + task_name, task_attrs = task.items()[0] + if task_attrs is None: + task_attrs = {} + + for default_attr, default_value in default_attrs.items(): + if default_attr not in task_attrs: + task_attrs[default_attr] = default_value + + task[task_name] = task_attrs + return fixture + + def get_fixture_relevance(self, actual_tasks, fixture): + """Get fixture relevance between actual deployment tasks + and tasks from fixture files + + :param actual_tasks: a list of actual tasks + :param fixture: a dictionary with fixture data + :return: a tuple of task sets + """ + actual_tasks = set(actual_tasks) + fixture_tasks = set([i.keys()[0] for i in fixture["tasks"]]) + tasks_description = self.env.admin_actions.get_tasks_description() + + extra_actual_tasks = actual_tasks.difference(fixture_tasks) + extra_fixture_tasks = fixture_tasks.difference(actual_tasks) + + # NOTE: in ideal case we need to avoid tasks with wrong types + wrong_types = {} + for task in fixture["tasks"]: + task_name, attrs = task.items()[0] + expected_type = self.get_task_type(tasks_description, task_name) + if not expected_type: + logger.error("No type or no such task {!r}".format(task_name)) + else: + if expected_type != attrs["type"]: + wrong_types.update({task_name: expected_type}) + + logger.info("Actual tasks {}contain extra tasks: {}" + .format("" if extra_actual_tasks else "don't ", + extra_actual_tasks)) + logger.info("Fixture tasks {}contain extra tasks: {}" + .format("" if extra_fixture_tasks else "don't ", + extra_fixture_tasks)) + + return extra_actual_tasks, extra_fixture_tasks, wrong_types + + def check_extra_tasks(self, slave_nodes, deployment): + """Check existing extra tasks regarding to fixture and actual task + or tasks with a wrong type + + :param slave_nodes: a list of nailgun nodes + :param deployment: a string, name of the deployment kind + :return: a list with nodes for which extra tasks regarding to fixture + and actual task or tasks with a wrong type were found + """ + result = {'extra_actual_tasks': {}, + 'extra_fixture_tasks': {}, + 'wrong_types': {}, + 'failed_tasks': {}} + for node in slave_nodes: + node_roles = "_".join(sorted(node["roles"])) + node_ref = "{}_{}".format(node["id"], node_roles) + fixture = self.load_fixture(deployment, node_roles) + node_tasks = self.get_nodes_tasks(node["id"]) + extra_actual_tasks, extra_fixture_tasks, wrong_types = \ + self.get_fixture_relevance(node_tasks, fixture) + result['extra_actual_tasks'][node_ref] = extra_actual_tasks + result['extra_fixture_tasks'][node_ref] = extra_fixture_tasks + result['wrong_types'][node_ref] = wrong_types + result['failed_tasks'][node_ref] = \ + extra_actual_tasks | \ + extra_fixture_tasks | \ + set([task for task in wrong_types.keys()]) + + logger.warning("Uncovered deployment tasks:\n{}" + .format(yaml.dump(result, default_flow_style=False))) + failed_nodes = [node_refs + for node_refs, failed_tasks in + result['failed_tasks'].items() + if failed_tasks] + return failed_nodes + + def execute_task_on_node(self, task, node, cluster_id): + """Execute deployment task against the corresponding node + + :param task: a string of task name + :param node: a dictionary with node description + :param cluster_id: an integer, number of cluster id + :return: None + """ + try: + logger.info("Trying to execute {!r} task on node {!r}" + .format(task, node['id'])) + tsk = self.fuel_web.client.put_deployment_tasks_for_cluster( + cluster_id=cluster_id, + data=[task], + node_id=node['id']) + self.fuel_web.assert_task_success(tsk, timeout=30 * 60) + except (AssertionError, TimeoutError) as e: + logger.exception("Failed to run task {!r}\n" + "Exception:\n{}".format(task, e)) + + def generate_fixture(self, node_refs, cluster_id, slave_nodes): + """Generate fixture with description of task idempotency + + :param node_refs: a string, refs to nailgun node + :param cluster_id: an integer, number of cluster id + :param slave_nodes: a list of nailgun nodes + :return: None + """ + result = {} + for node in slave_nodes: + node_roles = "_".join(sorted(node["roles"])) + node_ref = "{}_{}".format(node["id"], node_roles) + if node_ref not in node_refs: + logger.debug('Node {!r} was skipped because the current ' + 'fixtures are actual for deployment tasks which ' + 'are executed on this node'.format(node_ref)) + continue + node_tasks = self.get_nodes_tasks(node["id"]) + tasks_description = self.env.admin_actions.get_tasks_description() + tasks = [] + + for task in node_tasks: + task_type = self.get_task_type(tasks_description, task) + if task_type != "puppet": + logger.info("Skip checking of {!r} task,it is not puppet" + .format(task)) + tasks.append({task: {"type": task_type}}) + continue + + self.execute_task_on_node(task, node, cluster_id) + + try: + report = self.get_puppet_report(node) + except AssertionError: + # NOTE: in ideal case we need to avoid puppet + # tasks with "no_puppet_run": True + tasks.append({task: {"no_puppet_run": True}}) + msg = ("Unexpected no_puppet_run for task: {}" + .format(task)) + logger.info(msg) + continue + + failed = False + task_resources = [] + + for res_name, res_stats in report['resource_statuses'].items(): + if res_stats['changed']: + failed = True + msg = ("Non-idempotent task {!r}, resource: {}" + .format(task, res_name)) + logger.error(msg) + task_resources.append(res_name) + + if failed: + tasks.append({ + task: {"skip": task_resources} + }) + else: + tasks.append({ + task: None + }) + logger.info( + "Task {!r} on node {!r} was executed successfully" + .format(task, node['id'])) + + result.update( + { + node_ref: { + "role": node_roles, + "tasks": tasks + } + } + ) + + logger.info("Generated fixture:\n{}" + .format(yaml.dump(result, default_flow_style=False))) + + +@test(groups=['deploy_lcm_environment']) +class SetupLCMEnvironment(LCMTestBasic): + @test(depends_on=[SetupEnvironment.prepare_slaves_3], + groups=['lcm_deploy_1_ctrl_1_cmp_1_cinder']) + @log_snapshot_after_test + def lcm_deploy_1_ctrl_1_cmp_1_cinder(self): + """Create cluster with cinder + + Scenario: + 1. Revert snapshot "ready_with_3_slaves" + 2. Create cluster + 3. Add 1 controller + 4. Add 1 compute node + 5. Add 1 cinder node + 6. Deploy cluster + 7. Check extra deployment tasks + 8. Generate fixtures + + Snapshot: "lcm_deploy_1_ctrl_1_cmp_1_cinder" + """ + deployment = '1_ctrl_1_cmp_1_cinder' + snapshotname = 'lcm_deploy_{}'.format(deployment) + self.check_run(snapshotname) + self.show_step(1) + self.env.revert_snapshot("ready_with_3_slaves") + + self.show_step(2) + segment_type = NEUTRON_SEGMENT['tun'] + cluster_id = self.fuel_web.create_cluster( + name=self.__class__.__name__, + mode=DEPLOYMENT_MODE, + settings={ + "net_provider": NEUTRON, + "net_segment_type": segment_type + } + ) + self.show_step(3) + self.show_step(4) + self.show_step(5) + self.fuel_web.update_nodes( + cluster_id, + { + 'slave-01': ['controller'], + 'slave-02': ['compute'], + 'slave-03': ['cinder'] + } + ) + + self.show_step(6) + self.fuel_web.deploy_cluster_wait(cluster_id) + self.show_step(7) + slave_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id) + node_refs = self.check_extra_tasks(slave_nodes, deployment) + if node_refs: + self.show_step(8) + self.generate_fixture(node_refs, cluster_id, slave_nodes) + raise DeprecatedFixture + self.env.make_snapshot(snapshotname, is_make=True) + + @test(depends_on=[SetupEnvironment.prepare_slaves_3], + groups=['lcm_deploy_1_ctrl_1_cmp_1_mongo']) + @log_snapshot_after_test + def lcm_deploy_1_ctrl_1_cmp_1_mongo(self): + """Create cluster with Ceilometer + + Scenario: + 1. Revert snapshot "ready_with_3_slaves" + 2. Create cluster + 3. Add 1 controller + 4. Add 1 compute node + 5. Add 1 mongo node + 6. Deploy cluster + 7. Check extra deployment tasks + 8. Generate fixtures + + Snapshot: "lcm_deploy_1_ctrl_1_cmp_1_mongo" + """ + deployment = '1_ctrl_1_cmp_1_mongo' + snapshotname = 'lcm_deploy_{}'.format(deployment) + self.check_run(snapshotname) + self.show_step(1) + self.env.revert_snapshot("ready_with_3_slaves") + + self.show_step(2) + segment_type = NEUTRON_SEGMENT['vlan'] + cluster_id = self.fuel_web.create_cluster( + name=self.__class__.__name__, + mode=DEPLOYMENT_MODE, + settings={ + 'ceilometer': True, + 'net_provider': NEUTRON, + 'net_segment_type': segment_type + } + ) + self.show_step(3) + self.show_step(4) + self.show_step(5) + self.fuel_web.update_nodes( + cluster_id, + { + 'slave-01': ['controller'], + 'slave-02': ['compute'], + 'slave-03': ['mongo'] + } + ) + + self.show_step(6) + self.fuel_web.deploy_cluster_wait(cluster_id) + self.show_step(7) + slave_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id) + node_refs = self.check_extra_tasks(slave_nodes, deployment) + if node_refs: + self.show_step(8) + self.generate_fixture(node_refs, cluster_id, slave_nodes) + raise DeprecatedFixture + self.env.make_snapshot(snapshotname, is_make=True) + + @test(depends_on=[SetupEnvironment.prepare_slaves_5], + groups=['lcm_deploy_1_ctrl_1_cmp_3_ceph']) + @log_snapshot_after_test + def lcm_deploy_1_ctrl_1_cmp_3_ceph(self): + """Create cluster with ceph + + Scenario: + 1. Revert snapshot "ready_with_5_slaves" + 2. Create cluster + 3. Add 1 controller + 4. Add 1 compute node + 5. Add 3 ceph-osd nodes + 6. Deploy cluster + 7. Check extra deployment tasks + 8. Generate fixtures + + Snapshot: "lcm_deploy_1_ctrl_1_cmp_3_ceph" + """ + deployment = '1_ctrl_1_cmp_3_ceph' + snapshotname = 'lcm_deploy_{}'.format(deployment) + self.check_run(snapshotname) + self.show_step(1) + self.env.revert_snapshot("ready_with_5_slaves") + + self.show_step(2) + segment_type = NEUTRON_SEGMENT['tun'] + cluster_id = self.fuel_web.create_cluster( + name=self.__class__.__name__, + mode=DEPLOYMENT_MODE, + settings={ + 'volumes_lvm': False, + 'volumes_ceph': True, + 'images_ceph': True, + 'objects_ceph': True, + 'net_provider': NEUTRON, + 'net_segment_type': segment_type + } + ) + self.show_step(3) + self.show_step(4) + self.show_step(5) + self.fuel_web.update_nodes( + cluster_id, + { + 'slave-01': ['controller'], + 'slave-02': ['compute'], + 'slave-03': ['ceph-osd'], + 'slave-04': ['ceph-osd'], + 'slave-05': ['ceph-osd'] + } + ) + + self.show_step(6) + self.fuel_web.deploy_cluster_wait(cluster_id) + self.show_step(7) + slave_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id) + node_refs = self.check_extra_tasks(slave_nodes, deployment) + if node_refs: + self.show_step(8) + self.generate_fixture(node_refs, cluster_id, slave_nodes) + raise DeprecatedFixture + self.env.make_snapshot(snapshotname, is_make=True) diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/cinder.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/cinder.yaml new file mode 100644 index 000000000..0b2df0f9c --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/cinder.yaml @@ -0,0 +1,47 @@ +roles: + cinder +tasks: + - update_hosts: null + - clear_nodes_info: + type: shell + - copy_keys_ceph: + type: copy_files + - globals: null + - fuel_pkgs: null + - tools: null + - enable_cinder_volume_service: null + - rsync_core_puppet: + type: sync + - cgroups: null + - upload_nodes_info: + type: skipped + - copy_keys: + type: copy_files + - override_configuration: null + - setup_repositories: null + - dns-client: null + - allocate_hugepages: null + - plugins_setup_repositories: null + - upload_provision_data: + type: false + - ssl-keys-saving: null + - upload_configuration: + type: upload_file + - firewall: null + - top-role-cinder: + skip: + - Service[cinder-volume] + - logging: null + - sync_time: + type: shell + - plugins_rsync: + no_puppet_run: true + - connectivity_tests: null + - configuration_symlink: + type: shell + - hosts: null + - copy_haproxy_keys: + type: copy_files + - ntp-client: null + - ssl-add-trust-chain: null + - reserved_ports: null diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/compute.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/compute.yaml new file mode 100644 index 000000000..8ea99f52d --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/compute.yaml @@ -0,0 +1,66 @@ +roles: + compute +tasks: + - update_hosts: null + - openstack-network-start: + type: skipped + - openstack-network-common-config: null + - clear_nodes_info: + type: shell + - openstack-network-agents-sriov: null + - copy_keys_ceph: + type: copy_files + - globals: null + - fuel_pkgs: null + - openstack-network-agents-l3: null + - openstack-network-agents-metadata: null + - tools: null + - rsync_core_puppet: + type: sync + - enable_nova_compute_service: null + - cgroups: null + - upload_nodes_info: + type: skipped + - copy_keys: + type: copy_files + - override_configuration: null + - setup_repositories: null + - dns-client: null + - openstack-network-plugins-l2: null + - allocate_hugepages: null + - plugins_setup_repositories: null + - upload_provision_data: + type: false + - ceph-compute: + no_puppet_run: true + - ssl-keys-saving: null + - sriov_iommu_check: + skip: + - Exec[sriov_iommu_check] + - openstack-network-end: + type: skipped + - ceilometer-compute: + no_puppet_run: true + - upload_configuration: + type: upload_file + - firewall: null + - logging: null + - top-role-compute: + skip: + - Notify[Module openstack_tasks cannot notify service nova-compute on packages + update] + - Service[nova-compute] + - sync_time: + type: shell + - openstack-network-compute-nova: null + - plugins_rsync: + no_puppet_run: true + - connectivity_tests: null + - configuration_symlink: + type: shell + - hosts: null + - copy_haproxy_keys: + type: copy_files + - ntp-client: null + - ssl-add-trust-chain: null + - reserved_ports: null diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/controller.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/controller.yaml new file mode 100644 index 000000000..699eef7b2 --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_cinder/controller.yaml @@ -0,0 +1,188 @@ +roles: + controller +tasks: + - ironic_post_swift_key: + type: shell + - openstack-haproxy-mysqld: null + - cinder-db: null + - dump_rabbitmq_definitions: null + - rsync_core_puppet: + type: sync + - ssl-dns-setup: null + - ceilometer-controller: null + - override_configuration: null + - ceilometer-keystone: + no_puppet_run: true + - nova-db: null + - workloads_collector_add: null + - primary-openstack-network-plugins-l2: null + - radosgw-keystone: null + - virtual_ips: null + - primary-dns-server: null + - openstack-haproxy-murano: null + - openstack-network-end: + type: skipped + - openstack-haproxy-radosgw: null + - openstack-haproxy-swift: null + - heat-db: null + - openstack-haproxy-neutron: null + - updatedb: + no_puppet_run: true + - ironic-db: + no_puppet_run: true + - plugins_rsync: + no_puppet_run: true + - ceilometer-radosgw-user: + no_puppet_run: true + - openstack-haproxy-keystone: null + - hosts: null + - primary-rabbitmq: null + - primary-cluster-haproxy: null + - openstack-network-routers: null + - reserved_ports: null + - controller_remaining_tasks: null + - glance-keystone: null + - openstack-haproxy-aodh: null + - murano-cfapi: + no_puppet_run: true + - vmware-vcenter: + no_puppet_run: true + - ironic-compute: + no_puppet_run: true + - primary-openstack-network-agents-metadata: null + - cinder-keystone: null + - copy_keys: + type: copy_files + - enable_rados: + no_puppet_run: true + - ntp-check: null + - aodh-db: + no_puppet_run: true + - disable_keystone_service_token: null + - umm: null + - memcached: null + - allocate_hugepages: null + - openrc-delete: + skip: + - File[/root/openrc] + - plugins_setup_repositories: + no_puppet_run: true + - sahara-keystone: + no_puppet_run: true + - openstack-haproxy-sahara: null + - ssl-keys-saving: null + - primary-cluster: null + - upload_cirros: + type: shell + - primary-keystone: + skip: + - File[/root/openrc] + - primary-openstack-network-agents-l3: null + - upload_configuration: + type: upload_file + - create-cinder-types: null + - neutron-keystone: null + - logging: null + - nova-keystone: null + - update_hosts: null + - ironic-keystone: + no_puppet_run: true + - connectivity_tests: null + - swift-storage: null + - primary-heat: null + - conntrackd: null + - sahara-db: + no_puppet_run: true + - horizon: null + - openstack-haproxy-ceilometer: null + - openstack-network-common-config: null + - firewall: null + - apache: null + - globals: null + - aodh-keystone: + no_puppet_run: true + - glance: null + - tools: null + - openstack-haproxy: null + - cgroups: null + - murano-cfapi-keystone: + no_puppet_run: true + - aodh: + no_puppet_run: true + - ceph_create_pools: + no_puppet_run: true + - openstack-haproxy-ironic: + no_puppet_run: true + - setup_repositories: null + - openstack-network-routers-ha: + no_puppet_run: true + - glance-db: null + - neutron-db: null + - ironic_upload_images: + type: shell + - swift-rebalance-cron: null + - primary-ceph-mon: null + - openstack-haproxy-stats: null + - ironic-api: + no_puppet_run: true + - primary-ceph-radosgw: null + - dns-client: null + - cluster-vrouter: null + - murano-rabbitmq: + no_puppet_run: true + - api-proxy: null + - cluster_health: null + - heat-keystone: null + - openstack-haproxy-horizon: null + - openstack-network-start: + type: skipped + - clear_nodes_info: + type: shell + - murano-db: + no_puppet_run: true + - copy_keys_ceph: + type: copy_files + - sahara: + no_puppet_run: true + - fuel_pkgs: null + - swift-keystone: null + - public_vip_ping: null + - upload_nodes_info: + type: skipped + - openstack-haproxy-glance: null + - murano: + no_puppet_run: true + - ceph_ready_check: + type: shell + - enable_quorum: + type: shell + - openstack-haproxy-nova: null + - upload_provision_data: + type: false + - openstack-network-server-config: null + - primary-database: + skip: + - File[/root/.my.cnf] + - vcenter_compute_zones_create: + type: shell + - openstack-haproxy-cinder: null + - ntp-server: null + - murano-keystone: + no_puppet_run: true + - primary-openstack-network-agents-dhcp: null + - openstack-haproxy-heat: null + - primary-openstack-controller: null + - openstack-cinder: null + - keystone-db: + skip: + - File[/root/.my.cnf] + - sync_time: + type: shell + - configuration_symlink: + type: shell + - openstack-network-server-nova: null + - copy_haproxy_keys: + type: copy_files + - primary-swift-proxy: null + - openstack-network-networks: null + - ssl-add-trust-chain: null \ No newline at end of file diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/compute.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/compute.yaml new file mode 100644 index 000000000..bdc8fdb61 --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/compute.yaml @@ -0,0 +1,66 @@ +roles: + compute +tasks: + - update_hosts: null + - openstack-network-start: + type: skipped + - openstack-network-common-config: null + - clear_nodes_info: + type: shell + - openstack-network-agents-sriov: null + - copy_keys_ceph: + type: copy_files + - globals: null + - fuel_pkgs: null + - openstack-network-agents-l3: null + - openstack-network-agents-metadata: null + - tools: null + - rsync_core_puppet: + type: sync + - enable_nova_compute_service: null + - cgroups: null + - upload_nodes_info: + type: skipped + - copy_keys: + type: copy_files + - override_configuration: null + - setup_repositories: null + - dns-client: null + - openstack-network-plugins-l2: null + - allocate_hugepages: null + - plugins_setup_repositories: + no_puppet_run: true + - upload_provision_data: + type: false + - ceph-compute: + no_puppet_run: true + - ssl-keys-saving: null + - sriov_iommu_check: + skip: + - Exec[sriov_iommu_check] + - openstack-network-end: + type: skipped + - ceilometer-compute: null + - upload_configuration: + type: upload_file + - firewall: null + - logging: null + - top-role-compute: + skip: + - Notify[Module openstack_tasks cannot notify service nova-compute on packages + update] + - Service[nova-compute] + - sync_time: + type: shell + - openstack-network-compute-nova: null + - plugins_rsync: + no_puppet_run: true + - connectivity_tests: null + - configuration_symlink: + type: shell + - hosts: null + - copy_haproxy_keys: + type: copy_files + - ntp-client: null + - ssl-add-trust-chain: null + - reserved_ports: null diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/controller.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/controller.yaml new file mode 100644 index 000000000..b9a1955f2 --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/controller.yaml @@ -0,0 +1,183 @@ +roles: + controller +tasks: + - ironic_post_swift_key: + type: shell + - openstack-haproxy-mysqld: null + - cinder-db: null + - dump_rabbitmq_definitions: null + - rsync_core_puppet: + type: sync + - ssl-dns-setup: null + - ceilometer-controller: null + - override_configuration: null + - ceilometer-keystone: null + - nova-db: null + - workloads_collector_add: null + - primary-openstack-network-plugins-l2: null + - radosgw-keystone: null + - virtual_ips: null + - primary-dns-server: null + - openstack-haproxy-murano: null + - openstack-network-end: + type: skipped + - openstack-haproxy-radosgw: null + - openstack-haproxy-swift: null + - heat-db: null + - openstack-haproxy-neutron: null + - updatedb: null + - ironic-db: + no_puppet_run: true + - plugins_rsync: + no_puppet_run: true + - ceilometer-radosgw-user: + no_puppet_run: true + - openstack-haproxy-keystone: null + - hosts: null + - primary-rabbitmq: null + - primary-cluster-haproxy: null + - openstack-network-routers: null + - reserved_ports: null + - controller_remaining_tasks: null + - glance-keystone: null + - openstack-haproxy-aodh: null + - murano-cfapi: + no_puppet_run: true + - vmware-vcenter: + no_puppet_run: true + - ironic-compute: + no_puppet_run: true + - primary-openstack-network-agents-metadata: null + - cinder-keystone: null + - copy_keys: + type: copy_files + - enable_rados: + no_puppet_run: true + - ntp-check: null + - aodh-db: null + - disable_keystone_service_token: null + - umm: null + - memcached: null + - allocate_hugepages: null + - openrc-delete: + skip: + - File[/root/openrc] + - plugins_setup_repositories: + no_puppet_run: true + - sahara-keystone: + no_puppet_run: true + - openstack-haproxy-sahara: null + - ssl-keys-saving: null + - primary-cluster: null + - upload_cirros: + type: shell + - primary-keystone: + skip: + - File[/root/openrc] + - primary-openstack-network-agents-l3: null + - upload_configuration: + type: upload_file + - create-cinder-types: null + - neutron-keystone: null + - logging: null + - nova-keystone: null + - update_hosts: null + - ironic-keystone: + no_puppet_run: true + - connectivity_tests: null + - swift-storage: null + - primary-heat: null + - conntrackd: null + - sahara-db: + no_puppet_run: true + - horizon: null + - openstack-haproxy-ceilometer: null + - openstack-network-common-config: null + - firewall: null + - apache: null + - globals: null + - aodh-keystone: null + - glance: null + - tools: null + - openstack-haproxy: null + - cgroups: null + - murano-cfapi-keystone: + no_puppet_run: true + - aodh: null + - ceph_create_pools: + no_puppet_run: true + - openstack-haproxy-ironic: + no_puppet_run: true + - setup_repositories: null + - openstack-network-routers-ha: + no_puppet_run: true + - glance-db: null + - neutron-db: null + - ironic_upload_images: + type: shell + - swift-rebalance-cron: null + - primary-ceph-mon: null + - openstack-haproxy-stats: null + - ironic-api: + no_puppet_run: true + - primary-ceph-radosgw: null + - dns-client: null + - cluster-vrouter: null + - murano-rabbitmq: + no_puppet_run: true + - api-proxy: null + - cluster_health: null + - heat-keystone: null + - openstack-haproxy-horizon: null + - openstack-network-start: + type: skipped + - clear_nodes_info: + type: shell + - murano-db: + no_puppet_run: true + - copy_keys_ceph: + type: copy_files + - sahara: + no_puppet_run: true + - fuel_pkgs: null + - swift-keystone: null + - public_vip_ping: null + - upload_nodes_info: + type: skipped + - openstack-haproxy-glance: null + - murano: + no_puppet_run: true + - ceph_ready_check: + type: shell + - enable_quorum: + type: shell + - openstack-haproxy-nova: null + - upload_provision_data: + type: false + - openstack-network-server-config: null + - primary-database: + skip: + - File[/root/.my.cnf] + - vcenter_compute_zones_create: + type: shell + - openstack-haproxy-cinder: null + - ntp-server: null + - murano-keystone: + no_puppet_run: true + - primary-openstack-network-agents-dhcp: null + - openstack-haproxy-heat: null + - primary-openstack-controller: null + - openstack-cinder: null + - keystone-db: + skip: + - File[/root/.my.cnf] + - sync_time: + type: shell + - configuration_symlink: + type: shell + - openstack-network-server-nova: null + - copy_haproxy_keys: + type: copy_files + - primary-swift-proxy: null + - openstack-network-networks: null + - ssl-add-trust-chain: null diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/mongo.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/mongo.yaml new file mode 100644 index 000000000..04ca303ef --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_1_mongo/mongo.yaml @@ -0,0 +1,44 @@ +roles: + mongo +tasks: + - update_hosts: null + - clear_nodes_info: + type: shell + - top-role-primary-mongo: null + - copy_keys_ceph: + type: copy_files + - globals: null + - fuel_pkgs: null + - tools: null + - rsync_core_puppet: + type: sync + - cgroups: null + - upload_nodes_info: + type: skipped + - copy_keys: + type: copy_files + - override_configuration: null + - setup_repositories: null + - dns-client: null + - allocate_hugepages: null + - plugins_setup_repositories: null + - upload_provision_data: + type: false + - ssl-keys-saving: null + - upload_configuration: + type: upload_file + - firewall: null + - logging: null + - sync_time: + type: shell + - plugins_rsync: + no_puppet_run: true + - connectivity_tests: null + - configuration_symlink: + type: shell + - hosts: null + - copy_haproxy_keys: + type: copy_files + - ntp-client: null + - ssl-add-trust-chain: null + - reserved_ports: null diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/ceph-osd.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/ceph-osd.yaml new file mode 100644 index 000000000..0688c51de --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/ceph-osd.yaml @@ -0,0 +1,45 @@ +roles: + ceph-osd +tasks: + - update_hosts: null + - clear_nodes_info: + type: shell + - copy_keys_ceph: + type: copy_files + - globals: null + - fuel_pkgs: null + - tools: null + - rsync_core_puppet: + type: sync + - cgroups: null + - upload_nodes_info: + type: skipped + - copy_keys: + type: copy_files + - override_configuration: null + - setup_repositories: null + - dns-client: null + - allocate_hugepages: null + - plugins_setup_repositories: null + - upload_provision_data: + type: false + - ssl-keys-saving: null + - upload_configuration: + type: upload_file + - firewall: null + - top-role-ceph-osd: null + - logging: null + - updatedb: null + - sync_time: + type: shell + - plugins_rsync: + no_puppet_run: true + - connectivity_tests: null + - configuration_symlink: + type: shell + - hosts: null + - copy_haproxy_keys: + type: copy_files + - ntp-client: null + - ssl-add-trust-chain: null + - reserved_ports: null diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/compute.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/compute.yaml new file mode 100644 index 000000000..d6a440126 --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/compute.yaml @@ -0,0 +1,63 @@ +roles: + compute +tasks: + - update_hosts: null + - openstack-network-start: + type: skipped + - openstack-network-common-config: null + - clear_nodes_info: + type: shell + - openstack-network-agents-sriov: null + - copy_keys_ceph: + type: copy_files + - globals: null + - fuel_pkgs: null + - openstack-network-agents-l3: null + - openstack-network-agents-metadata: null + - tools: null + - rsync_core_puppet: + type: sync + - enable_nova_compute_service: null + - cgroups: null + - upload_nodes_info: + type: skipped + - copy_keys: + type: copy_files + - override_configuration: null + - setup_repositories: null + - dns-client: null + - openstack-network-plugins-l2: null + - allocate_hugepages: null + - plugins_setup_repositories: null + - upload_provision_data: + type: false + - ceph-compute: null + - ssl-keys-saving: null + - sriov_iommu_check: null + - openstack-network-end: + type: skipped + - ceilometer-compute: + no_puppet_run: true + - upload_configuration: + type: upload_file + - firewall: null + - logging: null + - top-role-compute: + skip: + - Notify[Module openstack_tasks cannot notify service nova-compute on packages + update] + - Service[nova-compute] + - sync_time: + type: shell + - openstack-network-compute-nova: null + - plugins_rsync: + no_puppet_run: true + - connectivity_tests: null + - configuration_symlink: + type: shell + - hosts: null + - copy_haproxy_keys: + type: copy_files + - ntp-client: null + - ssl-add-trust-chain: null + - reserved_ports: null diff --git a/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/controller.yaml b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/controller.yaml new file mode 100644 index 000000000..e0dec12df --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/fixtures/1_ctrl_1_cmp_3_ceph/controller.yaml @@ -0,0 +1,189 @@ +roles: + controller +tasks: + - ironic_post_swift_key: + type: shell + - openstack-haproxy-mysqld: null + - cinder-db: null + - dump_rabbitmq_definitions: null + - rsync_core_puppet: + type: sync + - ssl-dns-setup: null + - ceilometer-controller: null + - override_configuration: null + - ceilometer-keystone: + no_puppet_run: true + - nova-db: null + - workloads_collector_add: null + - primary-openstack-network-plugins-l2: null + - radosgw-keystone: null + - virtual_ips: null + - primary-dns-server: null + - openstack-haproxy-murano: null + - openstack-network-end: + type: skipped + - openstack-haproxy-radosgw: null + - openstack-haproxy-swift: null + - heat-db: null + - openstack-haproxy-neutron: null + - updatedb: null + - ironic-db: + no_puppet_run: true + - plugins_rsync: + no_puppet_run: true + - ceilometer-radosgw-user: + no_puppet_run: true + - openstack-haproxy-keystone: null + - hosts: null + - primary-rabbitmq: null + - primary-cluster-haproxy: null + - openstack-network-routers: null + - reserved_ports: null + - controller_remaining_tasks: null + - glance-keystone: null + - openstack-haproxy-aodh: null + - murano-cfapi: + no_puppet_run: true + - vmware-vcenter: + no_puppet_run: true + - ironic-compute: + no_puppet_run: true + - primary-openstack-network-agents-metadata: null + - cinder-keystone: null + - copy_keys: + type: copy_files + - enable_rados: null + - ntp-check: null + - aodh-db: + no_puppet_run: true + - disable_keystone_service_token: null + - umm: null + - memcached: null + - allocate_hugepages: null + - openrc-delete: + skip: + - File[/root/openrc] + - plugins_setup_repositories: + no_puppet_run: true + - sahara-keystone: + no_puppet_run: true + - openstack-haproxy-sahara: null + - ssl-keys-saving: null + - primary-cluster: null + - upload_cirros: + type: shell + - primary-keystone: + skip: + - File[/root/openrc] + - primary-openstack-network-agents-l3: null + - upload_configuration: + type: upload_file + - create-cinder-types: null + - neutron-keystone: null + - logging: null + - nova-keystone: null + - update_hosts: null + - ironic-keystone: + no_puppet_run: true + - connectivity_tests: null + - swift-storage: + no_puppet_run: true + - primary-heat: null + - conntrackd: null + - sahara-db: + no_puppet_run: true + - horizon: null + - openstack-haproxy-ceilometer: null + - openstack-network-common-config: null + - firewall: null + - apache: null + - globals: null + - aodh-keystone: + no_puppet_run: true + - glance: null + - tools: null + - openstack-haproxy: null + - cgroups: null + - murano-cfapi-keystone: + no_puppet_run: true + - aodh: + no_puppet_run: true + - ceph_create_pools: null + - openstack-haproxy-ironic: + no_puppet_run: true + - setup_repositories: null + - openstack-network-routers-ha: + no_puppet_run: true + - glance-db: null + - neutron-db: null + - ironic_upload_images: + type: shell + - swift-rebalance-cron: + no_puppet_run: true + - primary-ceph-mon: null + - openstack-haproxy-stats: null + - ironic-api: + no_puppet_run: true + - primary-ceph-radosgw: null + - dns-client: null + - cluster-vrouter: null + - murano-rabbitmq: + no_puppet_run: true + - api-proxy: null + - cluster_health: null + - heat-keystone: null + - openstack-haproxy-horizon: null + - openstack-network-start: + type: skipped + - clear_nodes_info: + type: shell + - murano-db: + no_puppet_run: true + - copy_keys_ceph: + type: copy_files + - sahara: + no_puppet_run: true + - fuel_pkgs: null + - swift-keystone: + no_puppet_run: true + - public_vip_ping: null + - upload_nodes_info: + type: skipped + - openstack-haproxy-glance: null + - murano: + no_puppet_run: true + - ceph_ready_check: + type: shell + - enable_quorum: + type: shell + - openstack-haproxy-nova: null + - upload_provision_data: + type: false + - openstack-network-server-config: null + - primary-database: + skip: + - File[/root/.my.cnf] + - vcenter_compute_zones_create: + type: shell + - openstack-haproxy-cinder: null + - ntp-server: null + - murano-keystone: + no_puppet_run: true + - primary-openstack-network-agents-dhcp: null + - openstack-haproxy-heat: null + - primary-openstack-controller: null + - openstack-cinder: null + - keystone-db: + skip: + - File[/root/.my.cnf] + - sync_time: + type: shell + - configuration_symlink: + type: shell + - openstack-network-server-nova: null + - copy_haproxy_keys: + type: copy_files + - primary-swift-proxy: + no_puppet_run: true + - openstack-network-networks: null + - ssl-add-trust-chain: null diff --git a/fuelweb_test/tests/tests_lcm/test_idempotency.py b/fuelweb_test/tests/tests_lcm/test_idempotency.py new file mode 100644 index 000000000..7bd2928d4 --- /dev/null +++ b/fuelweb_test/tests/tests_lcm/test_idempotency.py @@ -0,0 +1,162 @@ +# Copyright 2016 Mirantis, Inc. +# +# 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. + +from proboscis import asserts +from proboscis import test +import yaml + +from fuelweb_test import logger +from fuelweb_test.helpers.decorators import log_snapshot_after_test +from fuelweb_test.tests.tests_lcm.base_lcm_test import SetupLCMEnvironment +from fuelweb_test.tests.tests_lcm.base_lcm_test import LCMTestBasic + + +@test(groups=['idempotency']) +class TaskIdempotency(LCMTestBasic): + """TaskIdempotency.""" # TODO documentation + + def check_idempotency(self, deployment): + """Check task idempotency for corresponding deployment + + :param deployment: a string, name of the deployment kind + :return: a boolean, all tasks is idempotent - True, + some task is not idempotent - False + """ + idempotent = True + cluster_id = self.fuel_web.get_last_created_cluster() + slave_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id) + + result = {'tasks_idempotency': {}, + 'timeouterror_tasks': {}} + + for node in slave_nodes: + node_roles = "_".join(sorted(node["roles"])) + node_ref = "{}_{}".format(node["id"], node_roles) + fixture = self.load_fixture(deployment, node_roles) + + failed_tasks = {} + timeouterror_tasks = [] + + for task in fixture['tasks']: + task_name, fixture_task = task.items()[0] + + if fixture_task['type'] != 'puppet': + logger.info('Skip checking of {!r} task,it is not puppet' + .format(task_name)) + continue + + self.execute_task_on_node(task_name, node, cluster_id) + + try: + report = self.get_puppet_report(node) + except AssertionError: + if not fixture_task.get('no_puppet_run'): + msg = ('Unexpected no_puppet_run for task: {!r}' + .format(task_name)) + logger.info(msg) + timeouterror_tasks.append(task_name) + continue + + skip = fixture_task.get('skip') + failed = False + task_resources = [] + + for res_name, res_stats in report['resource_statuses'].items(): + if res_stats['changed'] and res_name not in skip: + failed = True + msg = ('Non-idempotent task {!r}, resource: {}' + .format(task, res_name)) + logger.error(msg) + task_resources.append(res_name) + + if failed: + idempotent = False + failed_tasks.update({ + task_name: task_resources + }) + else: + logger.info( + 'Task {!r} on node {!r} was executed successfully' + .format(task_name, node['id'])) + + result['tasks_idempotency'][node_ref] = failed_tasks + result['timeouterror_tasks'][node_ref] = timeouterror_tasks + + logger.warning('Non-idempotent tasks:\n{}' + .format(yaml.dump(result, default_flow_style=False))) + return idempotent + + @test(depends_on=[SetupLCMEnvironment.lcm_deploy_1_ctrl_1_cmp_1_cinder], + groups=['idempotency', + 'idempotency_1_ctrl_1_cmp_1_cinder']) + @log_snapshot_after_test + def idempotency_1_ctrl_1_cmp_1_cinder(self): + """Test idempotency for cluster with cinder + + Scenario: + 1. Revert snapshot "lcm_deploy_1_ctrl_1_cmp_1_cinder" + 2. Check task idempotency + + Snapshot: "idempotency_1_ctrl_1_cmp_1_cinder" + """ + self.show_step(1) + deployment = "1_ctrl_1_cmp_1_cinder" + self.env.revert_snapshot('lcm_deploy_{}'.format(deployment)) + self.show_step(2) + asserts.assert_true(self.check_idempotency(deployment), + 'There are non-idempotent tasks. ' + 'Please take a look at the output above!') + self.env.make_snapshot('idempotency_{}'.format(deployment)) + + @test(depends_on=[SetupLCMEnvironment.lcm_deploy_1_ctrl_1_cmp_1_mongo], + groups=['idempotency', 'idempotency_1_ctrl_1_cmp_1_mongo']) + @log_snapshot_after_test + def idempotency_1_ctrl_1_cmp_1_mongo(self): + """Test idempotency for cluster with Ceilometer + + Scenario: + 1. Revert snapshot "lcm_deploy_1_ctrl_1_cmp_1_mongo" + 2. Check task idempotency + + Snapshot: "idempotency_1_ctrl_1_cmp_1_mongo" + """ + self.show_step(1) + deployment = "1_ctrl_1_cmp_1_mongo" + self.env.revert_snapshot('lcm_deploy_{}'.format(deployment)) + self.show_step(2) + asserts.assert_true(self.check_idempotency(deployment), + 'There are non-idempotent tasks. ' + 'Please take a look at the output above!') + self.env.make_snapshot('idempotency_{}'.format(deployment)) + + @test(depends_on=[SetupLCMEnvironment.lcm_deploy_1_ctrl_1_cmp_3_ceph], + groups=['idempotency', 'idempotency_1_ctrl_1_cmp_3_ceph']) + @log_snapshot_after_test + def idempotency_1_ctrl_1_cmp_3_ceph(self): + """Test idempotency for cluster with Ceph + + Scenario: + 1. Revert snapshot "lcm_deploy_1_ctrl_1_cmp_3_ceph" + 2. Check task idempotency + + Snapshot: "idempotency_1_ctrl_1_cmp_3_ceph" + """ + self.show_step(1) + deployment = "1_ctrl_1_cmp_3_ceph" + self.env.revert_snapshot('lcm_deploy_{}'.format(deployment)) + self.show_step(2) + asserts.assert_true(self.check_idempotency(deployment), + 'There are non-idempotent tasks. ' + 'Please take a look at the output above!') + self.env.make_snapshot('idempotency_{}'.format(deployment))