Refine tobiko faults

* Setup proper logging
* Extend os-faults configuration template with more services
* Add unit tests initial files (Python API and CLI)
* Add proper doc explaining how to use tobiko faults

Change-Id: I6d528981fea6c76d20f4da095a86189748038f77
This commit is contained in:
abregman 2019-06-05 12:23:31 +03:00
parent a9e05e110c
commit 935856cb21
11 changed files with 160 additions and 12 deletions

3
.gitignore vendored
View File

@ -27,3 +27,6 @@ zuul/versioninfo
# Files created by releasenotes build
releasenotes/build
Pipfile.lock
tobiko.conf

View File

@ -11,3 +11,4 @@ Tobiko User Guide
install
config
run-test-cases
run-faults

View File

@ -0,0 +1,51 @@
.. _tobiko-faults-execution-guide:
=================================
Tobiko Faults Execution Guide
=================================
This document describes how to execute faults with Tobiko.
.. sidebar:: See also
For a quick and simpler start you can jump to the
:ref:`tobiko-quick-start-guide`.
To install Tobiko inside a virutalenv please read
:ref:`tobiko-installation-guide`.
To configure Tobiko please read :ref:`tobiko-configuration-guide`.
Requirements
~~~~~~~~~~~~
In order to be able faults with Tobiko you need an RC file
for your OpenStack hosts (not the instances which run on OpenStack hosts)
Using this RC file, Tobiko will be able to generate an os-faults configuration
for you automatically. If you already have os-faults configuration file, you
don't need this requirement.
CLI
~~~
In order to restart openvswitch service, run the following command:
tobiko-fault "restart openvswitch service"
Python API
~~~~~~~~~~
You can also use faults in your tests. Warning: running a fault in a test
while other tests are running in parallel might have negative affect on your
other tests.
from tobiko.fault.executor import FaultExecutor
fault = FaultExecutor()
fault.execute("restart openvswitch service")
Missing services & containers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
What to do if the service or the container I'm trying to control
is not part of os-faults configuration? In that case please submit a patch
to Tobiko to add it to tobiko/fault/templates/os-faults.yml.j2 template.

View File

@ -32,8 +32,7 @@ class FaultCMD(object):
def get_parser(self):
parser = argparse.ArgumentParser(add_help=True)
parser.add_argument(
'--fault',
required=True,
'fault',
help="The fault to execute (e.g. restart neutron service).\n")
return parser
@ -43,8 +42,17 @@ class FaultCMD(object):
fault_exec.execute(self.args.fault)
def setup_logging(debug=None):
"""Sets the logging."""
# pylint: disable=W0622
format = '%(message)s'
level = logging.DEBUG if debug else logging.INFO
logging.basicConfig(level=level, format=format)
def main():
"""Run CLI main entry."""
setup_logging()
fault_cli = FaultCMD()
fault_cli.run()

View File

@ -67,7 +67,7 @@ class FaultConfig(object):
containers=fault_const.CONTAINERS)
def get_nodes(self):
"""Returns a list of dictonaries with nodes name and address."""
"""Returns a list of dictionaries with nodes name and address."""
client = nova.get_nova_client()
return [{'name': server.name,
'address': server.addresses['ctlplane'][0]['addr']}

View File

@ -13,5 +13,7 @@
# under the License.
from __future__ import absolute_import
SERVICES = ['openvsiwtch']
SERVICES = ['openvswitch', 'tripleo_cinder_api', 'tripleo_cinder_api_cron',
'tripleo_cinder_scheduler', 'tripleo_clustercheck',
'tripleo_glance_api', 'tripleo_horizon']
CONTAINERS = ['neutron_ovs_agent', 'neutron_metadata_agent', 'neutron_api']

View File

@ -13,8 +13,11 @@
# under the License.
from __future__ import absolute_import
import sys
from oslo_log import log
import jsonschema
import os_faults
from tobiko.fault.config import FaultConfig
@ -25,14 +28,9 @@ LOG = log.getLogger(__name__)
class FaultExecutor(object):
"""Responsible for executing faults."""
def __init__(self, conf_file=None):
def __init__(self, conf_file=None, cloud=None):
self.config = FaultConfig(conf_file=conf_file)
try:
self.connect()
LOG.info("os-faults connected.")
except os_faults.api.error.OSFError:
msg = "Unable to connect. Please check your configuration."
raise RuntimeError(msg)
self.cloud = cloud
def connect(self):
"""Connect to the cloud using os-faults."""
@ -43,7 +41,12 @@ class FaultExecutor(object):
except os_faults.ansible.executor.AnsibleExecutionUnreachable:
LOG.warning("Couldn't verify connectivity to the"
" cloud with os-faults configuration")
except jsonschema.exceptions.ValidationError:
LOG.error("Wrong os-fault configuration format. Exiting...")
sys.exit(2)
def execute(self, fault):
"""Executes given fault using os-faults human API."""
LOG.info("Using %s" % self.config.conf_file)
self.connect()
os_faults.human_api(self.cloud, fault)

View File

@ -10,7 +10,6 @@ node_discover:
auth:
username: heat-admin
private_key_file: /home/stack/.ssh/id_rsa
become: true
{% endfor %}
services:

View File

@ -0,0 +1,48 @@
# Copyright (c) 2018 Red Hat
# All Rights Reserved.
#
# 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 absolute_import
import argparse
import sys
from tobiko.cmd import fault as _fault
from tobiko.tests import unit
class FaultCMDTest(unit.TobikoUnitTest):
command_name = 'tobiko-fault'
command_class = _fault.FaultCMD
default_fault = ["some_fault"]
def setUp(self):
super(FaultCMDTest, self).setUp()
self.mock_error = self.patch(argparse.ArgumentParser, 'error',
side_effect=self.fail)
def patch_argv(self, arguments=None):
"""Patch argv"""
arguments = list(arguments or [])
if not arguments:
arguments = self.default_fault
return self.patch(sys, 'argv',
[self.command_name] + arguments)
def test_init(self, arguments=None):
self.patch_argv(arguments=arguments)
command = self.command_class()
self.mock_error.assert_not_called()
args = command.args
self.assertIsNotNone(args)

View File

View File

@ -0,0 +1,33 @@
# Copyright (c) 2019 Red Hat, Inc.
#
# All Rights Reserved.
#
# 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 absolute_import
from tobiko.tests import unit
from tobiko.fault import executor
class FaultTest(unit.TobikoUnitTest):
conf_file = "/some/conf/file"
fault = "some_fault"
def setUp(self):
super(FaultTest, self).setUp()
self.fault_exec = executor.FaultExecutor(conf_file=self.conf_file)
def test_init(self):
self.assertEqual(self.fault_exec.config.conf_file, self.conf_file)
self.assertEqual(self.fault_exec.cloud, None)