Add new tests for reboot task for plugin feature.

Change-Id: I79f288fe3a56e16329ea2b0628c7841f44c686bf
Implements: blueprint reboot-action-for-plugin
This commit is contained in:
Alexander Kurenyshev 2015-03-05 17:25:25 +03:00
parent 9a6a526500
commit 1ca1eb4200
10 changed files with 415 additions and 4 deletions

View File

@ -19,6 +19,8 @@ from proboscis.asserts import assert_equal
from fuelweb_test import logger
from fuelweb_test.settings import FUEL_PLUGIN_BUILDER_REPO
class BaseActions(object):
def __init__(self, admin_remote):
@ -46,6 +48,31 @@ class BaseActions(object):
))
return ''.join(result['stdout']).strip()
def copy_between_node_and_container(self, copy_from, copy_to):
""" Copy files from/to container.
:param copy_from: path to copy file from
:param copy_to: path to copy file to
For ex.:
to copy from container to master node use:
copy_from = container:path_from
copy_to = path_to
to copy from master node to container use:
copy_from = path_from
copy_to = container:path_to
:return:
Standard output from console
"""
cmd = 'dockerctl copy {0} {1}'.format(copy_from, copy_to)
result = self.admin_remote.execute(cmd)
assert_equal(0, result['exit_code'],
('Command copy returned exit code "{e}", but '
'expected "0". Output: {out}; {err} ').format(
cmd=cmd,
e=result['exit_code'],
out=result['stdout'],
err=result['stderr']))
return ''.join(result['stdout']).strip()
class NailgunActions(BaseActions):
def __init__(self, admin_remote):
@ -125,3 +152,131 @@ class PostgresActions(BaseActions):
def count_sent_action_logs(self, table='action_logs'):
q = "select count(id) from {0} where is_sent = True".format(table)
return int(self.run_query('nailgun', q))
class FuelPluginBuilder(object):
"""
Basic class for fuel plugin builder support in tests.
Initializes BaseActions.
"""
def __init__(self, admin_remote):
self.admin_remote = admin_remote
self.admin_node = BaseActions(self.admin_remote)
def fpb_install(self):
"""
Installs fuel plugin builder from sources
in nailgun container on master node
:return: nothing
"""
fpb_cmd = """bash -c 'yum -y install git tar createrepo \
rpm dpkg-devel rpm-build;
git clone {0};
cd fuel-plugins/fuel_plugin_builder;
python setup.py sdist;
cd dist;
pip install *.tar.gz'""".format(FUEL_PLUGIN_BUILDER_REPO)
self.admin_node.execute_in_container(fpb_cmd, 'nailgun', 0)
def fpb_create_plugin(self, name):
"""
Creates new plugin with given name
:param name: name for plugin created
:return: nothing
"""
self.admin_node.execute_in_container("fpb --create {0}"
.format(name), 'nailgun', 0)
def fpb_build_plugin(self, path):
"""
Builds plugin from path
:param path: path to plugin. For ex.: /root/example_plugin
:return: nothing
"""
self.admin_node.execute_in_container("fpb --build {0}"
.format(path), 'nailgun', 0)
def fpb_validate_plugin(self, path):
"""
Validates plugin for errors
:param path: path to plugin to be verified
:return: nothing
"""
self.admin_node.execute_in_container("fpb --check {0}"
.format(path), 'nailgun', 0)
def fpb_copy_plugin_from_container(self, plugin_name, path_to):
"""
Copies plugin with given name to path
outside container on the master node
:param plugin_name: plugin to be copied
:param path_to: path to copy to
:return: nothing
"""
self.admin_node.copy_between_node_and_container(
'nailgun:/root/{0}/*.rpm'.format(plugin_name),
'{0}/{1}.rpm'.format(path_to, plugin_name))
def fpb_replace_plugin_content(self, local_file, remote_file):
"""
Replaces file inside nailgun container with given local file
:param local_file: path to the local file
:param remote_file: file to be replaced
:return: nothing
"""
self.admin_node.execute_in_container(
"rm -rf {0}".format(remote_file), 'nailgun')
self.admin_remote.upload(local_file, "/tmp/temp.file")
self.admin_node.copy_between_node_and_container(
'/tmp/temp.file', 'nailgun:{0}'.format(remote_file))
def fpb_change_plugin_version(self, plugin_name, new_version):
"""
Changes plugin version with given one
:param plugin_name: plugin name
:param new_version: new version to be used for plugin
:return: nothing
"""
self.admin_node.execute_in_container(
'sed -i "s/^\(version:\) \(.*\)/\\1 {0}/g" '
'/root/{1}/metadata.yaml'
.format(new_version, plugin_name), 'nailgun')
def fpb_change_package_version(self, plugin_name, new_version):
"""
Changes plugin's package version
:param plugin_name: plugin to be used for changing version
:param new_version: version to be changed at
:return: nothing
"""
self.admin_node.execute_in_container(
'sed -i "s/^\(package_version: \'\)\(.*\)\(\'\)/\\1{0}\\3/g" '
'/root/{1}/metadata.yaml'
.format(new_version, plugin_name), 'nailgun')
def change_content_in_yaml(self, old_file, new_file, element, value):
"""
Changes content in old_file at element is given to the new value
and creates new file with changed content
:param old_file: a path to the file content from to be changed
:param new_file: a path to the new file to ve created with new content
:param element: tuple with path to element to be changed
for example: ['root_elem', 'first_elem', 'target_elem']
if there are a few elements with equal names use integer
to identify which element should be used
:return: nothing
"""
with open(old_file, 'r') as f_old:
yaml_dict = yaml.load(f_old)
origin_yaml = yaml_dict
for k in element[:-1]:
yaml_dict = yaml_dict[k]
yaml_dict[element[-1]] = value
with open(new_file, 'w') as f_new:
yaml.dump(origin_yaml, f_new)

