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:
parent
a9e05e110c
commit
935856cb21
3
.gitignore
vendored
3
.gitignore
vendored
@ -27,3 +27,6 @@ zuul/versioninfo
|
||||
|
||||
# Files created by releasenotes build
|
||||
releasenotes/build
|
||||
|
||||
Pipfile.lock
|
||||
tobiko.conf
|
||||
|
@ -11,3 +11,4 @@ Tobiko User Guide
|
||||
install
|
||||
config
|
||||
run-test-cases
|
||||
run-faults
|
||||
|
51
doc/source/user/run-faults.rst
Normal file
51
doc/source/user/run-faults.rst
Normal 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.
|
@ -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()
|
||||
|
||||
|
@ -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']}
|
||||
|
@ -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']
|
||||
|
@ -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)
|
||||
|
@ -10,7 +10,6 @@ node_discover:
|
||||
auth:
|
||||
username: heat-admin
|
||||
private_key_file: /home/stack/.ssh/id_rsa
|
||||
become: true
|
||||
{% endfor %}
|
||||
|
||||
services:
|
||||
|
48
tobiko/tests/unit/cmd/test_fault.py
Normal file
48
tobiko/tests/unit/cmd/test_fault.py
Normal 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)
|
0
tobiko/tests/unit/fault/__init__.py
Normal file
0
tobiko/tests/unit/fault/__init__.py
Normal file
33
tobiko/tests/unit/fault/test_fault.py
Normal file
33
tobiko/tests/unit/fault/test_fault.py
Normal 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)
|
Loading…
Reference in New Issue
Block a user