`set_service_setting` accept multiple config changes

The method ``BaseTempestWhiteboxTestCase.set_service_setting`` accepts
multiple configuration parameters in one call. If the service
configuration changes, it will be needed to restart it only once.

Closes-Bug: #OSPRH-10514
Change-Id: I206f3ce73e9ab36d4fe1ba072735a0bd382c5621
This commit is contained in:
Rodolfo Alonso Hernandez 2024-10-04 08:45:40 +00:00
parent 6c381d8e20
commit 8b160a4c6e
5 changed files with 55 additions and 48 deletions

View File

@ -13,13 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
import base64
import collections
from functools import partial
from multiprocessing import Process
import os
import random
import re
import time
import typing
import yaml
import netaddr
@ -48,6 +48,8 @@ from whitebox_neutron_tempest_plugin.common import utils as local_utils
CONF = config.CONF
LOG = log.getLogger(__name__)
WB_CONF = CONF.whitebox_neutron_plugin_options
ConfigOption = collections.namedtuple(
'ConfigOption', ('section', 'parameter', 'value'))
class BaseTempestWhiteboxTestCase(base.BaseTempestTestCase):
@ -398,25 +400,29 @@ class BaseTempestWhiteboxTestCase(base.BaseTempestTestCase):
# TODO(mblue): next gen computes configuration set should be done too,
# 'oc patch' for data plane would need more steps and triggers deployment
@classmethod
def set_service_setting(cls, node_type: str = 'controller',
file: str = '', service: str = 'neutron',
section: str = 'DEFAULT', param: str = '',
value: typing.Union[str, int] = '',
cfg_change: bool = True) -> None:
def set_service_setting(
cls,
node_type: str = 'controller',
file: str = '',
service: str = 'neutron',
config_list: list[ConfigOption] = None,
cfg_change: bool = True
) -> None:
"""Set configuration for service
:param node_type: Node type for change, ex: controller/compute
(currently only controllers).
:param file: File for configuration change (except in podified).
All configuration parameters must be defined in the same file.
:param service: Podified service name (only podified).
:param section: Section in the config file.
:param param: Parameter in section to change.
:param value: Value to set.
:param config_list: List with the multiple configuration parameters,
defined in a namedtuple ConfigOption(section, parameter, value).
:param cfg_change: by default, it is always expected that the
configuration will change; in a podified environment, that implies a
pod replacement.
"""
assert param, "'param' must be supplied"
assert config_list, ("At least one configuration parameter must be "
"supplied")
if WB_CONF.openstack_type == 'podified' and node_type != 'compute':
service_pod = cls.get_pods_of_service(service)[0]
# TODO(mblue): process ini in python instead of crudini command,
@ -425,16 +431,22 @@ class BaseTempestWhiteboxTestCase(base.BaseTempestTestCase):
# combine configuration to stdout using mutable copy in service pod
# NOTE(mblue): 'bash -c' needed for 'oc rsh' to execute a few
# commands in pod shell session (instead of outside session).
combine_conf_cmd = (
"{0} rsh {1} bash -c '"
"cp /etc/neutron/neutron.conf.d/{2} /tmp/ && "
"chmod g+w /tmp/{2} && "
"crudini --set --output=- /tmp/{2} {3} {4} {5}'").format(
cls.OC, service_pod,
custom_file, section, param, value)
combined_conf = cls.proxy_host_client.exec_command(
combine_conf_cmd)
# correct indentation required for configuration to be accepted
copy_config = (
"{0} rsh {1} bash -c "
"'cp /etc/neutron/neutron.conf.d/{2} /tmp/ && "
"chmod g+w /tmp/{2}'").format(
cls.OC, service_pod, custom_file)
cls.proxy_host_client.exec_command(copy_config)
for config_option in config_list:
combine_conf_cmd = (
"{0} rsh {1} bash -c '"
"crudini --set /tmp/{2} {3} {4} {5}'").format(
cls.OC, service_pod, custom_file, config_option.section,
config_option.parameter, config_option.value)
cls.proxy_host_client.exec_command(combine_conf_cmd)
read_conf_cmd = "{0} rsh {1} bash -c 'cat /tmp/{2}'".format(
cls.OC, service_pod, custom_file)
combined_conf = cls.proxy_host_client.exec_command(read_conf_cmd)
combined_conf_ind = combined_conf.replace('\n', '\n' + 8 * ' ')
patch_buffer = (
'spec:\n'
@ -485,10 +497,12 @@ class BaseTempestWhiteboxTestCase(base.BaseTempestTestCase):
service=service,
pod_state=''))))
else:
cls.run_group_cmd(
'sudo crudini --set {} {} {} {} && sudo sync'.format(
file, section, param, value),
node_type)
for config_option in config_list:
cls.run_group_cmd(
'sudo crudini --set {} {} {} {} && sudo sync'.format(
file, config_option.section, config_option.parameter,
config_option.value),
node_type)
@classmethod
def check_service_setting(

View File

@ -44,10 +44,10 @@ class NeutronAPIServerTest(wb_base.BaseTempestTestCaseOvn):
# that will trigger the Neutron API restart. In a "devstack"
# environment, it will be needed to manually restart the Neutron API
# server.
_config = wb_base.ConfigOption('ovn', 'fdb_age_threshold',
random.randint(10000, 90000))
self.set_service_setting(file=wb_utils.get_ml2_conf_file(),
section='ovn',
param='fdb_age_threshold',
value=random.randint(10000, 90000))
config_list=[_config])
# 3) Restart Neutron API on all controllers simultaneously.
if not WB_CONF.openstack_type == 'podified':

