From 57614a0d7e7815ce0b77a6b5e4ec97c3635d51f9 Mon Sep 17 00:00:00 2001 From: Andrey Kurilin Date: Mon, 17 Aug 2020 17:47:30 +0300 Subject: [PATCH] Extend api_info section of env spec with pre_mitaka neutron cfg Change-Id: I9cf673fc63cc4e1f14bfc8def034e7b2b28c2918 --- CHANGELOG.rst | 39 +++++++- etc/rally/rally.conf.sample | 97 +++++++++++++------ rally_openstack/common/cfg/neutron.py | 2 +- .../common/services/network/neutron.py | 6 +- .../environment/platforms/existing.py | 20 +++- .../common/services/network/test_neutron.py | 27 +++++- .../task/scenarios/neutron/test_network.py | 1 + .../unit/task/scenarios/neutron/test_utils.py | 10 +- .../unit/task/scenarios/nova/test_servers.py | 4 +- tests/unit/task/scenarios/vm/test_utils.py | 4 +- 10 files changed, 167 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9ad56c0d..2f7120af 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -19,6 +19,38 @@ Changelog [unreleased] ------------ +Added +~~~~~ + +* openstack.pre_newton_neutron config option can be configured via environment + spec. + + .. code-block:: json + + { + "openstack": { + "api_info": { + "neutron": {"pre_newton": true} + }, + "auth_url": "http://example.net:5000/v3/", + "region_name": "RegionOne", + "endpoint_type": "public", + "admin": { + "username": "admin", + "password": "myadminpass", + "user_domain_name": "admin", + "project_name": "admin", + "project_domain_name": "admin" + }, + "https_insecure": false, + "https_cacert": "", + } + } + + Reminder: Based on this option, Rally will use or not some external fields + that can help to identify own resources during cleanup. + + Changed ~~~~~~~ @@ -69,8 +101,9 @@ Added Changed ~~~~~~~ -* `docker image `_ is - switched to use `docker image `_ as +* `xrally-openstack docker image + `_ is switched to use + `xrally/xrally docker image `_ as a base user that brings use python 3.6 and ubuntu bionic. * Bump min supported Rally framework version to 3.1.0 (rally>=3.1.0) @@ -203,7 +236,7 @@ Fixed * Handling of errors while cleaning up octavia resources * Missing project_id key for several Octavia API calls - `Launchpad-bug #1819284 `_ + `Launchpad-bug #1833235 `_ [1.5.0] - 2019-05-29 -------------------- diff --git a/etc/rally/rally.conf.sample b/etc/rally/rally.conf.sample index 154e728a..38b2a8c1 100644 --- a/etc/rally/rally.conf.sample +++ b/etc/rally/rally.conf.sample @@ -14,8 +14,8 @@ # configuration files, see the Python logging module documentation. # Note that when logging configuration files are used then all logging # configuration is set in the configuration file and other logging -# configuration options are ignored (for example, -# logging_context_format_string). (string value) +# configuration options are ignored (for example, log-date-format). +# (string value) # Note: This option can be changed without restarting. # Deprecated group/name - [DEFAULT]/log_config #log_config_append = @@ -67,28 +67,65 @@ # log_config_append is set. (boolean value) #use_stderr = true -# Format string to use for log messages with context. (string value) +# Log output to Windows Event Log. (boolean value) +#use_eventlog = false + +# The amount of time before the log files are rotated. This option is +# ignored unless log_rotation_type is setto "interval". (integer +# value) +#log_rotate_interval = 1 + +# Rotation interval type. The time of the last file change (or the +# time when the service was started) is used when scheduling the next +# rotation. (string value) +# Possible values: +# Seconds - +# Minutes - +# Hours - +# Days - +# Weekday - +# Midnight - +#log_rotate_interval_type = days + +# Maximum number of rotated log files. (integer value) +#max_logfile_count = 30 + +# Log file maximum size in MB. This option is ignored if +# "log_rotation_type" is not set to "size". (integer value) +#max_logfile_size_mb = 200 + +# Log rotation type. (string value) +# Possible values: +# interval - Rotate logs at predefined time intervals. +# size - Rotate logs once they reach a predefined size. +# none - Do not rotate log files. +#log_rotation_type = none + +# Format string to use for log messages with context. Used by +# oslo_log.formatters.ContextFormatter (string value) #logging_context_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s # Format string to use for log messages when context is undefined. -# (string value) +# Used by oslo_log.formatters.ContextFormatter (string value) #logging_default_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s # Additional data to append to log message when logging level for the -# message is DEBUG. (string value) +# message is DEBUG. Used by oslo_log.formatters.ContextFormatter +# (string value) #logging_debug_format_suffix = %(funcName)s %(pathname)s:%(lineno)d -# Prefix each line of exception output with this format. (string -# value) +# Prefix each line of exception output with this format. Used by +# oslo_log.formatters.ContextFormatter (string value) #logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d ERROR %(name)s %(instance)s # Defines the format string for %(user_identity)s that is used in -# logging_context_format_string. (string value) +# logging_context_format_string. Used by +# oslo_log.formatters.ContextFormatter (string value) #logging_user_identity_format = %(user)s %(tenant)s %(domain)s %(user_domain)s %(project_domain)s # List of package logging levels in logger=LEVEL pairs. This option is # ignored if log_config_append is set. (list value) -#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,oslo_messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN,taskflow=WARN,keystoneauth=WARN,oslo.cache=INFO,dogpile.core.dogpile=INFO +#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,oslo_messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN,taskflow=WARN,keystoneauth=WARN,oslo.cache=INFO,oslo_policy=INFO,dogpile.core.dogpile=INFO # Enables or disables publication of error events. (boolean value) #publish_errors = false @@ -121,6 +158,13 @@ # From rally # +# A mktemp(1)-like format string that will be used to pattern the +# generated random string. It must contain two separate segments of at +# least three 'X's; the first one will be replaced by a portion of the +# owner ID (i.e task/subtask ID), and the second will be replaced with +# a random string. (string value) +#context_resource_name_format = + # Print debugging output only for Rally. Off-site components stay # quiet. (boolean value) #rally_debug = false @@ -129,6 +173,13 @@ # Minimum value: 1 #raw_result_chunk_size = 1000 +# A mktemp(1)-like format string that will be used to pattern the +# generated random string. It must contain two separate segments of at +# least three 'X's; the first one will be replaced by a portion of the +# owner ID (i.e task/subtask ID), and the second will be replaced with +# a random string. (string value) +#scenario_resource_name_format = + # # From rally_openstack # @@ -182,16 +233,6 @@ # Deprecated group/name - [sql]/idle_timeout #connection_recycle_time = 3600 -# DEPRECATED: Minimum number of SQL connections to keep open in a -# pool. (integer value) -# Deprecated group/name - [DEFAULT]/sql_min_pool_size -# Deprecated group/name - [DATABASE]/sql_min_pool_size -# This option is deprecated for removal. -# Its value may be silently ignored in the future. -# Reason: The option to set the minimum pool size is not supported by -# sqlalchemy. -#min_pool_size = 1 - # Maximum number of SQL connections to keep open in a pool. Setting a # value of 0 indicates no limit. (integer value) # Deprecated group/name - [DEFAULT]/sql_max_pool_size @@ -289,16 +330,6 @@ # point value) #cinder_backup_restore_poll_interval = 2.0 -# Time to sleep after boot before polling for status (floating point -# value) -#ec2_server_boot_prepoll_delay = 1.0 - -# Server boot timeout (floating point value) -#ec2_server_boot_timeout = 300.0 - -# Server boot poll interval (floating point value) -#ec2_server_boot_poll_interval = 1.0 - # Time(in sec) to sleep after creating a resource before polling for # it status. (floating point value) #heat_stack_create_prepoll_delay = 2.0 @@ -783,6 +814,10 @@ # RAM size flavor used for orchestration test cases (integer value) #heat_instance_type_ram = 64 +# Disk size requirement in GiB flavor used for orchestration test +# cases (integer value) +#heat_instance_type_disk = 5 + # How many concurrent threads to use for serving roles context # (integer value) # Deprecated group/name - [roles_context]/resource_management_workers @@ -819,8 +854,8 @@ # Neutron create loadbalancer poll interval (floating point value) #neutron_create_loadbalancer_poll_interval = 2.0 -# Whether Neutron API is older then OpenStack Newton or not. Based in -# this option, some external fields for identifying resources can be +# Whether Neutron API is older then OpenStack Newton or not. Based on +# the option, some external fields for identifying resources can be # applied. (boolean value) #pre_newton_neutron = false diff --git a/rally_openstack/common/cfg/neutron.py b/rally_openstack/common/cfg/neutron.py index 0ac32b12..1564bf52 100644 --- a/rally_openstack/common/cfg/neutron.py +++ b/rally_openstack/common/cfg/neutron.py @@ -27,7 +27,7 @@ OPTS = {"openstack": [ cfg.BoolOpt("pre_newton_neutron", default=False, help="Whether Neutron API is older then OpenStack Newton or " - "not. Based in this option, some external fields for " + "not. Based on the option, some external fields for " "identifying resources can be applied."), cfg.ListOpt("neutron_bind_l2_agent_types", # default to agent types used in gate jobs diff --git a/rally_openstack/common/services/network/neutron.py b/rally_openstack/common/services/network/neutron.py index aa63c391..6350c815 100644 --- a/rally_openstack/common/services/network/neutron.py +++ b/rally_openstack/common/services/network/neutron.py @@ -948,8 +948,10 @@ class NeutronService(service.Service): "networks found.") net_id = ext_networks[0]["id"] - description = None - if not CONF.openstack.pre_newton_neutron: + description = _NONE + api_info = self._clients.credential.api_info.get("neutron", {}) + if (not api_info.get("pre_newton", False) + and not CONF.openstack.pre_newton_neutron): description = self.generate_random_name() body = _clean_dict( diff --git a/rally_openstack/environment/platforms/existing.py b/rally_openstack/environment/platforms/existing.py index b83f97f1..4285cf68 100644 --- a/rally_openstack/environment/platforms/existing.py +++ b/rally_openstack/environment/platforms/existing.py @@ -69,7 +69,7 @@ class OpenStack(platform.Platform): "api_info": { "type": "object", "patternProperties": { - "^[a-z]+$": { + "^(?!neutron)([a-z]+)$": { "type": "object", "properties": { "version": VERSION_SCHEMA, @@ -77,6 +77,24 @@ class OpenStack(platform.Platform): }, "minProperties": 1, "additionalProperties": False + }, + "^neutron$": { + "type": "object", + "properties": { + "version": VERSION_SCHEMA, + "service_type": {"type": "string"}, + "pre_newton": { + "type": "boolean", + "description": "Whether Neutron API is older " + "then OpenStack Newton or not. " + "Based on this option, some " + "external fields for " + "identifying resources can be " + "applied." + } + }, + "minProperties": 1, + "additionalProperties": False } }, "additionalProperties": False diff --git a/tests/unit/common/services/network/test_neutron.py b/tests/unit/common/services/network/test_neutron.py index 4255e3e8..fef92f46 100644 --- a/tests/unit/common/services/network/test_neutron.py +++ b/tests/unit/common/services/network/test_neutron.py @@ -15,6 +15,7 @@ from unittest import mock from rally import exceptions +from rally_openstack.common import credential from rally_openstack.common.services.network import neutron from tests.unit import test @@ -25,7 +26,13 @@ PATH = "rally_openstack.common.services.network.neutron" class NeutronServiceTestCase(test.TestCase): def setUp(self): super(NeutronServiceTestCase, self).setUp() - self.clients = mock.MagicMock() + self.clients = mock.MagicMock( + credential=credential.OpenStackCredential( + auth_url="example.com", + username="root", + password="changeme" + ) + ) self.nc = self.clients.neutron.return_value self.atomic_inst = [] @@ -821,6 +828,24 @@ class NeutronServiceTestCase(test.TestCase): self.nc.create_floatingip.reset_mock() self.nc.list_networks.reset_mock() + def test_create_floatingip_pre_newton(self): + self.clients.credential.api_info["neutron"] = {"pre_newton": True} + floatingip = "foo" + self.nc.create_floatingip.return_value = {"floatingip": floatingip} + floating_network = {"id": "net-id"} + + self.assertEqual( + floatingip, + self.neutron.create_floatingip(floating_network=floating_network) + ) + self.nc.create_floatingip.assert_called_once_with( + { + "floatingip": {"floating_network_id": floating_network["id"]} + } + ) + # generate random name should not be called + self.assertEqual(0, self.name_generator_count) + @mock.patch("%s.LOG.info" % PATH) def test_create_floatingip_failure(self, mock_log_info): from neutronclient.common import exceptions as neutron_exceptions diff --git a/tests/unit/task/scenarios/neutron/test_network.py b/tests/unit/task/scenarios/neutron/test_network.py index 11c161b3..22892319 100644 --- a/tests/unit/task/scenarios/neutron/test_network.py +++ b/tests/unit/task/scenarios/neutron/test_network.py @@ -29,6 +29,7 @@ class NeutronNetworksTestCase(test.TestCase): super(NeutronNetworksTestCase, self).setUp() patch = mock.patch("rally_openstack.common.osclients.Clients") self.clients = patch.start().return_value + self.clients.credential.api_info = {} self.addCleanup(patch.stop) self.nc = self.clients.neutron.return_value diff --git a/tests/unit/task/scenarios/neutron/test_utils.py b/tests/unit/task/scenarios/neutron/test_utils.py index 71f992f5..7d8b84d9 100644 --- a/tests/unit/task/scenarios/neutron/test_utils.py +++ b/tests/unit/task/scenarios/neutron/test_utils.py @@ -20,6 +20,7 @@ import netaddr from rally import exceptions from rally_openstack.common import consts +from rally_openstack.common import credential from rally_openstack.task.scenarios.neutron import utils from tests.unit import test @@ -34,7 +35,14 @@ class NeutronScenarioTestCase(test.ScenarioTestCase): def setUp(self): super(NeutronScenarioTestCase, self).setUp() self.network = mock.Mock() - self._clients = mock.MagicMock() + self._clients = mock.MagicMock( + credential=credential.OpenStackCredential( + auth_url="example.com", + username="root", + password="changeme", + permission=consts.EndpointPermission.ADMIN + ) + ) self._nc = self._clients.neutron.return_value self.scenario = utils.NeutronScenario(self.context, clients=self._clients) diff --git a/tests/unit/task/scenarios/nova/test_servers.py b/tests/unit/task/scenarios/nova/test_servers.py index 49cd2e02..cabee216 100644 --- a/tests/unit/task/scenarios/nova/test_servers.py +++ b/tests/unit/task/scenarios/nova/test_servers.py @@ -920,7 +920,7 @@ class NovaServersTestCase(test.ScenarioTestCase): server, "novnc") def test_boot_and_associate_floating_ip(self): - clients = mock.MagicMock() + clients = mock.MagicMock(credential=mock.MagicMock(api_info={})) neutronclient = clients.neutron.return_value floatingip = "floatingip" neutronclient.create_floatingip.return_value = { @@ -994,7 +994,7 @@ class NovaServersTestCase(test.ScenarioTestCase): ) def test_boot_server_associate_and_dissociate_floating_ip(self): - clients = mock.MagicMock() + clients = mock.MagicMock(credential=mock.MagicMock(api_info={})) neutronclient = clients.neutron.return_value floatingip = "floatingip" neutronclient.create_floatingip.return_value = { diff --git a/tests/unit/task/scenarios/vm/test_utils.py b/tests/unit/task/scenarios/vm/test_utils.py index f4dabafb..65ce41a4 100644 --- a/tests/unit/task/scenarios/vm/test_utils.py +++ b/tests/unit/task/scenarios/vm/test_utils.py @@ -136,7 +136,9 @@ class VMScenarioTestCase(test.ScenarioTestCase): addresses={"foo_net": [{"addr": "foo_ip"}]}, tenant_id="foo_tenant" ) - scenario = utils.VMScenario(self.context, clients=mock.MagicMock()) + scenario = utils.VMScenario( + self.context, + clients=mock.MagicMock(credential=mock.MagicMock(api_info={}))) scenario._boot_server = mock.Mock(return_value=server) scenario._delete_server = mock.Mock()