"""
Avocado VT plugin
"""
import copy
import logging
import os
from avocado.core import loader
from avocado.core import output
from virttest import cartesian_config
from virttest import data_dir
from virttest import standalone_test
from virttest import storage
from virttest.compat import get_opt, set_opt
from .options import VirtTestOptionsProcess
from .test import VirtTest
LOG = logging.getLogger("avocado.app")
def guest_listing(config, guest_name_parser=None):
"""
List available guest operating systems and info about image availability
"""
if get_opt(config, 'vt.type') == 'lvsb':
raise ValueError("No guest types available for lvsb testing")
LOG.debug("Using %s for guest images\n",
os.path.join(data_dir.get_data_dir(), 'images'))
LOG.info("Available guests in config:")
if guest_name_parser is None:
guest_name_parser = standalone_test.get_guest_name_parser(config)
for params in guest_name_parser.get_dicts():
base_dir = params.get("images_base_dir", data_dir.get_data_dir())
image_name = storage.get_image_filename(params, base_dir)
machine_type = get_opt(config, 'vt.common.machine_type')
name = params['name'].replace('.%s' % machine_type, '')
if os.path.isfile(image_name):
out = name
else:
missing = "(missing %s)" % os.path.basename(image_name)
out = (name + " " + output.TERM_SUPPORT.warn_header_str(missing))
LOG.debug(out)
LOG.debug("")
def arch_listing(config, guest_name_parser=None):
"""
List available machine/archs for given guest operating systems
"""
guest_os = get_opt(config, 'vt.guest_os')
if guest_os is not None:
extra = " for guest os \"%s\"" % guest_os
else:
extra = ""
LOG.info("Available arch profiles%s", extra)
if guest_name_parser is None:
guest_name_parser = standalone_test.get_guest_name_parser(config)
machine_type = get_opt(config, 'vt.common.machine_type')
for params in guest_name_parser.get_dicts():
LOG.debug(params['name'].replace('.%s' % machine_type, ''))
LOG.debug("")
class NotAvocadoVTTest(object):
"""
Not an Avocado-vt test (for reporting purposes)
"""
class VirtTestLoader(loader.TestLoader):
"""
Avocado loader plugin to load avocado-vt tests
"""
name = 'vt'
def __init__(self, config, extra_params):
"""
Following extra_params are supported:
* avocado_vt_extra_params: Will override the "vt_extra_params"
of this plugins "self.config" (extends the --vt-extra-params)
"""
vt_extra_params = extra_params.pop("avocado_vt_extra_params", None)
super(VirtTestLoader, self).__init__(config, extra_params)
if hasattr(self, 'config'):
self.args = self.config
else:
self.config = self.args
if vt_extra_params:
self.config = copy.deepcopy(self.config)
extra = get_opt(self.config, 'vt.extra_params')
if extra is not None:
extra += vt_extra_params
else:
extra = vt_extra_params
set_opt(self.config, 'vt.extra_params', extra)
def _get_parser(self):
options_processor = VirtTestOptionsProcess(self.config)
return options_processor.get_parser()
def _save_parser_cartesian_config(self, parser):
path = get_opt(self.config, 'vt.save_config')
if path is None:
return
with open(path, 'w') as cartesian_config:
cartesian_config.write("include %s\n" % parser.filename)
for statement in (parser.only_filters + parser.no_filters +
parser.assignments):
cartesian_config.write("%s\n" % statement)
def get_extra_listing(self):
if get_opt(self.config, 'vt.list_guests'):
config = copy.copy(self.config)
set_opt(config, 'vt.config', None)
set_opt(config, 'vt.guest_os', None)
guest_listing(config)
if get_opt(self.config, 'vt.list_archs'):
config = copy.copy(self.config)
set_opt(config, 'vt.common.machine_type', None)
set_opt(config, 'vt.common.arch', None)
arch_listing(config)
@staticmethod
def get_type_label_mapping():
"""
Get label mapping for display in test listing.
:returns: a dictionary with the test class as key and description
as value.
"""
return {VirtTest: 'VT', NotAvocadoVTTest: "!VT"}
@staticmethod
def get_decorator_mapping():
"""
Get label mapping for display in test listing.
:return: a dictionary with the test class as key and decorator
function as value.
"""
term_support = output.TermSupport()
return {VirtTest: term_support.healthy_str,
NotAvocadoVTTest: term_support.fail_header_str}
@staticmethod
def _report_bad_discovery(name, reason, which_tests):
if which_tests is loader.DiscoverMode.ALL:
return [(NotAvocadoVTTest, {"name": "%s: %s" % (name, reason)})]
else:
return []
def discover(self, url, which_tests=loader.DiscoverMode.DEFAULT):
try:
cartesian_parser = self._get_parser()
self._save_parser_cartesian_config(cartesian_parser)
except Exception as details:
return self._report_bad_discovery(url, details, which_tests)
if url is not None:
try:
cartesian_parser.only_filter(url)
except cartesian_config.ParserError as details:
return self._report_bad_discovery(url, details, which_tests)
elif (which_tests is loader.DiscoverMode.DEFAULT and
not get_opt(self.config, 'vt.config')):
return []
test_suite = []
for params in (_ for _ in cartesian_parser.get_dicts()):
test_name = None
if (get_opt(self.config, 'vt.config')
and get_opt(self.config, 'vt.short_names_when_config')):
test_name = params.get("shortname")
elif get_opt(self.config, 'vt.type') == "spice":
short_name_map_file = params.get("_short_name_map_file")
if "tests-variants.cfg" in short_name_map_file:
test_name = short_name_map_file["tests-variants.cfg"]
if test_name is None:
test_name = params.get("_short_name_map_file")["subtests.cfg"]
params['id'] = test_name
test_parameters = {'name': test_name,
'vt_params': params}
test_suite.append((VirtTest, test_parameters))
if which_tests is loader.DiscoverMode.ALL and not test_suite:
return self._report_bad_discovery(url, "No matching tests",
which_tests)
return test_suite