Move back tripleo_validator.py to tripleoclient
The reason of this revert is example in the depends-on review in tripleoclient Depends-On: https://review.opendev.org/c/openstack/python-tripleoclient/+/782776 Change-Id: Ifab62c734bf8d1f2f6647144b084d1ec1313588d
This commit is contained in:
parent
c876cbba8d
commit
408aec4dc3
13
setup.cfg
13
setup.cfg
@ -38,16 +38,3 @@ data_files =
|
||||
share/ansible/callback_plugins = callback_plugins/*
|
||||
share/ansible/lookup_plugins = lookup_plugins/*
|
||||
share/ansible/library = library/*
|
||||
|
||||
[entry_points]
|
||||
openstack.cli.extension =
|
||||
tripleo_validations = tripleo_validations.plugin
|
||||
|
||||
openstack.tripleo_validations.v2 =
|
||||
tripleo_validator_group_info = tripleo_validations.tripleo_validator:TripleOValidatorGroupInfo
|
||||
tripleo_validator_list = tripleo_validations.tripleo_validator:TripleOValidatorList
|
||||
tripleo_validator_run = tripleo_validations.tripleo_validator:TripleOValidatorRun
|
||||
tripleo_validator_show = tripleo_validations.tripleo_validator:TripleOValidatorShow
|
||||
tripleo_validator_show_history = tripleo_validations.tripleo_validator:TripleOValidatorShowHistory
|
||||
tripleo_validator_show_parameter = tripleo_validations.tripleo_validator:TripleOValidatorShowParameter
|
||||
tripleo_validator_show_run = tripleo_validations.tripleo_validator:TripleOValidatorShowRun
|
||||
|
@ -1,279 +0,0 @@
|
||||
# Copyright 2018 Red Hat, 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 mock
|
||||
|
||||
from osc_lib.tests import utils
|
||||
from tripleo_validations import tripleo_validator
|
||||
|
||||
VALIDATIONS_LIST = [{
|
||||
'description': 'My Validation One Description',
|
||||
'groups': ['prep', 'pre-deployment'],
|
||||
'id': 'my_val1',
|
||||
'name': 'My Validition One Name',
|
||||
'parameters': {}
|
||||
}, {
|
||||
'description': 'My Validation Two Description',
|
||||
'groups': ['prep', 'pre-introspection'],
|
||||
'id': 'my_val2',
|
||||
'name': 'My Validition Two Name',
|
||||
'parameters': {'min_value': 8}
|
||||
}]
|
||||
|
||||
GROUPS_LIST = [
|
||||
('group1', 'Group1 description'),
|
||||
('group2', 'Group2 description'),
|
||||
('group3', 'Group3 description'),
|
||||
]
|
||||
|
||||
VALIDATIONS_LOGS_CONTENTS_LIST = [{
|
||||
'plays': [{
|
||||
'play': {
|
||||
'duration': {
|
||||
'end': '2019-11-25T13:40:17.538611Z',
|
||||
'start': '2019-11-25T13:40:14.404623Z',
|
||||
'time_elapsed': '0:00:03.753'
|
||||
},
|
||||
'host': 'undercloud',
|
||||
'id': '008886df-d297-1eaa-2a74-000000000008',
|
||||
'validation_id': '512e',
|
||||
'validation_path':
|
||||
'/usr/share/ansible/validation-playbooks'
|
||||
},
|
||||
'tasks': [
|
||||
{
|
||||
'hosts': {
|
||||
'undercloud': {
|
||||
'_ansible_no_log': False,
|
||||
'action': 'command',
|
||||
'changed': False,
|
||||
'cmd': [u'ls', '/sys/class/block/'],
|
||||
'delta': '0:00:00.018913',
|
||||
'end': '2019-11-25 13:40:17.120368',
|
||||
'invocation': {
|
||||
'module_args': {
|
||||
'_raw_params': 'ls /sys/class/block/',
|
||||
'_uses_shell': False,
|
||||
'argv': None,
|
||||
'chdir': None,
|
||||
'creates': None,
|
||||
'executable': None,
|
||||
'removes': None,
|
||||
'stdin': None,
|
||||
'stdin_add_newline': True,
|
||||
'strip_empty_ends': True,
|
||||
'warn': True
|
||||
}
|
||||
},
|
||||
'rc': 0,
|
||||
'start': '2019-11-25 13:40:17.101455',
|
||||
'stderr': '',
|
||||
'stderr_lines': [],
|
||||
'stdout': 'vda',
|
||||
'stdout_lines': [u'vda']
|
||||
}
|
||||
},
|
||||
'task': {
|
||||
'duration': {
|
||||
'end': '2019-11-25T13:40:17.336687Z',
|
||||
'start': '2019-11-25T13:40:14.529880Z'
|
||||
},
|
||||
'id':
|
||||
'008886df-d297-1eaa-2a74-00000000000d',
|
||||
'name':
|
||||
'advanced-format-512e-support : List the available drives'
|
||||
}
|
||||
},
|
||||
{
|
||||
'hosts': {
|
||||
'undercloud': {
|
||||
'action':
|
||||
'advanced_format',
|
||||
'changed': False,
|
||||
'msg':
|
||||
'All items completed',
|
||||
'results': [{
|
||||
'_ansible_item_label': 'vda',
|
||||
'_ansible_no_log': False,
|
||||
'ansible_loop_var': 'item',
|
||||
'changed': False,
|
||||
'item': 'vda',
|
||||
'skip_reason': 'Conditional result was False',
|
||||
'skipped': True
|
||||
}],
|
||||
'skipped': True
|
||||
}
|
||||
},
|
||||
'task': {
|
||||
'duration': {
|
||||
'end': '2019-11-25T13:40:17.538611Z',
|
||||
'start': '2019-11-25T13:40:17.341704Z'
|
||||
},
|
||||
'id': '008886df-d297-1eaa-2a74-00000000000e',
|
||||
'name':
|
||||
'advanced-format-512e-support: Detect the drive'
|
||||
}
|
||||
}
|
||||
]
|
||||
}],
|
||||
'stats': {
|
||||
'undercloud': {
|
||||
'changed': 0,
|
||||
'failures': 0,
|
||||
'ignored': 0,
|
||||
'ok': 1,
|
||||
'rescued': 0,
|
||||
'skipped': 1,
|
||||
'unreachable': 0
|
||||
}
|
||||
},
|
||||
'validation_output': []
|
||||
}]
|
||||
|
||||
|
||||
class TestValidatorGroupInfo(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestValidatorGroupInfo, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = tripleo_validator.TripleOValidatorGroupInfo(self.app, None)
|
||||
|
||||
@mock.patch('validations_libs.validation_actions.ValidationActions.'
|
||||
'group_information', return_value=GROUPS_LIST)
|
||||
def test_show_group_info(self, mock_validations):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
|
||||
class TestValidatorList(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestValidatorList, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = tripleo_validator.TripleOValidatorList(self.app, None)
|
||||
|
||||
@mock.patch('validations_libs.validation_actions.ValidationActions.'
|
||||
'list_validations',
|
||||
return_value=VALIDATIONS_LIST)
|
||||
def test_validation_list_noargs(self, mock_validations):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
|
||||
class TestValidatorShow(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestValidatorShow, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = tripleo_validator.TripleOValidatorShow(self.app, None)
|
||||
|
||||
@mock.patch('validations_libs.validation_actions.ValidationActions.'
|
||||
'show_validations',
|
||||
return_value=VALIDATIONS_LIST[0])
|
||||
def test_validation_show(self, mock_validations):
|
||||
arglist = ['my_val1']
|
||||
verifylist = [('validation_id', 'my_val1')]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
|
||||
class TestValidatorShowParameter(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestValidatorShowParameter, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = tripleo_validator.TripleOValidatorShowParameter(self.app,
|
||||
None)
|
||||
|
||||
@mock.patch('validations_libs.validation_actions.ValidationActions.'
|
||||
'show_validations_parameters',
|
||||
return_value=VALIDATIONS_LIST[1])
|
||||
def test_validation_show_parameter(self, mock_validations):
|
||||
arglist = ['--validation', 'my_val2']
|
||||
verifylist = [('validation_name', ['my_val2'])]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
|
||||
class TestValidatorShowRun(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestValidatorShowRun, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = tripleo_validator.TripleOValidatorShowRun(self.app,
|
||||
None)
|
||||
|
||||
@mock.patch('validations_libs.validation_actions.ValidationLogs.'
|
||||
'get_logfile_content_by_uuid',
|
||||
return_value=VALIDATIONS_LOGS_CONTENTS_LIST)
|
||||
def test_validation_show_run(self, mock_validations):
|
||||
arglist = ['008886df-d297-1eaa-2a74-000000000008']
|
||||
verifylist = [('uuid', '008886df-d297-1eaa-2a74-000000000008')]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
|
||||
class TestValidatorShowHistory(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestValidatorShowHistory, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = tripleo_validator.TripleOValidatorShowHistory(self.app,
|
||||
None)
|
||||
|
||||
@mock.patch('validations_libs.validation_actions.ValidationActions.'
|
||||
'show_history',
|
||||
return_value=VALIDATIONS_LOGS_CONTENTS_LIST)
|
||||
def test_validation_show_history(self, mock_validations):
|
||||
arglist = []
|
||||
verifylist = []
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
@mock.patch('validations_libs.validation_actions.ValidationActions.'
|
||||
'show_history',
|
||||
return_value=VALIDATIONS_LOGS_CONTENTS_LIST)
|
||||
def test_validation_show_history_for_a_validation(self, mock_validations):
|
||||
arglist = [
|
||||
'--validation',
|
||||
'512e'
|
||||
]
|
||||
verifylist = [('validation', '512e')]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
@ -13,27 +13,6 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
DEFAULT_VALIDATIONS_BASEDIR = "/usr/share/ansible"
|
||||
DEFAULT_VALIDATIONS_LEGACY_BASEDIR = "/usr/share/openstack-tripleo-validations"
|
||||
|
||||
VALIDATIONS_LOG_BASEDIR = '/var/log/validations'
|
||||
|
||||
ANSIBLE_VALIDATION_DIR = (
|
||||
os.path.join(DEFAULT_VALIDATIONS_LEGACY_BASEDIR, 'playbooks')
|
||||
if os.path.exists(os.path.join(DEFAULT_VALIDATIONS_LEGACY_BASEDIR,
|
||||
'playbooks'))
|
||||
else "/usr/share/ansible/validation-playbooks"
|
||||
)
|
||||
|
||||
|
||||
VALIDATION_GROUPS_INFO = (
|
||||
'/usr/share/ansible/groups.yaml'
|
||||
if os.path.exists('/usr/share/ansible/groups.yaml')
|
||||
else os.path.join(DEFAULT_VALIDATIONS_LEGACY_BASEDIR, 'groups.yaml')
|
||||
)
|
||||
|
||||
# TRIPLEO_META_USAGE_KEY is inserted into metadata for containers created in
|
||||
# Swift via SwiftPlanStorageBackend to identify them from other containers
|
||||
TRIPLEO_META_USAGE_KEY = 'x-container-meta-usage-tripleo'
|
||||
|
@ -1,55 +0,0 @@
|
||||
# Copyright 2013 Nebula 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.
|
||||
#
|
||||
|
||||
"""OpenStackClient Plugin interface"""
|
||||
|
||||
import logging
|
||||
|
||||
from osc_lib import utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_TRIPLEO_VALIDATION_API_VERSION = '2'
|
||||
|
||||
# Required by the OSC plugin interface
|
||||
API_NAME = 'tripleo_validations'
|
||||
API_VERSION_OPTION = 'os_tripleo_validations_api_version'
|
||||
API_VERSIONS = {
|
||||
'2': 'tripleo_validations.plugin'
|
||||
}
|
||||
|
||||
|
||||
# Required by the OSC plugin interface
|
||||
def build_option_parser(parser):
|
||||
"""Hook to add global options
|
||||
|
||||
Called from openstackclient.shell.OpenStackShell.__init__()
|
||||
after the builtin parser has been initialized. This is
|
||||
where a plugin can add global options such as an API version setting.
|
||||
|
||||
:param argparse.ArgumentParser parser: The parser object that has been
|
||||
initialized by OpenStackShell.
|
||||
"""
|
||||
parser.add_argument(
|
||||
'--os-tripleo-validations-api-version',
|
||||
metavar='<tripleo-validations-api-version>',
|
||||
default=utils.env(
|
||||
'OS_TRIPLEO_VALIDATIONS_API_VERSION',
|
||||
default=DEFAULT_TRIPLEO_VALIDATION_API_VERSION),
|
||||
help=("TripleO Client API version, default={}"
|
||||
" (Env: DEFAULT_TRIPLEO_VALIDATION_API_VERSION)").format(
|
||||
DEFAULT_TRIPLEO_VALIDATION_API_VERSION))
|
||||
return parser
|
@ -1,494 +0,0 @@
|
||||
# Copyright 2019 Red Hat, 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 argparse
|
||||
import json
|
||||
import logging
|
||||
import yaml
|
||||
|
||||
from openstack import exceptions as os_exceptions
|
||||
from osc_lib import exceptions
|
||||
from osc_lib.i18n import _
|
||||
from prettytable import PrettyTable
|
||||
|
||||
from osc_lib.command import command
|
||||
from tripleoclient import utils as oooutils
|
||||
from tripleoclient.workflows import deployment
|
||||
from tripleo_validations import constants
|
||||
|
||||
from validations_libs import constants as v_consts
|
||||
from validations_libs import utils as v_utils
|
||||
from validations_libs.validation_actions import ValidationActions
|
||||
from validations_libs.validation_logs import ValidationLogs
|
||||
|
||||
LOG = logging.getLogger(__name__ + ".TripleoValidator")
|
||||
|
||||
RED = "\033[1;31m"
|
||||
GREEN = "\033[0;32m"
|
||||
CYAN = "\033[36m"
|
||||
YELLOW = "\033[0;33m"
|
||||
RESET = "\033[0;0m"
|
||||
|
||||
FAILED_VALIDATION = "{}FAILED{}".format(RED, RESET)
|
||||
PASSED_VALIDATION = "{}PASSED{}".format(GREEN, RESET)
|
||||
|
||||
GROUP_FILE = constants.VALIDATION_GROUPS_INFO
|
||||
|
||||
NO_VALIDATION_STATE = ['DEPLOY_FAILED', 'DEPLOYING']
|
||||
|
||||
|
||||
class _CommaListGroupAction(argparse.Action):
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
opts = v_utils.get_validation_group_name_list(GROUP_FILE)
|
||||
for value in values.split(','):
|
||||
if value not in opts:
|
||||
message = ("Invalid choice: {value} (choose from {choice})"
|
||||
.format(value=value,
|
||||
choice=opts))
|
||||
raise argparse.ArgumentError(self, message)
|
||||
setattr(namespace, self.dest, values.split(','))
|
||||
|
||||
|
||||
class _CommaListAction(argparse.Action):
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
setattr(namespace, self.dest, values.split(','))
|
||||
|
||||
|
||||
class TripleOValidatorGroupInfo(command.Lister):
|
||||
"""Display Information about Validation Groups"""
|
||||
|
||||
auth_required = False
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(TripleOValidatorGroupInfo, self).get_parser(prog_name)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
actions = ValidationActions(constants.ANSIBLE_VALIDATION_DIR)
|
||||
return actions.group_information(GROUP_FILE)
|
||||
|
||||
|
||||
class TripleOValidatorShow(command.ShowOne):
|
||||
"""Display detailed information about a Validation"""
|
||||
|
||||
auth_required = False
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(TripleOValidatorShow, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument('validation_id',
|
||||
metavar="<validation>",
|
||||
type=str,
|
||||
help='Validation ID')
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
LOG.debug(_('Show validation result'))
|
||||
actions = ValidationActions(constants.ANSIBLE_VALIDATION_DIR)
|
||||
|
||||
try:
|
||||
data = actions.show_validations(parsed_args.validation_id)
|
||||
except Exception as e:
|
||||
raise exceptions.CommandError(e)
|
||||
|
||||
if data:
|
||||
return data.keys(), data.values()
|
||||
|
||||
|
||||
class TripleOValidatorShowParameter(command.Command):
|
||||
"""Display Validations Parameters"""
|
||||
|
||||
auth_required = False
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=self.get_description(),
|
||||
prog=prog_name,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
add_help=True
|
||||
)
|
||||
|
||||
ex_group = parser.add_mutually_exclusive_group(required=False)
|
||||
|
||||
ex_group.add_argument(
|
||||
'--validation',
|
||||
metavar='<validation_id>[,<validation_id>,...]',
|
||||
dest='validation_name',
|
||||
action=_CommaListAction,
|
||||
default=[],
|
||||
help=_("List specific validations, "
|
||||
"if more than one validation is required "
|
||||
"separate the names with commas: "
|
||||
"--validation check-ftype,512e | "
|
||||
"--validation 512e")
|
||||
)
|
||||
|
||||
ex_group.add_argument(
|
||||
'--group',
|
||||
metavar='<group_id>[,<group_id>,...]',
|
||||
action=_CommaListGroupAction,
|
||||
default=[],
|
||||
help=_("List specific group validations, "
|
||||
"if more than one group is required "
|
||||
"separate the group names with commas: "
|
||||
"pre-upgrade,prep | "
|
||||
"openshift-on-openstack")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--download',
|
||||
action='store',
|
||||
default=None,
|
||||
help=_("Create a json or a yaml file "
|
||||
"containing all the variables "
|
||||
"available for the validations: "
|
||||
"/tmp/myvars")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-f', '--format',
|
||||
action='store',
|
||||
metavar='<format>',
|
||||
default='json',
|
||||
choices=['json', 'yaml'],
|
||||
help=_("Print representation of the validation. "
|
||||
"The choices of the output format is json,yaml. ")
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
actions = ValidationActions(constants.ANSIBLE_VALIDATION_DIR)
|
||||
params = actions.show_validations_parameters(
|
||||
parsed_args.validation_name,
|
||||
parsed_args.group,
|
||||
parsed_args.format,
|
||||
parsed_args.download)
|
||||
if parsed_args.download:
|
||||
print("The file {} has been created successfully".format(
|
||||
parsed_args.download))
|
||||
else:
|
||||
print(params)
|
||||
|
||||
|
||||
class TripleOValidatorList(command.Lister):
|
||||
"""List the available validations"""
|
||||
|
||||
auth_required = False
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(TripleOValidatorList, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'--group',
|
||||
metavar='<group>[,<group>,...]',
|
||||
action=_CommaListGroupAction,
|
||||
default=[],
|
||||
help=_("List specific group validations, "
|
||||
"if more than one group is required "
|
||||
"separate the group names with commas: "
|
||||
"--group pre-upgrade,prep | "
|
||||
"--group openshift-on-openstack")
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
LOG.debug(_('Launch listing the validations'))
|
||||
try:
|
||||
v_consts.DEFAULT_VALIDATIONS_BASEDIR = constants.\
|
||||
DEFAULT_VALIDATIONS_BASEDIR
|
||||
actions = ValidationActions(constants.ANSIBLE_VALIDATION_DIR,
|
||||
parsed_args.group)
|
||||
return actions.list_validations()
|
||||
except Exception as e:
|
||||
raise RuntimeError(_("Validations listing finished with errors\n"
|
||||
"Output: {}").format(e))
|
||||
|
||||
|
||||
class TripleOValidatorRun(command.Command):
|
||||
"""Run the available validations"""
|
||||
|
||||
auth_required = False
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=self.get_description(),
|
||||
prog=prog_name,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
add_help=False
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--plan', '--stack',
|
||||
dest='plan',
|
||||
default=None,
|
||||
help=_("Execute the validations using a custom plan name")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--ssh-user',
|
||||
dest='ssh_user',
|
||||
default='heat-admin',
|
||||
help=_("Ssh User name for the Overcloud ssh connection.")
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--limit', action='store', required=False, help=_(
|
||||
"A string that identifies a single node or comma-separated"
|
||||
"list of nodes to be upgraded in parallel in this upgrade"
|
||||
" run invocation. For example: --limit \"compute-0,"
|
||||
" compute-1, compute-5\".")
|
||||
)
|
||||
extra_vars_group = parser.add_mutually_exclusive_group(required=False)
|
||||
|
||||
extra_vars_group.add_argument(
|
||||
'--extra-vars',
|
||||
action='store',
|
||||
default={},
|
||||
type=json.loads,
|
||||
help=_(
|
||||
"Add a dictionary as extra variable to a validation: "
|
||||
"--extra-vars '{\"min_undercloud_ram_gb\": 24}'")
|
||||
)
|
||||
|
||||
extra_vars_group.add_argument(
|
||||
'--extra-vars-file',
|
||||
action='store',
|
||||
default='',
|
||||
help=_(
|
||||
"Add a JSON/YAML file containing extra variable "
|
||||
"to a validation: "
|
||||
"--extra-vars-file /home/stack/vars.[json|yaml] "
|
||||
"If using Mistral, only a valid JSON file will be "
|
||||
"supported."
|
||||
)
|
||||
)
|
||||
|
||||
extra_vars_group.add_argument(
|
||||
'--extra-env-vars',
|
||||
action='store',
|
||||
default={},
|
||||
type=json.loads,
|
||||
help=_(
|
||||
"A dictionary as extra environment variables you may need "
|
||||
"to provide to your Ansible execution example:"
|
||||
"ANSIBLE_STDOUT_CALLBACK=default")
|
||||
)
|
||||
|
||||
extra_vars_group.add_argument(
|
||||
'--static-inventory',
|
||||
action='store',
|
||||
default='',
|
||||
help=_(
|
||||
"Provide your own static inventory file. You can generate "
|
||||
"such an inventory calling tripleo-ansible-inventory command. "
|
||||
"Especially useful when heat service isn't available."
|
||||
)
|
||||
)
|
||||
|
||||
ex_group = parser.add_mutually_exclusive_group(required=True)
|
||||
|
||||
ex_group.add_argument(
|
||||
'--validation',
|
||||
metavar='<validation_id>[,<validation_id>,...]',
|
||||
dest="validation_name",
|
||||
action=_CommaListAction,
|
||||
default=[],
|
||||
help=_("Run specific validations, "
|
||||
"if more than one validation is required "
|
||||
"separate the names with commas: "
|
||||
"--validation check-ftype,512e | "
|
||||
"--validation 512e")
|
||||
)
|
||||
|
||||
ex_group.add_argument(
|
||||
'--group',
|
||||
metavar='<group>[,<group>,...]',
|
||||
action=_CommaListGroupAction,
|
||||
default=[],
|
||||
help=_("Run specific group validations, "
|
||||
"if more than one group is required "
|
||||
"separate the group names with commas: "
|
||||
"--group pre-upgrade,prep | "
|
||||
"--group openshift-on-openstack")
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def _run_validator_run(self, parsed_args):
|
||||
LOG = logging.getLogger(__name__ + ".ValidationsRunAnsible")
|
||||
|
||||
plan = parsed_args.plan
|
||||
# Try to perform OpenStack authentication, if no authentication
|
||||
# and static inventory provided continue, else raise error.
|
||||
try:
|
||||
clients = self.app.client_manager
|
||||
clients._auth_required = True
|
||||
clients.setup_auth()
|
||||
except os_exceptions.ConfigException:
|
||||
msg = "Running Validations without authentication."
|
||||
LOG.warning("{}{}{}".format(YELLOW, msg, RESET))
|
||||
if not parsed_args.static_inventory:
|
||||
raise exceptions.CommandError(
|
||||
_("No static inventory provided, please provide a valid "
|
||||
"inventory or use authentication."))
|
||||
else:
|
||||
if plan:
|
||||
status = deployment.get_deployment_status(clients, plan)
|
||||
if not status or status in NO_VALIDATION_STATE:
|
||||
raise exceptions.CommandError(
|
||||
_("The plan and the stack '{}' doesn't exist OR are "
|
||||
"in 'failed' or 'deploying' state. "
|
||||
"Please use a valid plan".format(plan)))
|
||||
else:
|
||||
msg = "Running Validations without Overcloud settings."
|
||||
LOG.warning("{}{}{}".format(YELLOW, msg, RESET))
|
||||
limit = parsed_args.limit
|
||||
extra_vars = parsed_args.extra_vars
|
||||
if parsed_args.extra_vars_file:
|
||||
try:
|
||||
with open(parsed_args.extra_vars_file, 'r') as env_file:
|
||||
extra_vars.update(yaml.safe_load(env_file.read()))
|
||||
except yaml.YAMLError as e:
|
||||
error_msg = (
|
||||
"The request body must be properly formatted YAML/JSON. "
|
||||
"Details: %s." % e)
|
||||
raise exceptions.CommandError(error_msg)
|
||||
|
||||
# We don't check if the file exists in order to support
|
||||
# passing a string such as "localhost,", like we can do with
|
||||
# the "-i" option of ansible-playbook.
|
||||
if parsed_args.static_inventory:
|
||||
static_inventory = parsed_args.static_inventory
|
||||
else:
|
||||
static_inventory = oooutils.get_tripleo_ansible_inventory(
|
||||
ssh_user=parsed_args.ssh_user,
|
||||
stack=parsed_args.plan,
|
||||
undercloud_connection='local',
|
||||
return_inventory_file_path=True)
|
||||
|
||||
v_consts.DEFAULT_VALIDATIONS_BASEDIR = constants.\
|
||||
DEFAULT_VALIDATIONS_BASEDIR
|
||||
actions = ValidationActions()
|
||||
try:
|
||||
results = actions.run_validations(
|
||||
inventory=static_inventory,
|
||||
limit_hosts=limit,
|
||||
group=parsed_args.group,
|
||||
extra_vars=extra_vars,
|
||||
validations_dir=constants.ANSIBLE_VALIDATION_DIR,
|
||||
validation_name=parsed_args.validation_name,
|
||||
extra_env_vars=parsed_args.extra_env_vars,
|
||||
quiet=True)
|
||||
except RuntimeError as e:
|
||||
raise exceptions.CommandError(e)
|
||||
|
||||
if results:
|
||||
# Build output
|
||||
t = PrettyTable(border=True, header=True, padding_width=1)
|
||||
# Set Field name by getting the result dict keys
|
||||
t.field_names = results[0].keys()
|
||||
for r in results:
|
||||
if r.get('Status_by_Host'):
|
||||
h = []
|
||||
for host in r['Status_by_Host'].split(', '):
|
||||
_name, _status = host.split(',')
|
||||
color = (GREEN if _status == 'PASSED' else RED)
|
||||
_name = '{}{}{}'.format(color, _name, RESET)
|
||||
h.append(_name)
|
||||
r['Status_by_Host'] = ', '.join(h)
|
||||
if r.get('status'):
|
||||
status = r.get('status')
|
||||
color = (CYAN if status in ['starting', 'running']
|
||||
else GREEN if status == 'PASSED' else RED)
|
||||
r['status'] = '{}{}{}'.format(color, status, RESET)
|
||||
t.add_row(r.values())
|
||||
print(t)
|
||||
else:
|
||||
msg = "No Validation has been run, please check your parameters."
|
||||
LOG.info(_(msg))
|
||||
|
||||
if not parsed_args.static_inventory:
|
||||
LOG.debug(_('Removing static tripleo ansible inventory file'))
|
||||
oooutils.cleanup_tripleo_ansible_inventory_file(
|
||||
static_inventory)
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self._run_validator_run(parsed_args)
|
||||
|
||||
|
||||
class TripleOValidatorShowRun(command.Command):
|
||||
"""Display details about a Validation execution"""
|
||||
|
||||
auth_required = False
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=self.get_description(),
|
||||
prog=prog_name,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
add_help=False
|
||||
)
|
||||
|
||||
parser.add_argument('uuid',
|
||||
metavar="<uuid>",
|
||||
type=str,
|
||||
help='Validation UUID Run')
|
||||
|
||||
parser.add_argument('--full',
|
||||
action='store_true',
|
||||
help='Show Full Details for the run')
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
vlogs = ValidationLogs()
|
||||
data = vlogs.get_logfile_content_by_uuid(parsed_args.uuid)
|
||||
if data:
|
||||
if parsed_args.full:
|
||||
for d in data:
|
||||
print(json.dumps(d, indent=4, sort_keys=True))
|
||||
else:
|
||||
for d in data:
|
||||
for p in d.get('validation_output', []):
|
||||
print(json.dumps(p['task'],
|
||||
indent=4,
|
||||
sort_keys=True))
|
||||
else:
|
||||
raise exceptions.CommandError(
|
||||
"Could not find the log file linked to this UUID: %s" %
|
||||
parsed_args.uuid)
|
||||
|
||||
|
||||
class TripleOValidatorShowHistory(command.Lister):
|
||||
"""Display Validations execution history"""
|
||||
|
||||
auth_required = False
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(TripleOValidatorShowHistory, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument('--validation',
|
||||
metavar="<validation>",
|
||||
type=str,
|
||||
help='Display execution history for a validation')
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
actions = ValidationActions(constants.ANSIBLE_VALIDATION_DIR)
|
||||
return actions.show_history(parsed_args.validation)
|
Loading…
x
Reference in New Issue
Block a user