Run Rally 3.0.0

Co-Authored-By: Cédric Ollivier <ollivier.cedric@gmail.com>

Change-Id: Ibc652d95ef9fe862e6b67a55e9b22fb5333825dc
This commit is contained in:
Andrey Kurilin 2020-03-23 17:44:20 +02:00
parent 6302212b42
commit 83eae7f02a
27 changed files with 98 additions and 186 deletions

View File

@ -26,6 +26,12 @@ Changed
switched to use `docker image <https://hub.docker.com/r/xrally/xrally>`_ as
a base user that brings use python 3.6 and ubuntu bionic.
* Bump min supported Rally framework version (rally>=3.0.0)
Removed
~~~~~~~
* Support for Python < 3.6
[1.7.0] - 2020-12-25
--------------------

View File

@ -18,18 +18,6 @@ from rally.common import version as __rally_version__
__rally_version__ = __rally_version__.version_info.semantic_version()
__rally_version__ = __rally_version__.version_tuple()
if __rally_version__ < (0, 12):
# NOTE(andreykurilin): Rally < 0.12 doesn't care about loading options from
# external packages, so we need to handle it manually.
from rally.common import opts as global_opts
from rally_openstack.cfg import opts
# ensure that rally options are registered.
global_opts.register()
global_opts.register_opts(opts.list_opts())
__version_info__ = pbr.version.VersionInfo("rally-openstack")
__version__ = __version_info__.version_string()
__version_tuple__ = __version_info__.semantic_version().version_tuple()

View File

