Add tests for MOS customizations detection

Add tests for python-cudet tool functionality
that is related to checking MOS packages
customizations.

Closes-Bug: #1622916
Change-Id: Id5f8c4ef70d9e8c5df0c467473845f36164b3e02
This commit is contained in:
Dmitriy Kruglov 2016-09-12 23:17:04 +00:00
parent 8c491bbb06
commit 72cd837895
2 changed files with 502 additions and 0 deletions

View File

@ -685,6 +685,9 @@ Test OpenStack Upgrades
.. automodule:: fuelweb_test.tests.tests_upgrade.test_os_upgrade
:members:
.. automodule:: fuelweb_test.tests.tests_upgrade.test_customizations_check
:members:
Tests for separated services
============================

View File

@ -0,0 +1,499 @@
# 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 __future__ import unicode_literals
import copy
import os
from proboscis import asserts
from proboscis import test
from fuelweb_test.helpers.decorators import log_snapshot_after_test
from fuelweb_test.helpers.utils import YamlEditor
from fuelweb_test import logger
from fuelweb_test import settings
from fuelweb_test.tests.base_test_case import SetupEnvironment
from fuelweb_test.tests.base_test_case import TestBasic
@test(groups=['env_customizations_check'])
class EnvCustomizationsCheck(TestBasic):
"""Test suite for verification of tooling that checks customizations
of an env prior to its upgrade.
"""
CUSTOMIZED_FILE1 = \
"/usr/lib/python2.7/dist-packages/neutronclient/__init__.py"
CUSTOMIZED_FILE2 = \
"/usr/lib/python2.7/dist-packages/neutronclient/version.py"
CUDET_REPORT_PATH = "/tmp/cudet/info"
CUDET_CONFIG_PATH = "/usr/share/cudet/cudet-config.yaml"
SNAPSHOT_NAME = 'customizations_check_env'
def add_comment_to_file_on_remote(
self, ip, file_path, comment="customization"):
"""Add a comment to a package source file on an env node.
This will be evaluated as a customization when performing
the corresponding check.
:param ip: str, IP address of an env node
:param file_path: str, path to a file to update
:param comment: str, comment to add to the file
:return: None
"""
cmd = 'echo "# {0}" >> {1}'.format(comment, file_path)
self.ssh_manager.check_call(ip, cmd)
def is_file_in_report(self, cluster_id, node_id, file_path):
"""Check that customized file is mentioned in report for the given node.
:param cluster_id: int, ID of a cluster to check report for
:param node_id: str, ID of a node to check report for
:param file_path: str, file (full path) to check that it is referenced
in the report
:return: bool
"""
node_report_path = os.path.join(
self.CUDET_REPORT_PATH,
"cmds/cluster-{0}/node-{1}".format(cluster_id, node_id),
"*packages-md5-verify*")
report = self.ssh_manager.check_call(
self.ssh_manager.admin_ip, "cat {0}".format(node_report_path))
return file_path in report.stdout_str
@test(depends_on=[SetupEnvironment.prepare_slaves_3],
groups=['customizations_check_env'])
@log_snapshot_after_test
def customizations_check_env(self):
"""Create a simple 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. Run network check
8. Run OSTF
9. Install cudet tool
Duration 60m
Snapshot: customizations_check_env
"""
self.check_run(self.SNAPSHOT_NAME)
self.show_step(1)
self.env.revert_snapshot("ready_with_3_slaves")
self.show_step(2)
cluster_id = self.fuel_web.create_cluster(
name=self.__class__.__name__,
mode=settings.DEPLOYMENT_MODE,
settings={
"net_provider": 'neutron',
"net_segment_type": settings.NEUTRON_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)
self.fuel_web.verify_network(cluster_id)
self.show_step(8)
self.fuel_web.run_ostf(
cluster_id=cluster_id)
self.show_step(9)
self.env.admin_install_pkg('python-cudet')
self.env.make_snapshot(self.SNAPSHOT_NAME, is_make=True)
@test(depends_on=[customizations_check_env],
groups=['check_env_customizations'])
@log_snapshot_after_test
def check_env_customizations(self):
"""Check customizations of a node, of an env, of all nodes
Scenario:
1. Revert snapshot "customizations_check_env"
2. Update a package source on all env nodes
3. Check env for customizations - run cudet tool parametrizing it:
- for all nodes
- for all nodes of a particular env
- for a particular node
- for a particular node of a particular env
For each option verify that customized file is mentioned
in both, the command output and generated report.
Duration 10m
Snapshot: check_env_customizations
"""
self.show_step(1)
self.env.revert_snapshot(self.SNAPSHOT_NAME)
self.show_step(2)
cluster_id = self.fuel_web.get_last_created_cluster()
nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
for node in nodes:
self.add_comment_to_file_on_remote(
node['ip'], self.CUSTOMIZED_FILE1)
# Cudet command options to be verified:
# -e ENV_ID
# Check customizations only for the specified environment
# -n NODE_ID
# Check customizations only for the specified node
cases = {
"cudet -e {0}".format(cluster_id): nodes,
"cudet -n {0}".format(nodes[0]['id']): [nodes[0]],
"cudet -e {0} -n {1}".format(cluster_id, nodes[0]['id']):
[nodes[0]],
"cudet": nodes,
}
self.show_step(3)
for case in cases:
logger.info("Running {0}...".format(case))
result = self.ssh_manager.check_call(
self.ssh_manager.admin_ip, case, timeout=60 * 5)
asserts.assert_true(
self.CUSTOMIZED_FILE1 in result.stdout_str,
"Cudet doesn't report customizations in the command output")
asserts.assert_true(
self.ssh_manager.exists_on_remote(
self.ssh_manager.admin_ip,
self.CUDET_REPORT_PATH),
"Cudet report is not generated")
for node in cases[case]:
asserts.assert_true(
self.is_file_in_report(
cluster_id, node['id'], self.CUSTOMIZED_FILE1),
"The {0!r} customized file is not referenced in the "
"corresponding node report".format(self.CUSTOMIZED_FILE1))
logger.info("Deleting cudet report")
self.ssh_manager.rm_rf_on_remote(
self.ssh_manager.admin_ip, self.CUDET_REPORT_PATH)
self.env.make_snapshot('check_env_customizations')
@test(depends_on=[customizations_check_env],
groups=['regenerate_report'])
@log_snapshot_after_test
def regenerate_report(self):
"""Check cudet report regenerating
Scenario:
1. Revert snapshot "customizations_check_env"
2. Update a package source on a node
3. Run cudet specifying the node to evaluate
4. Verify that the report has been generated
5. Update another package source on the node
6. Run cudet specifying 'fake' option to only regenerate the report
7. Verify that the second updated file is not referenced
in the report
8. Run cudet specifying the same node to evaluate
9. Verify that the second updated file is referenced in the report
10. Delete the report
11. Run cudet specifying 'fake' option to only regenerate
the report
12. Verify that cudet doesn't generate report as
no data is available
Duration 10m
Snapshot: regenerate_report
"""
self.show_step(1)
self.env.revert_snapshot(self.SNAPSHOT_NAME)
self.show_step(2)
cluster_id = self.fuel_web.get_last_created_cluster()
nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
self.add_comment_to_file_on_remote(
nodes[0]['ip'], self.CUSTOMIZED_FILE1)
self.show_step(3)
result = self.ssh_manager.check_call(
self.ssh_manager.admin_ip,
"cudet -n {0}".format(nodes[0]['id']),
timeout=60 * 5)
self.show_step(4)
asserts.assert_true(
self.ssh_manager.exists_on_remote(
self.ssh_manager.admin_ip,
self.CUDET_REPORT_PATH),
"Cudet report is not generated")
self.show_step(5)
self.add_comment_to_file_on_remote(
nodes[0]['ip'], self.CUSTOMIZED_FILE2)
# -f command option is used to only regenerate report, without
# recollecting data from nodes
self.show_step(6)
self.ssh_manager.check_call(
self.ssh_manager.admin_ip,
"cudet -n {0} -f".format(nodes[0]['id']),
timeout=60 * 5)
self.show_step(7)
asserts.assert_false(
self.is_file_in_report(
cluster_id, nodes[0]['id'], self.CUSTOMIZED_FILE2),
"The {0!r} customized file is referenced in the report, despite "
"the fake run of cudet".format(self.CUSTOMIZED_FILE2))
self.show_step(8)
self.ssh_manager.check_call(
self.ssh_manager.admin_ip,
"cudet -n {0}".format(nodes[0]['id']),
timeout=60 * 5)
self.show_step(9)
asserts.assert_true(
self.is_file_in_report(
cluster_id, nodes[0]['id'], self.CUSTOMIZED_FILE2),
"The {0!r} customized file is not referenced in the "
"corresponding node report".format(self.CUSTOMIZED_FILE2))
self.show_step(10)
self.ssh_manager.rm_rf_on_remote(
self.ssh_manager.admin_ip, self.CUDET_REPORT_PATH)
self.show_step(11)
self.ssh_manager.check_call(
self.ssh_manager.admin_ip, "cudet -f", timeout=60 * 5)
self.show_step(12)
for node in nodes:
node_report_dir = os.path.join(
self.CUDET_REPORT_PATH,
"cmds/cluster-{0}/node-{1}".format(cluster_id, node['id']))
result = self.ssh_manager.check_call(
self.ssh_manager.admin_ip, "ls -A {0}".format(node_report_dir))
asserts.assert_equal(
len(result.stdout), 0,
"Report has been generated, although no data was collected")
self.env.make_snapshot('regenerate_report')
@test(depends_on=[customizations_check_env],
groups=['filter_nodes_via_config'])
@log_snapshot_after_test
def filter_nodes_via_config(self):
"""Check customizations filtering nodes to check via cudet config
Scenario:
1. Revert snapshot "customizations_check_env"
2. Update a package source on all env nodes
3. Check nodes for customizations filtering them using
cudet config file:
- specify filtering via env ID
- specify filtering via node ID
- specify filtering via role name
For each option verify that customized file is mentioned
in both, the command output and generated report.
Duration 10m
Snapshot: filter_nodes_via_config
"""
self.show_step(1)
self.env.revert_snapshot(self.SNAPSHOT_NAME)
self.show_step(2)
cluster_id = self.fuel_web.get_last_created_cluster()
nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
for node in nodes:
self.add_comment_to_file_on_remote(
node['ip'], self.CUSTOMIZED_FILE1)
cases = {
"roles": ["cinder",
self.fuel_web.get_nailgun_cluster_nodes_by_roles(
cluster_id, ["cinder"])],
"id": [nodes[0]['id'], [nodes[0]]],
"cluster": [cluster_id, nodes],
}
self.show_step(3)
cudet_config_dir = os.path.dirname(self.CUDET_CONFIG_PATH)
for case in cases:
with YamlEditor(
self.CUDET_CONFIG_PATH, self.ssh_manager.admin_ip) as ed:
initial_content = copy.deepcopy(ed.content)
ed.content['filters'][case].append(cases[case][0])
# -c command option allows to specify the path to custom config
# file to use instead of the default one
logger.info("Running filtering for {0}...".format(case))
result = self.ssh_manager.check_call(
self.ssh_manager.admin_ip,
"cd {0}; cudet -c {1}".format(cudet_config_dir,
self.CUDET_CONFIG_PATH),
timeout=60 * 5)
asserts.assert_true(
self.CUSTOMIZED_FILE1 in result.stdout_str,
"Cudet doesn't report customizations in the command output")
asserts.assert_true(
self.ssh_manager.exists_on_remote(
self.ssh_manager.admin_ip,
self.CUDET_REPORT_PATH),
"Cudet report is not generated")
for node in cases[case][1]:
asserts.assert_true(
self.is_file_in_report(
cluster_id, node['id'], self.CUSTOMIZED_FILE1),
"The {0!r} customized file is not referenced in the "
"corresponding node report".format(self.CUSTOMIZED_FILE1))
logger.info("Deleted cudet report")
self.ssh_manager.rm_rf_on_remote(
self.ssh_manager.admin_ip, self.CUDET_REPORT_PATH)
logger.info("Restore initial cudet config")
with YamlEditor(
self.CUDET_CONFIG_PATH, self.ssh_manager.admin_ip) as ed:
ed.content = copy.deepcopy(initial_content)
self.env.make_snapshot('filter_nodes_via_config')
@test(depends_on=[customizations_check_env],
groups=['invalid_parameters_processing'])
@log_snapshot_after_test
def invalid_parameters_processing(self):
"""Check that cudet handles invalid parameters
Scenario:
1. Revert snapshot "customizations_check_env"
2. Run cudet specifying an invalid env ID
3. Verify that the message is returned notifying about wrong
input and no report data is generated
4. Run cudet specifying an invalid node ID
5. Verify that the message is returned notifying about wrong
input and no report data is generated
6. Run cudet specifying an invalid custom config file
7. Verify that the message is returned notifying about wrong
input and no report data is generated
Duration 10m
Snapshot: invalid_parameters_processing
"""
self.show_step(1)
self.env.revert_snapshot(self.SNAPSHOT_NAME)
self.show_step(2)
result = self.ssh_manager.check_call(
self.ssh_manager.admin_ip, "cudet -e {0}".format(100))
self.show_step(3)
asserts.assert_true(
"There are no nodes to check" in result.stdout_str,
"No message is returned notifying about wrong input")
asserts.assert_false(
self.ssh_manager.exists_on_remote(
self.ssh_manager.admin_ip,
self.CUDET_REPORT_PATH),
"Cudet report is generated")
self.show_step(4)
result = self.ssh_manager.check_call(
self.ssh_manager.admin_ip, "cudet -n {0}".format(100))
self.show_step(5)
asserts.assert_true(
"There are no nodes to check" in result.stdout_str,
"No message is returned notifying about wrong input")
asserts.assert_false(
self.ssh_manager.exists_on_remote(
self.ssh_manager.admin_ip,
self.CUDET_REPORT_PATH),
"Cudet report is generated")
self.show_step(6)
result = self.ssh_manager.check_call(
self.ssh_manager.admin_ip,
"cudet -c {0}".format("fake_config"),
expected=[1])
self.show_step(7)
asserts.assert_true(
"No such file or directory" in result.stderr_str,
"No message is returned notifying about wrong input")
asserts.assert_false(
self.ssh_manager.exists_on_remote(
self.ssh_manager.admin_ip,
self.CUDET_REPORT_PATH),
"Cudet report is generated")
self.env.make_snapshot('invalid_parameters_processing')
@test(depends_on=[customizations_check_env],
groups=['check_offline_node_customizations'])
@log_snapshot_after_test
def check_offline_node_customizations(self):
"""Check that cudet handles attempt to check customizations
of an offline node
Scenario:
1. Revert snapshot "customizations_check_env"
2. Update a package source on a node
3. Shutdown the node
4. Run cudet specifying the node to evaluate
5. Verify that no customization data is in the generated report
Duration 10m
Snapshot: check_offline_node_customizations
"""
self.show_step(1)
self.env.revert_snapshot(self.SNAPSHOT_NAME)
self.show_step(2)
cluster_id = self.fuel_web.get_last_created_cluster()
node = self.fuel_web.client.list_cluster_nodes(cluster_id)[0]
self.add_comment_to_file_on_remote(node['ip'], self.CUSTOMIZED_FILE1)
self.show_step(3)
devops_node = self.fuel_web.get_devops_node_by_nailgun_node(node)
self.fuel_web.warm_shutdown_nodes([devops_node])
self.show_step(4)
self.ssh_manager.check_call(
self.ssh_manager.admin_ip,
"cudet -n {0}".format(node['id']),
timeout=60 * 5)
asserts.assert_false(
self.is_file_in_report(
cluster_id, node['id'], self.CUSTOMIZED_FILE1),
"The data have been collected, although the node is offline")
self.env.make_snapshot('check_offline_node_customizations')