View File

@ -21,6 +21,7 @@ def import_tests():
from tests.plugins.plugin_example import test_fuel_plugin_example # noqa
from tests.plugins.plugin_glusterfs import test_plugin_glusterfs # noqa
from tests.plugins.plugin_lbaas import test_plugin_lbaas # noqa
from tests.plugins.plugin_reboot import test_plugin_reboot_task # noqa
from tests import test_multiple_networks # noqa

View File

@ -369,3 +369,5 @@ EXTERNAL_NTP = os.environ.get('EXTERNAL_NTP', 'ua.pool.ntp.org')
TIMESTAT_PATH_YAML = os.environ.get(
'TIMESTAT_PATH_YAML', os.path.join(
LOGS_DIR, 'timestat_{}.yaml'.format(time.strftime("%Y%m%d"))))
FUEL_PLUGIN_BUILDER_REPO = 'https://github.com/stackforge/fuel-plugins.git'

View File

@ -1 +0,0 @@
__author__ = 'tleontovich'

View File

@ -1 +0,0 @@
__author__ = 'tleontovich'

View File

@ -1 +0,0 @@
__author__ = 'tleontovich'

View File

@ -1 +0,0 @@
__author__ = 'tleontovich'

View File

@ -0,0 +1,19 @@
- role: ['controller', 'ceph-osd']
stage: pre_deployment
type: shell
parameters:
cmd: sleep 20
timeout: 30
- role: ['controller', 'ceph-osd']
stage: pre_deployment
type: reboot
parameters:
timeout: 60
- role: ['controller', 'ceph-osd']
stage: pre_deployment
type: shell
parameters:
cmd: sleep 50
timeout: 60

View File