View File

@ -97,12 +97,11 @@ class TestMetadataRateLimiting(wb_base.BaseTempestWhiteboxTestCase):
f'Section - {METADATA_RATE_LIMITING_SECTION}\n'
f'Parameter - {key}\n'
f'Value - {value}\n')
cls.set_service_setting(
node_type='compute',
file=cls.metadata_conf_file,
section=METADATA_RATE_LIMITING_SECTION,
param=key,
value=value)
_config = wb_base.ConfigOption(METADATA_RATE_LIMITING_SECTION,
key, value)
cls.set_service_setting(node_type='compute',
file=cls.metadata_conf_file,
config_list=[_config])
cls._restart_metadata_agent()
def tearDown(self):

View File

@ -51,15 +51,12 @@ class OvnFdbAgingTest(wb_base.BaseTempestTestCaseOvn):
def test_fdb_aging(self):
# 1) Configure the FDB learn flag and set the aging threshold to 5
# seconds.
config_list = [
wb_base.ConfigOption('ovn', 'localnet_learn_fdb', 'true'),
wb_base.ConfigOption('ovn', 'fdb_age_threshold',
FDB_AGE_THRESHOLD)]
self.set_service_setting(file=wb_utils.get_ml2_conf_file(),
section='ovn',
param='localnet_learn_fdb',
value='true',
cfg_change=False)
self.set_service_setting(file=wb_utils.get_ml2_conf_file(),
section='ovn',
param='fdb_age_threshold',
value=FDB_AGE_THRESHOLD,
config_list=config_list,
cfg_change=False)
# 2) restart neutron api on all controllers simultaneously

View File

@ -452,14 +452,11 @@ class BaseSecGroupLoggingTest(
# default preset (min possible): rate limit 100, burst limit 25
burst_val = random.randint(30, 150)
rate_val = random.randint(120, 300)
config_list = [
wb_base.ConfigOption('network_log', 'burst_limit', burst_val),
wb_base.ConfigOption('network_log', 'rate_limit', rate_val)]
self.set_service_setting(file=self.ML2_CONF_FILE,
section='network_log',
param='burst_limit',
value=burst_val)
self.set_service_setting(file=self.ML2_CONF_FILE,
section='network_log',
param='rate_limit',
value=rate_val)
config_list=config_list)
# 5) restart neutron api on all controllers simultaneously
if not WB_CONF.openstack_type == 'podified':
service_ptn = utils.get_neutron_api_service_name()