Create bw limit qos test
iperf is used to measure bw from a CentOS VM instance Change-Id: I4e474bd9fbaefae9e7d356eda2bf9c458ed3356b
This commit is contained in:
parent
1be2747cfd
commit
e91a08df90
|
@ -36,6 +36,7 @@ CONFIG_MODULES = ['tobiko.openstack.glance.config',
|
||||||
'tobiko.openstack.topology.config',
|
'tobiko.openstack.topology.config',
|
||||||
'tobiko.shell.ssh.config',
|
'tobiko.shell.ssh.config',
|
||||||
'tobiko.shell.ping.config',
|
'tobiko.shell.ping.config',
|
||||||
|
'tobiko.shell.iperf.config',
|
||||||
'tobiko.shell.sh.config',
|
'tobiko.shell.sh.config',
|
||||||
'tobiko.tripleo.config']
|
'tobiko.tripleo.config']
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from __future__ import absolute_import
|
||||||
import tobiko
|
import tobiko
|
||||||
from tobiko import config
|
from tobiko import config
|
||||||
from tobiko.openstack import glance
|
from tobiko.openstack import glance
|
||||||
|
from tobiko.openstack import nova
|
||||||
from tobiko.openstack.stacks import _nova
|
from tobiko.openstack.stacks import _nova
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,4 +62,9 @@ class CentosExternalServerStackFixture(CentosServerStackFixture,
|
||||||
|
|
||||||
class CentosQosServerStackFixture(CentosServerStackFixture,
|
class CentosQosServerStackFixture(CentosServerStackFixture,
|
||||||
_nova.QosServerStackFixture):
|
_nova.QosServerStackFixture):
|
||||||
pass
|
|
||||||
|
@property
|
||||||
|
def cloud_config(self):
|
||||||
|
return nova.cloud_config(
|
||||||
|
super(CentosQosServerStackFixture, self).cloud_config,
|
||||||
|
packages=['iperf3'])
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Copyright (c) 2021 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from tobiko.shell.iperf import _assert
|
||||||
|
|
||||||
|
|
||||||
|
assert_bw_limit = _assert.assert_bw_limit
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Copyright (c) 2019 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
|
import tobiko
|
||||||
|
from tobiko import config
|
||||||
|
from tobiko.shell.iperf import _iperf
|
||||||
|
|
||||||
|
|
||||||
|
CONF = config.CONF
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_bw(iperf_measures):
|
||||||
|
# first interval is removed because BW measured during it is not
|
||||||
|
# limited - it takes ~ 1 second to traffic shaping algorithm to apply
|
||||||
|
# bw limit properly (buffer is empty when traffic starts being sent)
|
||||||
|
intervals = iperf_measures['intervals'][1:]
|
||||||
|
|
||||||
|
bits_received = sum([interval['sum']['bytes'] * 8
|
||||||
|
for interval in intervals])
|
||||||
|
totaltime = sum([interval['sum']['seconds'] for interval in intervals])
|
||||||
|
# bw in bits per second
|
||||||
|
return bits_received / totaltime
|
||||||
|
|
||||||
|
|
||||||
|
def assert_bw_limit(ssh_client, ssh_server, **params):
|
||||||
|
iperf_measures = _iperf.iperf(ssh_client, ssh_server, **params)
|
||||||
|
measured_bw = calculate_bw(iperf_measures)
|
||||||
|
|
||||||
|
testcase = tobiko.get_test_case()
|
||||||
|
bw_limit = float(params.get('bw_limit') or
|
||||||
|
CONF.tobiko.neutron.bwlimit_kbps * 1000.)
|
||||||
|
LOG.debug('measured_bw = %f', measured_bw)
|
||||||
|
LOG.debug('bw_limit = %f', bw_limit)
|
||||||
|
# a 5% of upper deviation is allowed
|
||||||
|
testcase.assertLess(measured_bw, bw_limit * 1.05)
|
||||||
|
# an 8% of lower deviation is allowed
|
||||||
|
testcase.assertGreater(measured_bw, bw_limit * 0.92)
|
|
@ -0,0 +1,185 @@
|
||||||
|
# Copyright (c) 2021 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
|
import tobiko
|
||||||
|
from tobiko.shell import sh
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def install_iperf(ssh_client):
|
||||||
|
def iperf_help():
|
||||||
|
cmd = 'iperf3 --help'
|
||||||
|
try:
|
||||||
|
return sh.execute(cmd,
|
||||||
|
expect_exit_status=None,
|
||||||
|
ssh_client=ssh_client)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return sh.execute_result(command=cmd,
|
||||||
|
exit_status=127,
|
||||||
|
stdout='command not found')
|
||||||
|
result = iperf_help()
|
||||||
|
usage = ((result.stdout and str(result.stdout)) or
|
||||||
|
(result.stderr and str(result.stderr)) or "").strip()
|
||||||
|
if result.exit_status != 0 and 'command not found' in usage.lower():
|
||||||
|
install_command = '{install_tool} install -y iperf3'
|
||||||
|
install_tools = ('yum', 'apt')
|
||||||
|
for install_tool in install_tools:
|
||||||
|
try:
|
||||||
|
result = sh.execute(
|
||||||
|
command=install_command.format(install_tool=install_tool),
|
||||||
|
ssh_client=ssh_client,
|
||||||
|
sudo=True)
|
||||||
|
except sh.ShellError:
|
||||||
|
LOG.debug(f'Unable to install iperf3 using {install_tool}')
|
||||||
|
else:
|
||||||
|
LOG.debug(f'iperf3 successfully installed with {install_tool}')
|
||||||
|
break
|
||||||
|
|
||||||
|
if iperf_help().exit_status != 0:
|
||||||
|
raise RuntimeError('iperf3 command was not installed successfully')
|
||||||
|
elif result.exit_status != 0:
|
||||||
|
raise RuntimeError('Error executing iperf3 command')
|
||||||
|
else:
|
||||||
|
LOG.debug('iperf3 already installed')
|
||||||
|
|
||||||
|
|
||||||
|
def get_iperf_command(parameters, ssh_client):
|
||||||
|
interface = get_iperf_interface(ssh_client=ssh_client)
|
||||||
|
return interface.get_iperf_command(parameters)
|
||||||
|
|
||||||
|
|
||||||
|
def get_iperf_interface(ssh_client):
|
||||||
|
manager = tobiko.setup_fixture(IperfInterfaceManager)
|
||||||
|
interface = manager.get_iperf_interface(ssh_client=ssh_client)
|
||||||
|
tobiko.check_valid_type(interface, IperfInterface)
|
||||||
|
return interface
|
||||||
|
|
||||||
|
|
||||||
|
class IperfInterfaceManager(tobiko.SharedFixture):
|
||||||
|
def __init__(self):
|
||||||
|
super(IperfInterfaceManager, self).__init__()
|
||||||
|
self.client_interfaces = {}
|
||||||
|
self.interfaces = []
|
||||||
|
self.default_interface = IperfInterface()
|
||||||
|
|
||||||
|
def add_iperf_interface(self, interface):
|
||||||
|
LOG.debug('Register iperf interface %r', interface)
|
||||||
|
self.interfaces.append(interface)
|
||||||
|
|
||||||
|
def get_iperf_interface(self, ssh_client):
|
||||||
|
try:
|
||||||
|
return self.client_interfaces[ssh_client]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
install_iperf(ssh_client)
|
||||||
|
LOG.debug('Assign default iperf interface to SSH client %r',
|
||||||
|
ssh_client)
|
||||||
|
self.client_interfaces[ssh_client] = self.default_interface
|
||||||
|
return self.default_interface
|
||||||
|
|
||||||
|
|
||||||
|
class IperfInterface(object):
|
||||||
|
def get_iperf_command(self, parameters):
|
||||||
|
command = sh.shell_command(['iperf3'] +
|
||||||
|
self.get_iperf_options(parameters))
|
||||||
|
LOG.debug(f'Got iperf command: {command}')
|
||||||
|
return command
|
||||||
|
|
||||||
|
def get_iperf_options(self, parameters):
|
||||||
|
options = []
|
||||||
|
|
||||||
|
port = parameters.port
|
||||||
|
if port:
|
||||||
|
options += self.get_port_option(port)
|
||||||
|
|
||||||
|
timeout = parameters.timeout
|
||||||
|
if timeout and parameters.mode == 'client':
|
||||||
|
options += self.get_timeout_option(timeout)
|
||||||
|
|
||||||
|
output_format = parameters.output_format
|
||||||
|
if output_format:
|
||||||
|
options += self.get_output_format_option(output_format)
|
||||||
|
|
||||||
|
bitrate = parameters.bitrate
|
||||||
|
if bitrate and parameters.mode == 'client':
|
||||||
|
options += self.get_bitrate_option(bitrate)
|
||||||
|
|
||||||
|
download = parameters.download
|
||||||
|
if download and parameters.mode == 'client':
|
||||||
|
options += self.get_download_option(download)
|
||||||
|
|
||||||
|
protocol = parameters.protocol
|
||||||
|
if protocol and parameters.mode == 'client':
|
||||||
|
options += self.get_protocol_option(protocol)
|
||||||
|
|
||||||
|
options += self.get_mode_option(parameters)
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_mode_option(parameters):
|
||||||
|
mode = parameters.mode
|
||||||
|
if not mode or mode not in ('client', 'server'):
|
||||||
|
raise ValueError('iperf mode values allowed: [client|server]')
|
||||||
|
elif mode == 'client' and not parameters.ip:
|
||||||
|
raise ValueError('iperf client mode requires a destination '
|
||||||
|
'IP address')
|
||||||
|
elif mode == 'client':
|
||||||
|
return ['-c', parameters.ip]
|
||||||
|
else: # mode == 'server'
|
||||||
|
return ['-s', '-D'] # server mode is executed with daemon mode
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_download_option(download):
|
||||||
|
if download:
|
||||||
|
return ['-R']
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_protocol_option(protocol):
|
||||||
|
if protocol == 'tcp':
|
||||||
|
return []
|
||||||
|
elif protocol == 'udp':
|
||||||
|
return ['-u']
|
||||||
|
else:
|
||||||
|
raise ValueError('iperf protocol values allowed: [tcp|udp]')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_timeout_option(timeout):
|
||||||
|
return ['-t', timeout]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_output_format_option(output_format):
|
||||||
|
if output_format == 'json':
|
||||||
|
return ['-J']
|
||||||
|
else:
|
||||||
|
raise ValueError('iperf output format values allowed: '
|
||||||
|
'[json]')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_port_option(port):
|
||||||
|
return ['-p', port]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_bitrate_option(bitrate):
|
||||||
|
return ['-b', bitrate]
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Copyright (c) 2021 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
|
from tobiko.shell.iperf import _interface
|
||||||
|
from tobiko.shell.iperf import _parameters
|
||||||
|
from tobiko.shell import sh
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def iperf(ssh_client, ssh_server, **iperf_params):
|
||||||
|
"""Run iperf on both client and server machines and return obtained
|
||||||
|
statistics
|
||||||
|
|
||||||
|
:param ssh_client: ssh connection to client
|
||||||
|
:param ssh_server: ssh connection to server
|
||||||
|
:param **iperf_params: parameters to be forwarded to get_statistics()
|
||||||
|
function
|
||||||
|
:returns: dict
|
||||||
|
"""
|
||||||
|
parameters_server = _parameters.get_iperf_parameters(
|
||||||
|
mode='server', **iperf_params)
|
||||||
|
# no output expected
|
||||||
|
execute_iperf_server(parameters_server, ssh_server)
|
||||||
|
|
||||||
|
time.sleep(0.1)
|
||||||
|
parameters_client = _parameters.get_iperf_parameters(
|
||||||
|
mode='client', ip=ssh_server.host, **iperf_params)
|
||||||
|
# output is a dictionary
|
||||||
|
output = execute_iperf_client(parameters_client, ssh_client)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def execute_iperf_server(parameters, ssh_client):
|
||||||
|
# kill any iperf3 process running before executing it again
|
||||||
|
sh.execute(command='pkill iperf3',
|
||||||
|
ssh_client=ssh_client,
|
||||||
|
expect_exit_status=None)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# server is executed in background and no output is expected
|
||||||
|
command = _interface.get_iperf_command(parameters=parameters,
|
||||||
|
ssh_client=ssh_client)
|
||||||
|
sh.execute(command=command, ssh_client=ssh_client)
|
||||||
|
|
||||||
|
|
||||||
|
def execute_iperf_client(parameters, ssh_client):
|
||||||
|
command = _interface.get_iperf_command(parameters=parameters,
|
||||||
|
ssh_client=ssh_client)
|
||||||
|
result = sh.execute(command=command,
|
||||||
|
ssh_client=ssh_client,
|
||||||
|
timeout=parameters.timeout + 5.,
|
||||||
|
expect_exit_status=None)
|
||||||
|
return json.loads(result.stdout)
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Copyright (c) 2021 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import collections
|
||||||
|
|
||||||
|
from tobiko import config
|
||||||
|
|
||||||
|
|
||||||
|
CONF = config.CONF
|
||||||
|
|
||||||
|
|
||||||
|
def get_iperf_parameters(mode, ip=None, **iperf_params):
|
||||||
|
"""Get iperf parameters
|
||||||
|
mode allowed values: client or server
|
||||||
|
ip is only needed for client mode
|
||||||
|
"""
|
||||||
|
return IperfParameters(
|
||||||
|
mode=mode,
|
||||||
|
ip=ip,
|
||||||
|
port=iperf_params.get('port', CONF.tobiko.iperf.port),
|
||||||
|
timeout=iperf_params.get('timeout', CONF.tobiko.iperf.timeout),
|
||||||
|
output_format=iperf_params.get('output_format',
|
||||||
|
CONF.tobiko.iperf.output_format),
|
||||||
|
download=iperf_params.get('download', CONF.tobiko.iperf.download),
|
||||||
|
bitrate=iperf_params.get('bitrate', CONF.tobiko.iperf.bitrate),
|
||||||
|
protocol=iperf_params.get('protocol', CONF.tobiko.iperf.protocol))
|
||||||
|
|
||||||
|
|
||||||
|
class IperfParameters(collections.namedtuple('IperfParameters',
|
||||||
|
['mode',
|
||||||
|
'ip',
|
||||||
|
'port',
|
||||||
|
'timeout',
|
||||||
|
'output_format',
|
||||||
|
'download',
|
||||||
|
'bitrate',
|
||||||
|
'protocol'])):
|
||||||
|
"""Recollect parameters to be used to format iperf command line
|
||||||
|
|
||||||
|
IperfParameters class is a data model recollecting parameters used to
|
||||||
|
create an iperf command line. It provides the feature of copying default
|
||||||
|
values from another instance of IperfParameters passed using constructor
|
||||||
|
parameter 'default'.
|
||||||
|
"""
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Copyright 2021 Red Hat
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
GROUP_NAME = "iperf"
|
||||||
|
OPTIONS = [
|
||||||
|
cfg.IntOpt('port',
|
||||||
|
default=1234,
|
||||||
|
help="Port number"),
|
||||||
|
cfg.StrOpt('protocol',
|
||||||
|
default='tcp',
|
||||||
|
choices=['tcp', 'udp'],
|
||||||
|
help="tcp and udp values are supported"),
|
||||||
|
cfg.StrOpt('output_format',
|
||||||
|
default='json',
|
||||||
|
choices=['', 'json'],
|
||||||
|
help="output format"),
|
||||||
|
cfg.IntOpt('bitrate',
|
||||||
|
default=20000000,
|
||||||
|
help="target bit rate"),
|
||||||
|
cfg.BoolOpt('download',
|
||||||
|
default=True,
|
||||||
|
help="direction download (True) or upload (False)"),
|
||||||
|
cfg.IntOpt('timeout',
|
||||||
|
default=10,
|
||||||
|
help="timeout of the iperf test")]
|
||||||
|
|
||||||
|
|
||||||
|
def register_tobiko_options(conf):
|
||||||
|
conf.register_opts(group=cfg.OptGroup(GROUP_NAME), opts=OPTIONS)
|
||||||
|
|
||||||
|
|
||||||
|
def list_options():
|
||||||
|
return [(GROUP_NAME, itertools.chain(OPTIONS))]
|
|
@ -42,6 +42,7 @@ ShellStdinClosed = _exception.ShellStdinClosed
|
||||||
|
|
||||||
execute = _execute.execute
|
execute = _execute.execute
|
||||||
execute_process = _execute.execute_process
|
execute_process = _execute.execute_process
|
||||||
|
execute_result = _execute.execute_result
|
||||||
ShellExecuteResult = _execute.ShellExecuteResult
|
ShellExecuteResult = _execute.ShellExecuteResult
|
||||||
|
|
||||||
HostNameError = _hostname.HostnameError
|
HostNameError = _hostname.HostnameError
|
||||||
|
|
|
@ -20,6 +20,7 @@ import testtools
|
||||||
import tobiko
|
import tobiko
|
||||||
from tobiko.openstack import stacks
|
from tobiko.openstack import stacks
|
||||||
from tobiko.openstack import topology
|
from tobiko.openstack import topology
|
||||||
|
from tobiko.shell import iperf
|
||||||
from tobiko.tripleo import containers
|
from tobiko.tripleo import containers
|
||||||
from tobiko.tripleo import overcloud
|
from tobiko.tripleo import overcloud
|
||||||
|
|
||||||
|
@ -41,11 +42,24 @@ class QoSBasicTest(testtools.TestCase):
|
||||||
if (overcloud.has_overcloud() and
|
if (overcloud.has_overcloud() and
|
||||||
topology.verify_osp_version('16.0', lower=True) and
|
topology.verify_osp_version('16.0', lower=True) and
|
||||||
containers.ovn_used_on_overcloud()):
|
containers.ovn_used_on_overcloud()):
|
||||||
self.skip("QoS not supported in this setup")
|
self.skipTest("QoS not supported in this setup")
|
||||||
|
|
||||||
def test_qos_basic(self):
|
def test_qos_basic(self):
|
||||||
# Verify QoS Policy attached to the network corresponds with the QoS
|
'''Verify QoS Policy attached to the network corresponds with the QoS
|
||||||
# Policy previously created
|
Policy previously created'''
|
||||||
self.assertEqual(self.stack.network_stack.qos_stack.qos_policy_id,
|
self.assertEqual(self.stack.network_stack.qos_stack.qos_policy_id,
|
||||||
self.stack.network_stack.qos_policy_id)
|
self.stack.network_stack.qos_policy_id)
|
||||||
self.assertIsNone(self.stack.port_details['qos_policy_id'])
|
self.assertIsNone(self.stack.port_details['qos_policy_id'])
|
||||||
|
|
||||||
|
def test_qos_bw_limit(self):
|
||||||
|
'''Verify BW limit using the iperf tool
|
||||||
|
The test is executed from the undercloud node (client) to the VM
|
||||||
|
instance (server)'''
|
||||||
|
if not tobiko.tripleo.has_undercloud():
|
||||||
|
# TODO(eolivare): this test does not support devstack environments
|
||||||
|
# yet and that should be fixed
|
||||||
|
tobiko.skip_test('test not supported on devstack environments')
|
||||||
|
|
||||||
|
ssh_client = None # localhost will act as client
|
||||||
|
ssh_server = self.stack.peer_ssh_client
|
||||||
|
iperf.assert_bw_limit(ssh_client, ssh_server)
|
||||||
|
|
Loading…
Reference in New Issue