@ -0,0 +1,238 @@
# Copyright 2015 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 os
from proboscis import asserts
from proboscis import test
from fuelweb_test.helpers import checkers
from fuelweb_test import logger
from fuelweb_test.settings import DEPLOYMENT_MODE
from fuelweb_test.tests.base_test_case import SetupEnvironment
from fuelweb_test.tests.base_test_case import TestBasic
from fuelweb_test.helpers.fuel_actions import FuelPluginBuilder
@test(groups=["plugins"])
class RebootPlugin(TestBasic):
"""
Test class for testing reboot task in plugins
"""
@test(depends_on=[SetupEnvironment.prepare_slaves_5],
groups=["deploy_cluster_with_reboot_plugin"])
def deploy_cluster_with_reboot_plugin(self):
"""Add pre-deployment reboot task to nailgun via plugin.
Scenario:
1. Revert snapshot with 5 nodes
2. Download and install fuel-plugin-builder
3. Create plugin with reboot task
4. Build and copy plugin from container nailgun
5. Install plugin to fuel
6. Create cluster and enable plugin
7. Provision nodes
8. Collect timestamps from nodes
9. Deploy cluster
10. Check if timestamps are changed
Duration 40m
"""
# define some plugin related variables
plugin_name = 'reboot_plugin'
plugin_path = '/var'
tasks_path = os.path.dirname(os.path.abspath(__file__))
tasks_file = 'reboot_tasks.yaml'
# start reverting snapshot
self.env.revert_snapshot("ready_with_5_slaves")
# let's get ssh client for the master node
admin_remote = self.env.d_env.get_admin_remote()
# initiate fuel plugin builder instance
fpb = FuelPluginBuilder(admin_remote)
# install fuel_plugin_builder on master node
fpb.fpb_install()
# create plugin template on the master node
fpb.fpb_create_plugin(plugin_name)
# replace plugin tasks with our file
fpb.fpb_replace_plugin_content(
os.path.join(tasks_path, tasks_file),
os.path.join('/root/', plugin_name, 'tasks.yaml'))
# build plugin
fpb.fpb_build_plugin(os.path.join('/root/', plugin_name))
# copy plugin archive file from nailgun container
# to the /var directory on the master node
fpb.fpb_copy_plugin_from_container(plugin_name, plugin_path)
# let's install plugin
checkers.install_plugin_check_code(
admin_remote,
plugin=os.path.join(plugin_path, '{}.rpm'.format(plugin_name)))
# create cluster
cluster_id = self.fuel_web.create_cluster(
name=self.__class__.__name__,
mode=DEPLOYMENT_MODE
)
# get plugins from fuel and enable our one
attr = self.fuel_web.client.get_cluster_attributes(cluster_id)
if plugin_name in attr['editable']:
plugin_data = attr['editable'][plugin_name]['metadata']
plugin_data['enabled'] = True
self.fuel_web.client.update_cluster_attributes(cluster_id, attr)
logger.info('cluster is %s' % str(cluster_id))
self.fuel_web.update_nodes(
cluster_id,
{'slave-01': ['controller', 'ceph-osd'],
'slave-02': ['compute', 'ceph-osd'],
'slave-03': ['compute'],
'slave-04': ['ceph-osd']}
)
# firstly, let's provision nodes
self.fuel_web.provisioning_cluster_wait(cluster_id)
# after provision is done, collect timestamps from nodes
old_timestamps = {}
nodes = {
'slave-01': True,
'slave-02': True,
'slave-03': False,
'slave-04': True
}
for node in nodes:
logger.debug(
"Get init object creation time from node {0}".format(node))
cmd = 'stat --printf=\'%Y\' /proc/1'
_ip = self.fuel_web.get_nailgun_node_by_name(node)['ip']
old_timestamps[node] = self.env.d_env.get_ssh_to_remote(
_ip).execute(cmd)['stdout'][0]
# start deploying nodes
# here nodes with controller and ceph roles should be rebooted
self.fuel_web.deploy_cluster_wait_progress(cluster_id, 30)
# collect new timestamps and check them
for node in nodes:
logger.debug(
"Get init object creation time from node {0}".format(node))
cmd = 'stat --printf=\'%Y\' /proc/1'
_ip = self.fuel_web.get_nailgun_node_by_name(node)['ip']
new_timestamp = self.env.d_env.get_ssh_to_remote(
_ip).execute(cmd)['stdout'][0]
# compute node without ceph role shouldn't reboot
if not nodes[node]:
asserts.assert_equal(
new_timestamp, old_timestamps[node],
'The new timestamp {0} is not equal to old one {1}, '
'but it shouldn\'t for {2} node'
.format(new_timestamp, old_timestamps[node], node)
)
else:
# other nodes should be rebooted and have new timestamps
# greater than old
asserts.assert_true(
new_timestamp > old_timestamps[node],
'The new timestamp {0} is not greater than old one {1} '
'but it should for node {2}'
.format(new_timestamp, old_timestamps[node], node)
)
@test(depends_on=[SetupEnvironment.prepare_slaves_3],
groups=["deploy_cluster_with_reboot_plugin_timeout"])
def deploy_cluster_with_reboot_plugin_timeout(self):
"""Check deployment is failed by reboot task plugin.
Scenario:
1. Revert snapshot with 3 nodes
2. Download and install fuel-plugin-builder
3. Create plugin with reboot task,
set timeout for reboot task as 1 second
4. Build and copy plugin from container nailgun
5. Install plugin to fuel
6. Create cluster and enable plugin
7. Provision nodes
8. Deploy cluster
9. Check deployment was failed by reboot task
10. Check error msg at the logs
Duration 15m
"""
# define some plugin related variables
plugin_name = 'timeout_plugin'
plugin_path = '/var'
tasks_path = os.path.dirname(os.path.abspath(__file__))
tasks_file = 'reboot_tasks.yaml'
# start reverting snapshot
self.env.revert_snapshot("ready_with_3_slaves")
# let's get ssh client for the master node
admin_remote = self.env.d_env.get_admin_remote()
# initiate fuel plugin builder instance
fpb = FuelPluginBuilder(admin_remote)
# install fuel_plugin_builder on master node
fpb.fpb_install()
# change timeout to a new value '1'
fpb.change_content_in_yaml(os.path.join(tasks_path, tasks_file),
os.path.join('/tmp/', tasks_file),
[1, 'parameters', 'timeout'],
1)
# create plugin template on the master node
fpb.fpb_create_plugin(plugin_name)
# replace plugin tasks with our file
fpb.fpb_replace_plugin_content(
os.path.join('/tmp/', tasks_file),
os.path.join('/root/', plugin_name, 'tasks.yaml')
)
# build plugin
fpb.fpb_build_plugin(os.path.join('/root/', plugin_name))
# copy plugin archive file from nailgun container
# to the /var directory on the master node
fpb.fpb_copy_plugin_from_container(plugin_name, plugin_path)
# let's install plugin
checkers.install_plugin_check_code(
admin_remote,
plugin=os.path.join(plugin_path, '{}.rpm'.format(plugin_name)))
# create cluster
cluster_id = self.fuel_web.create_cluster(
name=self.__class__.__name__,
mode=DEPLOYMENT_MODE
)
# get plugins from fuel and enable it
attr = self.fuel_web.client.get_cluster_attributes(cluster_id)
if plugin_name in attr['editable']:
plugin_data = attr['editable'][plugin_name]['metadata']
plugin_data['enabled'] = True
self.fuel_web.client.update_cluster_attributes(cluster_id, attr)
logger.info('cluster is %s' % str(cluster_id))
self.fuel_web.update_nodes(
cluster_id,
{'slave-01': ['controller', 'ceph-osd']}
)
self.fuel_web.provisioning_cluster_wait(cluster_id)
logger.info('Start cluster #%s deployment', cluster_id)
task = self.fuel_web.client.deploy_nodes(cluster_id)
self.fuel_web.assert_task_failed(task)
msg = 'Time detection (1 sec) for node reboot has expired'
cmd = 'grep "{0}" /var/log/docker-logs/astute/astute.log'.format(msg)
result = admin_remote.execute(cmd)['stdout'][0]
asserts.assert_true(
msg in result,
'Failed to find reboot plugin warning message in logs'
)