@ -16,7 +16,6 @@
import os
import zipfile
from rally.common import fileutils
from rally.common import utils
from rally.common import validation
from rally import exceptions
@ -25,6 +24,7 @@ from rally.task import context
from rally_openstack.cleanup import manager as resource_manager
from rally_openstack import consts
from rally_openstack import osclients
from rally_openstack.scenarios.murano import utils as mutils
@validation.add("required_platform", platform="openstack", users=True)
@ -51,7 +51,7 @@ class PackageGenerator(context.Context):
zip_name = pckg_path
elif os.path.isdir(pckg_path):
is_config_app_dir = True
zip_name = fileutils.pack_dir(pckg_path)
zip_name = mutils.pack_dir(pckg_path)
else:
msg = "There is no zip archive or directory by this path: %s"
raise exceptions.ContextSetupFailure(msg=msg % pckg_path,

View File

@ -21,19 +21,6 @@ from rally.common import opts
from rally.common.plugin import plugin
from rally.task.processing import charts
import rally_openstack
if rally_openstack.__rally_version__ < (1, 5, 0):
# NOTE(andreykurilin): this is a workaround to make inheritance of
# OSProfilerChart clear.
OutputEmbeddedChart = type("OutputEmbeddedChart", (object, ), {})
OutputEmbeddedExternalChart = type("OutputEmbeddedExternalChart",
(object, ), {})
else:
OutputEmbeddedChart = charts.OutputEmbeddedChart
OutputEmbeddedExternalChart = charts.OutputEmbeddedExternalChart
OPTS = {
"openstack": [
@ -61,8 +48,8 @@ def _datetime_json_serialize(obj):
@plugin.configure(name="OSProfiler")
class OSProfilerChart(OutputEmbeddedChart,
OutputEmbeddedExternalChart,
class OSProfilerChart(charts.OutputEmbeddedChart,
charts.OutputEmbeddedExternalChart,
charts.OutputTextArea):
"""Chart for embedding OSProfiler data."""
@ -130,13 +117,7 @@ class OSProfilerChart(OutputEmbeddedChart,
title = "{0} : {1}".format(data["title"],
data["data"]["trace_id"])
if rally_openstack.__rally_version__ < (1, 5, 0):
return {
"title": title,
"widget": "EmbeddedChart",
"data": osp_report.replace("/script>", "\\/script>")
}
elif (mode and mode != "raw") and "workload_uuid" in data["data"]:
if (mode and mode != "raw") and "workload_uuid" in data["data"]:
# NOTE(andreykurilin): we need to rework our charts plugin
# mechanism so it is available out of box
workload_uuid = data["data"]["workload_uuid"]
@ -145,7 +126,7 @@ class OSProfilerChart(OutputEmbeddedChart,
path = os.path.join(mode, file_name)
with open(path, "w") as f:
f.write(osp_report)
return OutputEmbeddedExternalChart.render_complete_data(
return charts.OutputEmbeddedExternalChart.render_complete_data(
{
"title": title,
"widget": "EmbeddedChart",
@ -153,7 +134,7 @@ class OSProfilerChart(OutputEmbeddedChart,
}
)
else:
return OutputEmbeddedChart.render_complete_data(
return charts.OutputEmbeddedChart.render_complete_data(
{"title": title,
"widget": "EmbeddedChart",
"data": osp_report}

View File

@ -168,7 +168,8 @@ class OSClient(plugin.Plugin):
float(version)
except ValueError:
raise exceptions.ValidationError(
"'%s' is invalid. Should be numeric value." % version)
"'%s' is invalid. Should be numeric value." % version
) from None
def choose_service_type(self, service_type=None):
"""Return service_type string.
@ -286,7 +287,7 @@ class Keystone(OSClient):
{"username": self.credential.username,
"tenant_name": self.credential.tenant_name})
raise e
raise e from None
return self.cache["keystone_auth_ref"]
def get_session(self, version=None):
@ -409,7 +410,7 @@ class Nova(OSClient):
api_versions.get_api_version(version)
except nova_exc.UnsupportedVersion:
raise exceptions.RallyException(
"Version string '%s' is unsupported." % version)
"Version string '%s' is unsupported." % version) from None
def create_client(self, version=None, service_type=None):
"""Return nova client."""
@ -541,7 +542,7 @@ class Manila(OSClient):
api_versions.get_api_version(version)
except manila_exc.UnsupportedVersion:
raise exceptions.RallyException(
"Version string '%s' is unsupported." % version)
"Version string '%s' is unsupported." % version) from None
def create_client(self, version=None, service_type=None):
"""Return manila client."""
@ -879,7 +880,7 @@ class Clients(object):
spec = existing.OpenStack.create_spec_from_sys_environ(os.environ)
if not spec["available"]:
raise ValueError(spec["message"])
raise ValueError(spec["message"]) from None
creds = spec["spec"]
oscred = credential.OpenStackCredential(

View File

@ -184,11 +184,8 @@ class OpenStack(platform.Platform):
except osclients.exceptions.RallyException as e:
# all rally native exceptions should provide user-friendly
# messages
return {"available": False, "message": e.format_message(),
# traceback is redundant here. Remove as soon as min
# required rally version will be updated
# More details here:
# https://review.openstack.org/597197
return {"available": False,
"message": e.format_message(),
"traceback": traceback.format_exc()}
except Exception:
d = copy.deepcopy(user)

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from rally.plugins.common.scenarios.dummy import dummy
from rally.plugins.task.scenarios.dummy import dummy
from rally_openstack import scenario

View File

@ -12,9 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from rally.task import validation
import yaml
from rally.task import validation
from rally_openstack import consts
from rally_openstack import scenario
from rally_openstack.scenarios.magnum import utils
@ -48,7 +49,7 @@ class CreatePods(utils.MagnumScenario):
for manifest in manifests:
with open(manifest, "r") as f:
manifest_str = f.read()
manifest = yaml.load(manifest_str)
manifest = yaml.safe_load(manifest_str)
pod = self._create_v1pod(manifest)
msg = ("Pod isn't created")
self.assertTrue(pod, err_msg=msg)
@ -67,7 +68,7 @@ class CreateRcs(utils.MagnumScenario):
for manifest in manifests:
with open(manifest, "r") as f:
manifest_str = f.read()
manifest = yaml.load(manifest_str)
manifest = yaml.safe_load(manifest_str)
rc = self._create_v1rc(manifest)
msg = ("RC isn't created")
self.assertTrue(rc, err_msg=msg)

View File

@ -20,7 +20,6 @@ import uuid
import zipfile
from rally.common import cfg
from rally.common import fileutils
from rally.common import utils as common_utils
from rally.task import atomic
from rally.task import utils
@ -32,6 +31,37 @@ from rally_openstack import scenario
CONF = cfg.CONF
def pack_dir(source_directory, zip_name=None):
"""Archive content of the directory into .zip
Zip content of the source folder excluding root directory
into zip archive. When zip_name is specified, it would be used
as a destination for the archive. Otherwise method would
try to use temporary file as a destination for the archive.
:param source_directory: root of the newly created archive.
Directory is added recursively.
:param zip_name: destination zip file name.
:raises IOError: whenever there are IO issues.
:returns: path to the newly created zip archive either specified via
zip_name or a temporary one.
"""
if not zip_name:
fp = tempfile.NamedTemporaryFile(delete=False)
zip_name = fp.name
zipf = zipfile.ZipFile(zip_name, mode="w")
try:
for root, dirs, files in os.walk(source_directory):
for f in files:
abspath = os.path.join(root, f)
relpath = os.path.relpath(abspath, source_directory)
zipf.write(abspath, relpath)
finally:
zipf.close()
return zip_name
class MuranoScenario(scenario.OpenStackScenario):
"""Base class for Murano scenarios with basic atomic actions."""
@ -253,7 +283,7 @@ class MuranoPackageManager(common_utils.RandomNameGeneratorMixin):
shutil.copytree(os.path.expanduser(package_path), pkg_dir)
self._change_app_fullname(pkg_dir)
package_path = fileutils.pack_dir(pkg_dir)
package_path = pack_dir(pkg_dir)
finally:
shutil.rmtree(tmp_dir)

View File

@ -523,8 +523,8 @@ class CreateAndDeletePorts(utils.NeutronScenario):
@validation.add("required_platform", platform="openstack",
users=True, admin=True)
@scenario.configure(context={"cleanup@openstack": ["neutron"],
"networking_agents": {},
"network": {}},
"networking_agents@openstack": {},
"network@openstack": {}},
name="NeutronNetworks.create_and_bind_ports",
platform="openstack")
class CreateAndBindPorts(utils.NeutronScenario):

View File

@ -22,9 +22,9 @@ import netaddr
from rally.common import cfg
from rally.common import logging
from rally.common import sshutils
from rally.task import atomic
from rally.task import utils
from rally.utils import sshutils
from rally_openstack.scenarios.nova import utils as nova_utils
from rally_openstack.wrappers import network as network_wrapper

View File

@ -18,12 +18,12 @@ import os
import pkgutil
from rally.common import logging
from rally.common import sshutils
from rally.common import validation
from rally import exceptions
from rally.plugins.common import validators
from rally.task import atomic
from rally.task import types
from rally.utils import sshutils
from rally_openstack import consts
from rally_openstack import scenario

View File

@ -15,14 +15,12 @@
import copy
import operator
import re
import traceback
from rally.common import logging
from rally.common.plugin import plugin
from rally import exceptions
from rally.task import types
import rally_openstack
from rally_openstack import osclients
from rally_openstack.services.image import image
from rally_openstack.services.storage import block
@ -38,14 +36,7 @@ class OpenStackResourceType(types.ResourceType):
"""A base class for OpenStack ResourceTypes plugins with help-methods"""
def __init__(self, context=None, cache=None):
if rally_openstack.__rally_version__ >= (0, 12):
super(OpenStackResourceType, self).__init__(context, cache)
else:
super(OpenStackResourceType, self).__init__()
self._context = context or {}
self._global_cache = cache or {}
self._global_cache.setdefault(self.get_name(), {})
self._cache = self._global_cache[self.get_name()]
super(OpenStackResourceType, self).__init__(context, cache)
self._clients = None
if self._context.get("admin"):
@ -130,34 +121,9 @@ class OpenStackResourceType(types.ResourceType):
matching))})
return matching[0]
if rally_openstack.__rally_version__ < (0, 12):
@classmethod
def _get_doc(cls):
return cls.__doc__
class DeprecatedBehaviourMixin(object):
"""A Mixin class which returns deprecated `transform` method."""
@classmethod
def transform(cls, clients, resource_config):
caller = traceback.format_stack(limit=2)[0]
if rally_openstack.__rally_version__ >= (0, 12):
# The new interface of ResourceClass is introduced with Rally 0.12
LOG.warning("Calling method `transform` of %s is deprecated:\n%s"
% (cls.__name__, caller))
if clients:
# it doesn't matter "permission" of the user. it will pick the
# first one
context = {"admin": {"credential": clients.credential}}
else:
context = {}
self = cls(context, cache={})
return self.pre_process(resource_spec=resource_config, config={})
@plugin.configure(name="nova_flavor")
class Flavor(DeprecatedBehaviourMixin, OpenStackResourceType):
class Flavor(OpenStackResourceType):
"""Find Nova's flavor ID by name or regexp."""
def pre_process(self, resource_spec, config):
@ -172,7 +138,7 @@ class Flavor(DeprecatedBehaviourMixin, OpenStackResourceType):
@plugin.configure(name="glance_image")
class GlanceImage(DeprecatedBehaviourMixin, OpenStackResourceType):
class GlanceImage(OpenStackResourceType):
"""Find Glance's image ID by name or regexp."""
def pre_process(self, resource_spec, config):
@ -191,7 +157,7 @@ class GlanceImage(DeprecatedBehaviourMixin, OpenStackResourceType):
@plugin.configure(name="glance_image_args")
class GlanceImageArguments(DeprecatedBehaviourMixin, OpenStackResourceType):
class GlanceImageArguments(OpenStackResourceType):
"""Process Glance image create options to look similar in case of V1/V2."""
def pre_process(self, resource_spec, config):
resource_spec = copy.deepcopy(resource_spec)
@ -206,7 +172,7 @@ class GlanceImageArguments(DeprecatedBehaviourMixin, OpenStackResourceType):
@plugin.configure(name="ec2_image")
class EC2Image(DeprecatedBehaviourMixin, OpenStackResourceType):
class EC2Image(OpenStackResourceType):
"""Find EC2 image ID."""
def pre_process(self, resource_spec, config):
@ -229,7 +195,7 @@ class EC2Image(DeprecatedBehaviourMixin, OpenStackResourceType):
@plugin.configure(name="cinder_volume_type")
class VolumeType(DeprecatedBehaviourMixin, OpenStackResourceType):
class VolumeType(OpenStackResourceType):
"""Find Cinder volume type ID by name or regexp."""
def pre_process(self, resource_spec, config):
@ -244,7 +210,7 @@ class VolumeType(DeprecatedBehaviourMixin, OpenStackResourceType):
@plugin.configure(name="neutron_network")
class NeutronNetwork(DeprecatedBehaviourMixin, OpenStackResourceType):
class NeutronNetwork(OpenStackResourceType):
"""Find Neutron network ID by it's name."""
def pre_process(self, resource_spec, config):
resource_id = resource_spec.get("id")
@ -262,7 +228,7 @@ class NeutronNetwork(DeprecatedBehaviourMixin, OpenStackResourceType):
@plugin.configure(name="watcher_strategy")
class WatcherStrategy(DeprecatedBehaviourMixin, OpenStackResourceType):
class WatcherStrategy(OpenStackResourceType):
"""Find Watcher strategy ID by it's name."""
def pre_process(self, resource_spec, config):
@ -279,7 +245,7 @@ class WatcherStrategy(DeprecatedBehaviourMixin, OpenStackResourceType):
@plugin.configure(name="watcher_goal")
class WatcherGoal(DeprecatedBehaviourMixin, OpenStackResourceType):
class WatcherGoal(OpenStackResourceType):
"""Find Watcher goal ID by it's name."""
def pre_process(self, resource_spec, config):

View File

@ -17,14 +17,14 @@ import inspect
import os
import re
import yaml
from rally.common import logging
from rally.common import validation
from rally.common import yamlutils as yaml
from rally import exceptions
from rally.plugins.common import validators
from rally.task import types
import rally_openstack
from rally_openstack import consts
from rally_openstack.contexts.keystone import roles
from rally_openstack.contexts.nova import flavors as flavors_ctx
@ -34,6 +34,7 @@ from rally_openstack import types as openstack_types
LOG = logging.getLogger(__name__)
@validation.configure("required_platform", platform="openstack")
class RequiredOpenStackValidator(validation.RequiredPlatformValidator):
def __init__(self, admin=False, users=False):
"""Validates credentials for OpenStack platform.
@ -69,11 +70,6 @@ class RequiredOpenStackValidator(validation.RequiredPlatformValidator):
pass
if rally_openstack.__rally_version__ >= (0, 13):
RequiredOpenStackValidator = validation.configure(
"required_platform", platform="openstack")(RequiredOpenStackValidator)
def with_roles_ctx():
"""Add roles to users for validate

View File

@ -17,9 +17,10 @@ import re
import shutil
import subprocess
from rally.common import yamlutils as yaml
import yaml
from rally import exceptions
from rally.plugins.common.verification import testr
from rally.plugins.verification import testr
from rally.verification import manager
from rally.verification import utils

View File

@ -3,7 +3,7 @@
requests!=2.20.0 # Apache License, Version 2.0
rally>=0.11.0 # Apache License, Version 2.0
rally>=3.0.0 # Apache License, Version 2.0
# OpenStack related
gnocchiclient # Apache Software License

View File

@ -22,8 +22,8 @@ import traceback
import unittest
from rally import api
from rally.cli import yamlutils as yaml
from rally.common import broker
from rally.common import yamlutils as yaml
from rally import plugins
import rally_openstack as rally_openstack_module
from tests.functional import utils

View File

@ -82,8 +82,8 @@ class OSProfilerChartTestCase(test.TestCase):
connection_str, trace_id)
self.assertIsNone(r)
@mock.patch("%s.OutputEmbeddedExternalChart" % PATH)
@mock.patch("%s.OutputEmbeddedChart" % PATH)
@mock.patch("%s.charts.OutputEmbeddedExternalChart" % PATH)
@mock.patch("%s.charts.OutputEmbeddedChart" % PATH)
@mock.patch("%s._return_raw_response_for_complete_data" % CHART_PATH)
@mock.patch("%s._fetch_osprofiler_data" % CHART_PATH)
@mock.patch("%s._generate_osprofiler_report" % CHART_PATH)
@ -178,26 +178,3 @@ class OSProfilerChartTestCase(test.TestCase):
"widget": "EmbeddedChart",
"data": "/path/w_W_ID-777.html"})
self.assertFalse(mock__return_raw_response_for_complete_data.called)
# case 6: rally < 1.5.0
pdata = {"data": {"trace_id": trace_id,
"conn_str": "conn",
"workload_uuid": "W_ID",
"iteration": 777},
"title": title}
mock_rally_os = mock.Mock()
mock_rally_os.__rally_version__ = (1, 4, 0)
with mock.patch.object(osp_chart, "rally_openstack") as m:
m.__rally_version__ = (1, 4, 0)
with mock.patch("%s.CONF.openstack" % PATH) as mock_cfg_os:
mock_cfg_os.osprofiler_chart_mode = "/path"
r = osp_chart.OSProfilerChart.render_complete_data(
copy.deepcopy(pdata))
self.assertEqual({
"title": "%s : %s" % (title, trace_id),
"widget": "EmbeddedChart",
"data": "DD"
}, r)

View File

@ -296,9 +296,13 @@ class ExistingPlatformTestCase(PlatformBaseTestCase):
"users": [{"username": "balbab", "password": "12345"}]}
result = existing.OpenStack({}, platform_data=pdata).check_health()
self._check_health_schema(result)
self.assertEqual({"available": False, "message": e.format_message(),
"traceback": mock.ANY},
result)
self.assertEqual(
{
"available": False,
"message": e.format_message(),
"traceback": mock.ANY
},
result)
@mock.patch("rally_openstack.osclients.Clients")
def test_check_failed_admin(self, mock_clients):

View File

@ -19,8 +19,8 @@ import traceback
from unittest import mock
from rally import api
from rally.cli import yamlutils as yaml
from rally.common.plugin import discover
from rally.common import yamlutils as yaml
from rally.task import engine
from rally.task import task_cfg

View File

@ -14,7 +14,7 @@
import os
from rally.common import yamlutils as yaml
import yaml
import rally_openstack
from tests.unit import test

View File

@ -132,7 +132,7 @@ class MuranoScenarioTestCase(test.ScenarioTestCase):
@mock.patch("tempfile.mkdtemp")
@mock.patch("shutil.copytree")
@mock.patch(MRN_UTILS + ".MuranoPackageManager._change_app_fullname")
@mock.patch("rally.common.fileutils.pack_dir")
@mock.patch("%s.pack_dir" % MRN_UTILS)
@mock.patch("shutil.rmtree")
def test_prepare_zip_if_not_zip(
self, mock_shutil_rmtree, mock_pack_dir,

View File

@ -113,7 +113,7 @@ class VMScenarioTestCase(test.ScenarioTestCase):
check_interval=CONF.openstack.vm_ping_poll_interval)
@mock.patch(VMTASKS_UTILS + ".VMScenario._run_command_over_ssh")
@mock.patch("rally.common.sshutils.SSH")
@mock.patch("rally.utils.sshutils.SSH")
def test__run_command(self, mock_sshutils_ssh,
mock_vm_scenario__run_command_over_ssh):
vm_scenario = utils.VMScenario(self.context)

View File

@ -989,7 +989,7 @@ class VolumeTypeExistsValidatorTestCase(test.TestCase):
@ddt.ddt
class WorkbookContainsWorkflowValidatorTestCase(test.TestCase):
@mock.patch("rally.common.yamlutils.safe_load")
@mock.patch("%s.yaml.safe_load" % PATH)
@mock.patch("%s.os.access" % PATH)
@mock.patch("%s.open" % PATH)
def test_validator(self, mock_open, mock_access, mock_safe_load):

View File

@ -26,30 +26,8 @@ from tests.unit import test
class WorkaroundTestCase(test.TestCase):
WORKAROUNDS = [
([0, 12], [
"'rally_openstack.__init__' module contains a hack for loading "
"configuration options.",
"'rally_openstack.types' module contains a compatibility layer for"
" an old interface of ResourceTypes."]
),
([0, 13], [
"'rally_openstack.validators' module has a check to do not "
"register 'required_platforms@openstack' validator for old Rally "
"releases."
]),
([1, 2], [
"'existing@openstack' platform puts 'traceback' in check method "
"in case of native keystone errors. It is redundant. "
"See https://review.opendev.org/597197"
]),
([1, 5], [
"New chart classes exist anyway at Rally side, so no need for "
"backward compatibility layer at rally_openstack.embecharts. "
"See https://review.opendev.org/#/c/653500/"
])
]
WORKAROUNDS = []
def get_min_required_version(self):
package = pkg_resources.get_distribution("rally-openstack")
@ -62,8 +40,8 @@ class WorkaroundTestCase(test.TestCase):
elif statement == ">":
version[-1] += 1
return version
self.skip("Failed to get a minimum required version of Rally "
"framework.")
self.skipTest("Failed to get a minimum required version of Rally "
"framework.")
def test_rally_version(self):
rally_version = self.get_min_required_version()

16
tox.ini
View File

@ -91,18 +91,4 @@ commands = bindep
commands = {toxinidir}/tests/ci/rally_self_job.sh {toxinidir}/rally-jobs/self-rally.yaml
[pytest]
filterwarnings =
error
ignore:.*EngineFacade is deprecated; please use oslo_db.sqlalchemy.enginefacade*:
# instead of ignoring all modules, let's list only libraries that are failing
ignore:invalid escape sequence:DeprecationWarning:.*netaddr.*
ignore:invalid escape sequence:DeprecationWarning:.*prettytable
ignore:invalid escape sequence:DeprecationWarning:.*subunit.*
ignore:invalid escape sequence:DeprecationWarning:.*testtools.*
# new to rally-openstack
ignore:::.*rally.*
ignore:Using or importing the ABCs:DeprecationWarning:.*oslo_context.*
# python 3.7
ignore:Using or importing the ABCs:DeprecationWarning:unittest2.*
# python 3.8
ignore:::.*netaddr.strategy.*
addopts = -p no:warnings

View File

@ -102,7 +102,7 @@ python-watcherclient===2.5.0
python-zaqarclient===1.13.0
pytz===2019.3
PyYAML===5.3.1
rally===2.1.0
rally===3.0.0
requests===2.23.0
requests-oauthlib===1.3.0
requestsexceptions===1.4.0