Replace SR-IOV systemd unit script
* The goal of this change is to enable the ability to configure only the VFs that are configured through the charm and not fallback to the blanket configuration. * This python version of the script brings unit-tests that fully covers it. * Move the the template files to `files` and modify `neutron_ovs_utils` accordingly. Closes-Bug: 1832379 Depends-On: https://review.opendev.org/#/c/664837/ Change-Id: I7ad1ebc16883bda23cbad89a852e7e8f88f49c49
This commit is contained in:
parent
fc7c7b3885
commit
d02fad482d
@ -13,7 +13,7 @@ WantedBy=network-online.target
|
||||
[Service]
|
||||
Type=oneshot
|
||||
EnvironmentFile=-/etc/default/networking-sriov
|
||||
ExecStart=/etc/init.d/neutron-openvswitch-networking-sriov.sh systemd-start
|
||||
ExecStop=/etc/init.d/neutron-openvswitch-networking-sriov.sh systemd-stop
|
||||
ExecStart=/usr/local/bin/neutron-openvswitch-networking-sriov.sh systemd-start
|
||||
ExecStop=/usr/local/bin/neutron-openvswitch-networking-sriov.sh systemd-stop
|
||||
RemainAfterExit=true
|
||||
TimeoutStartSec=5min
|
73
files/neutron-openvswitch-networking-sriov.sh
Executable file
73
files/neutron-openvswitch-networking-sriov.sh
Executable file
@ -0,0 +1,73 @@
|
||||
#!/bin/sh
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: networking-sriov
|
||||
# Required-Start: mountkernfs $local_fs
|
||||
# Required-Stop: $local_fs
|
||||
# Default-Start: S
|
||||
# Default-Stop: 0 6
|
||||
# Short-Description: Configure SRIOV Virtual Functions
|
||||
### END INIT INFO
|
||||
|
||||
# Authors: Frode Nordahl <frode.nordahl@gmail.com>
|
||||
|
||||
DESC="Configure SRIOV Virtual Functions"
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
# Include defaults if available
|
||||
if [ -f /etc/default/neutron-openvswitch-networking-sriov ] ; then
|
||||
. /etc/default/neutron-openvswitch-networking-sriov
|
||||
fi
|
||||
|
||||
if [ -z "${ENABLE}" ]; then
|
||||
ENABLE=0
|
||||
fi
|
||||
|
||||
if [ -z "${VFS_BLANKET}" ]; then
|
||||
VFS_BLANKET=auto
|
||||
fi
|
||||
|
||||
# Exit if feature is not enabled
|
||||
[ $ENABLE -gt 0 ] || exit 0
|
||||
|
||||
do_start() {
|
||||
/usr/local/bin/neutron_openvswitch_networking_sriov.py --start --vfs "${VFS_LIST}" --vfs-blanket "${VFS_BLANKET}"
|
||||
}
|
||||
|
||||
do_restart() {
|
||||
/usr/local/bin/neutron_openvswitch_networking_sriov.py --restart --vfs "${VFS_LIST}" --vfs-blanket "${VFS_BLANKET}"
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
/usr/local/bin/neutron_openvswitch_networking_sriov.py --stop --vfs "${VFS_LIST}" --vfs-blanket "${VFS_BLANKET}"
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
log_daemon_msg "$DESC"
|
||||
do_start
|
||||
;;
|
||||
stop)
|
||||
log_daemon_msg "Un-$DESC"
|
||||
do_stop
|
||||
;;
|
||||
systemd-start)
|
||||
do_start
|
||||
;;
|
||||
systemd-stop)
|
||||
do_stop
|
||||
;;
|
||||
restart)
|
||||
log_daemon_msg "Re-$DESC"
|
||||
do_stop
|
||||
do_start
|
||||
;;
|
||||
*)
|
||||
N=/usr/local/bin/neutron-openvswitch-networking-sriov.sh
|
||||
echo "Usage: $N {start|stop|restart|systemd-start|systemd-stop}" >&2
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
220
files/neutron_openvswitch_networking_sriov.py
Executable file
220
files/neutron_openvswitch_networking_sriov.py
Executable file
@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright 2019 Canonical Ltd
|
||||
#
|
||||
# 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
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def wait_for_vfs(device, numvfs):
|
||||
"""Wait for the VFs to be created.
|
||||
|
||||
:param str device: path to the NIC
|
||||
:param str numvfs: number of VFs to wait for
|
||||
:returns: None
|
||||
"""
|
||||
numvfs = int(numvfs)
|
||||
created_vfs_number = 0
|
||||
while created_vfs_number < numvfs:
|
||||
created_vfs = [f for f in os.listdir(device) if f.startswith('virtfn')]
|
||||
created_vfs_number = len(created_vfs)
|
||||
print('Waiting for {numvfs} VFs to appear in {dev}'.format(
|
||||
numvfs=numvfs, dev=device))
|
||||
time.sleep(0.05)
|
||||
|
||||
|
||||
def get_totalvfs(device):
|
||||
"""Get the number of allowed VFs.
|
||||
|
||||
:param str device: Path of the device
|
||||
:returns: number of allowed VFs.
|
||||
:rtype: str
|
||||
"""
|
||||
path = os.path.join(device, 'sriov_totalvfs')
|
||||
with open(path) as f:
|
||||
total_vfs = f.read()
|
||||
return total_vfs
|
||||
|
||||
|
||||
def find_sriov_devices():
|
||||
"""Find SR-IOV devices.
|
||||
|
||||
:returns: list of SR-IOV devices' paths
|
||||
:rtype: list
|
||||
"""
|
||||
f_name = 'sriov_totalvfs'
|
||||
devices = []
|
||||
for path, dirs, files in os.walk('/sys/devices'):
|
||||
if f_name in files:
|
||||
devices.append(path)
|
||||
return devices
|
||||
|
||||
|
||||
def write_sriov_numvfs(base_path, numvfs):
|
||||
"""Write the number of VFs to file.
|
||||
|
||||
:param str base_path: Path of the device
|
||||
:param str numvfs: Number of VFs
|
||||
:returns: None
|
||||
"""
|
||||
path = os.path.join(base_path, 'sriov_numvfs')
|
||||
print('Configuring {numvfs} VFs for {path}'.format(
|
||||
numvfs=numvfs, path=path))
|
||||
try:
|
||||
with open(path, 'w') as f:
|
||||
f.write(numvfs)
|
||||
wait_for_vfs(base_path, numvfs)
|
||||
except OSError as err:
|
||||
print(
|
||||
'Error while configuring VFs: {err}'.format(err=err))
|
||||
|
||||
|
||||
def configure_vfs(vfs, vfs_blanket='auto', stop=False):
|
||||
"""Configure the VFs.
|
||||
|
||||
:param dict vfs: list of VFs as dict (e.g. {'eth0': '8', 'eth1': '4'}
|
||||
:param str vfs_blanket: blanket config for the VFs
|
||||
:param bool stop: If we are stopping
|
||||
:returns: None
|
||||
"""
|
||||
if vfs:
|
||||
for device, numvfs in vfs.items():
|
||||
if stop:
|
||||
numvfs = '0'
|
||||
base_path = '/sys/class/net/{dev}/device/'.format(dev=device)
|
||||
write_sriov_numvfs(base_path, numvfs)
|
||||
else:
|
||||
sriov_devices = find_sriov_devices()
|
||||
for device in sriov_devices:
|
||||
total_vfs = get_totalvfs(device)
|
||||
if stop:
|
||||
vfs_blanket = '0'
|
||||
if vfs_blanket == 'auto':
|
||||
numvfs = total_vfs
|
||||
elif int(vfs_blanket) > int(total_vfs):
|
||||
numvfs = total_vfs
|
||||
else:
|
||||
numvfs = vfs_blanket
|
||||
write_sriov_numvfs(device, numvfs)
|
||||
|
||||
|
||||
def restart(vfs, vfs_blanket):
|
||||
"""Restart the VFs
|
||||
|
||||
:param dict vfs: list of VFs as dict (e.g. {'eth0': '8', 'eth1': '4'}
|
||||
:returns: None
|
||||
"""
|
||||
stop(vfs)
|
||||
start(vfs, vfs_blanket)
|
||||
|
||||
|
||||
def start(vfs, vfs_blanket):
|
||||
"""Start the VFs.
|
||||
|
||||
:param dict vfs: list of VFs as dict (e.g. {'eth0': '8', 'eth1': '4'}
|
||||
:returns: None
|
||||
"""
|
||||
configure_vfs(vfs, vfs_blanket)
|
||||
|
||||
|
||||
def stop(vfs):
|
||||
"""Stop the VFs.
|
||||
|
||||
:param dict vfs: list of VFs as dict (e.g. {'eth0': '8', 'eth1': '4'}
|
||||
:returns: None
|
||||
"""
|
||||
configure_vfs(vfs, stop=True)
|
||||
|
||||
|
||||
def parse_vfs(vfs=None):
|
||||
"""Parse VFs from string
|
||||
|
||||
:param dict vfs: string containing the VFs
|
||||
:returns: dict of VFs
|
||||
:rtype: dict {
|
||||
'eth0': '8',
|
||||
'eth1': '2'
|
||||
}
|
||||
"""
|
||||
if not vfs:
|
||||
return {}
|
||||
parsed_vfs = {}
|
||||
for vf in vfs.split():
|
||||
k, v = vf.split(':')
|
||||
parsed_vfs[k] = v
|
||||
return parsed_vfs
|
||||
|
||||
|
||||
def parse_args(args):
|
||||
"""Parse the arguments.
|
||||
|
||||
: param list args: list of args
|
||||
: returns: the parsed arguments
|
||||
: rtype: Namespace
|
||||
: raises SystemExit: if there are missing required args
|
||||
"""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--start',
|
||||
help='Start',
|
||||
action='store_true',
|
||||
default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
'--stop',
|
||||
help='Stop',
|
||||
action='store_true',
|
||||
default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
'--restart',
|
||||
help='Restart',
|
||||
action='store_true',
|
||||
default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
'--vfs',
|
||||
help='VFS List'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--vfs-blanket',
|
||||
help='VFS Blanket',
|
||||
default='auto'
|
||||
)
|
||||
return parser.parse_args(args)
|
||||
|
||||
|
||||
def main(args):
|
||||
"""Main function.
|
||||
|
||||
: param list args: list of arguments
|
||||
: returns: 0
|
||||
: rtype: int
|
||||
"""
|
||||
args = parse_args(args)
|
||||
vfs = parse_vfs(args.vfs)
|
||||
if args.restart:
|
||||
restart(vfs, args.vfs_blanket)
|
||||
elif args.start:
|
||||
start(vfs, args.vfs_blanket)
|
||||
elif args.stop:
|
||||
stop(vfs)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
@ -66,6 +66,8 @@ from neutron_ovs_utils import (
|
||||
pause_unit_helper,
|
||||
resume_unit_helper,
|
||||
determine_purge_packages,
|
||||
install_sriov_systemd_files,
|
||||
enable_sriov,
|
||||
)
|
||||
|
||||
hooks = Hooks()
|
||||
@ -100,6 +102,10 @@ def upgrade_charm():
|
||||
# migrating.
|
||||
if 'Service restart triggered' not in f.read():
|
||||
CONFIGS.write(OVS_DEFAULT)
|
||||
# Ensure that the SR-IOV systemd files are copied if a charm-upgrade
|
||||
# happens
|
||||
if enable_sriov():
|
||||
install_sriov_systemd_files()
|
||||
|
||||
|
||||
@hooks.hook('neutron-plugin-relation-changed')
|
||||
@ -148,7 +154,7 @@ def neutron_plugin_api_changed():
|
||||
# per 17.08 release notes L3HA + DVR is a Newton+ feature
|
||||
_os_release = os_release('neutron-common', base='icehouse')
|
||||
if (use_l3ha() and
|
||||
CompareOpenStackReleases(_os_release) >= 'newton'):
|
||||
CompareOpenStackReleases(_os_release) >= 'newton'):
|
||||
install_l3ha_packages()
|
||||
|
||||
# NOTE(hopem): don't uninstall keepalived if not using l3ha since that
|
||||
|
@ -129,9 +129,12 @@ OVS_DEFAULT = '/etc/default/openvswitch-switch'
|
||||
DPDK_INTERFACES = '/etc/dpdk/interfaces'
|
||||
NEUTRON_SRIOV_AGENT_CONF = os.path.join(NEUTRON_CONF_DIR,
|
||||
'plugins/ml2/sriov_agent.ini')
|
||||
NEUTRON_SRIOV_INIT_SCRIPT = os.path.join('/etc/init.d',
|
||||
NEUTRON_SRIOV_INIT_SCRIPT = os.path.join('/usr/local/bin',
|
||||
'neutron-openvswitch-'
|
||||
'networking-sriov.sh')
|
||||
NEUTRON_SRIOV_INIT_PY_SCRIPT = os.path.join('/usr/local/bin',
|
||||
'neutron_openvswitch_'
|
||||
'networking_sriov.py')
|
||||
NEUTRON_SRIOV_INIT_DEFAULT = os.path.join('/etc/default',
|
||||
'neutron-openvswitch-'
|
||||
'networking-sriov')
|
||||
@ -216,14 +219,6 @@ SRIOV_RESOURCE_MAP = OrderedDict([
|
||||
'services': [],
|
||||
'contexts': [neutron_ovs_context.OVSPluginContext()],
|
||||
}),
|
||||
(NEUTRON_SRIOV_INIT_SCRIPT, {
|
||||
'services': [],
|
||||
'contexts': [],
|
||||
}),
|
||||
(NEUTRON_SRIOV_SYSTEMD_UNIT, {
|
||||
'services': [],
|
||||
'contexts': [],
|
||||
}),
|
||||
(NEUTRON_SRIOV_UPSTART_CONF, {
|
||||
'services': [],
|
||||
'contexts': [],
|
||||
@ -288,7 +283,7 @@ def determine_packages():
|
||||
_os_release = os_release('neutron-common', base='icehouse')
|
||||
# per 17.08 release notes L3HA + DVR is a Newton+ feature
|
||||
if (use_l3ha() and
|
||||
CompareOpenStackReleases(_os_release) >= 'newton'):
|
||||
CompareOpenStackReleases(_os_release) >= 'newton'):
|
||||
pkgs.extend(L3HA_PACKAGES)
|
||||
if enable_local_dhcp():
|
||||
pkgs.extend(DHCP_PACKAGES)
|
||||
@ -502,6 +497,16 @@ def install_tmpfilesd():
|
||||
subprocess.check_call(['systemd-tmpfiles', '--create'])
|
||||
|
||||
|
||||
def install_sriov_systemd_files():
|
||||
'''Install SR-IOV systemd files'''
|
||||
shutil.copy('files/neutron_openvswitch_networking_sriov.py',
|
||||
'/usr/local/bin')
|
||||
shutil.copy('files/neutron-openvswitch-networking-sriov.sh',
|
||||
'/usr/local/bin')
|
||||
shutil.copy('files/neutron-openvswitch-networking-sriov.service',
|
||||
'/lib/systemd/system')
|
||||
|
||||
|
||||
def configure_ovs():
|
||||
status_set('maintenance', 'Configuring ovs')
|
||||
if not service_running('openvswitch-switch'):
|
||||
@ -624,9 +629,8 @@ def configure_sriov():
|
||||
if not enable_sriov():
|
||||
return
|
||||
|
||||
# make sure init script has correct mode and that boot time execution
|
||||
# is enabled
|
||||
os.chmod(NEUTRON_SRIOV_INIT_SCRIPT, 0o755)
|
||||
install_sriov_systemd_files()
|
||||
# make sure that boot time execution is enabled
|
||||
service('enable', 'neutron-openvswitch-networking-sriov')
|
||||
|
||||
devices = PCINetDevices()
|
||||
|
@ -20,7 +20,7 @@ VFS_BLANKET=auto
|
||||
|
||||
# List of <device>:<numvfs> tuples for configuration of specific NICs
|
||||
#
|
||||
#VFS_LIST=ens3p0:16 ens4p0:16
|
||||
#VFS_LIST="ens3p0:16 ens4p0:16"
|
||||
{% if sriov_vfs_list -%}
|
||||
VFS_LIST="{{ sriov_vfs_list }}"
|
||||
{% endif -%}
|
||||
|
@ -6,6 +6,6 @@ start on virtual-filesystems
|
||||
task
|
||||
console log
|
||||
script
|
||||
[ -x "/etc/init.d/neutron-openvswitch-networking-sriov.sh" ] || exit 0
|
||||
exec /etc/init.d/neutron-openvswitch-networking-sriov.sh start
|
||||
[ -x "/usr/local/bin/neutron-openvswitch-networking-sriov.sh" ] || exit 0
|
||||
exec /usr/local/bin/neutron-openvswitch-networking-sriov.sh start
|
||||
end script
|
||||
|
@ -1,121 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: networking-sriov
|
||||
# Required-Start: mountkernfs $local_fs
|
||||
# Required-Stop: $local_fs
|
||||
# Default-Start: S
|
||||
# Default-Stop: 0 6
|
||||
# Short-Description: Configure SRIOV Virtual Functions
|
||||
### END INIT INFO
|
||||
|
||||
# Authors: Frode Nordahl <frode.nordahl@gmail.com>
|
||||
|
||||
DESC="Configure SRIOV Virtual Functions"
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
# Include defaults if available
|
||||
if [ -f /etc/default/neutron-openvswitch-networking-sriov ] ; then
|
||||
. /etc/default/neutron-openvswitch-networking-sriov
|
||||
fi
|
||||
|
||||
if [ -z "${ENABLE}" ]; then
|
||||
ENABLE=0
|
||||
fi
|
||||
|
||||
if [ -z "${VFS_BLANKET}" ]; then
|
||||
VFS_BLANKET=auto
|
||||
fi
|
||||
|
||||
# Exit if feature is not enabled
|
||||
[ $ENABLE -gt 0 ] || exit 0
|
||||
|
||||
do_wait_for_vfs() {
|
||||
# Wait for VFs to be created
|
||||
PCI_DEVICE_PATH=$1
|
||||
NUMVFS=$2
|
||||
[ -z "${DEBUG}" ] || echo "do_wait_for_vfs ${PCI_DEVICE_PATH} ${NUMVFS}"
|
||||
while [ `ls -1 "${PCI_DEVICE_PATH}/" | wc -l` -lt "${NUMVFS}" ]; do
|
||||
[ -z "${DEBUG}" ] || echo wait...
|
||||
sleep 0.05
|
||||
done
|
||||
}
|
||||
|
||||
do_configure_vfs() {
|
||||
if [ ! -z "${VFS_LIST}" ]; then
|
||||
# Do configuration according to list of <device>:<numvfs> tuples
|
||||
OIFS="$IFS"
|
||||
echo "${VFS_LIST}" | \
|
||||
while IFS=':' read DEVICE NUMVFS; do
|
||||
# Check whether we should stop
|
||||
[ -z "${STOP}" ] || NUMVFS=0
|
||||
[ -z "${DEBUG}" ] || echo "echo ${NUMVFS} \> /sys/class/net/${DEVICE}/device/sriov_numvfs"
|
||||
echo "${NUMVFS}" > "/sys/class/net/${DEVICE}/device/sriov_numvfs"
|
||||
do_wait_for_vfs "/sys/class/net/${DEVICE}/device" "${NUMVFS}"
|
||||
done
|
||||
IFS="$OIFS"
|
||||
else
|
||||
# Do blanket configuration
|
||||
SYSFS_LST=`find /sys/devices -name sriov_totalvfs`
|
||||
for ENT in $SYSFS_LST; do
|
||||
DENT=`dirname $ENT`
|
||||
if [ -d ${DENT}/net ]; then
|
||||
TOTALVFS=`cat "${ENT}"`
|
||||
[ -z "${STOP}" ] || VFS_BLANKET=0
|
||||
if [ "${VFS_BLANKET}" = "auto" ]; then
|
||||
# Set sriov_numvfs to value of sriov_toatlvfs for "auto"
|
||||
NUMVFS=$TOTALVFS
|
||||
elif [ "${VFS_BLANKET}" -gt "${TOTALVFS}" ]; then
|
||||
# Set sriov_numvfs to value of sriov_totalvfs if
|
||||
# requested number is larger than sriov_totalvfs
|
||||
NUMVFS=$TOTALVFS
|
||||
else
|
||||
NUMVFS=$VFS_BLANKET
|
||||
fi
|
||||
# Set sriov_numvfs to requested number
|
||||
[ -z "${DEBUG}" ] || echo "echo ${NUMVFS} \> ${DENT}/sriov_numvfs"
|
||||
echo "${NUMVFS}" > "${DENT}/sriov_numvfs"
|
||||
do_wait_for_vfs "${DENT}" "${NUMVFS}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
do_start() {
|
||||
do_configure_vfs
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
STOP=1
|
||||
do_configure_vfs
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
log_daemon_msg "$DESC"
|
||||
do_start
|
||||
;;
|
||||
stop)
|
||||
log_daemon_msg "Un-$DESC"
|
||||
do_stop
|
||||
;;
|
||||
systemd-start)
|
||||
do_start
|
||||
;;
|
||||
systemd-stop)
|
||||
do_stop
|
||||
;;
|
||||
restart)
|
||||
log_daemon_msg "Re-$DESC"
|
||||
do_stop
|
||||
do_start
|
||||
;;
|
||||
*)
|
||||
N=/etc/init.d/neutron-openvswitch-networking-sriov.sh
|
||||
echo "Usage: $N {start|stop|restart|systemd-start|systemd-stop}" >&2
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
2
tox.ini
2
tox.ini
@ -41,7 +41,7 @@ deps = -r{toxinidir}/requirements.txt
|
||||
basepython = python3
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = flake8 {posargs} hooks unit_tests tests actions lib
|
||||
commands = flake8 {posargs} hooks unit_tests tests actions lib files
|
||||
charm-proof
|
||||
|
||||
[testenv:cover]
|
||||
|
223
unit_tests/test_neutron_openvswitch_networking_sriov.py
Normal file
223
unit_tests/test_neutron_openvswitch_networking_sriov.py
Normal file
@ -0,0 +1,223 @@
|
||||
# Copyright 2019 Canonical Ltd
|
||||
#
|
||||
# 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
|
||||
|
||||
import unittest
|
||||
from unittest.mock import (
|
||||
call,
|
||||
mock_open,
|
||||
patch
|
||||
)
|
||||
import files.neutron_openvswitch_networking_sriov as net_sriov
|
||||
|
||||
|
||||
class NeutronOVSNetworkingSriovTest(unittest.TestCase):
|
||||
|
||||
def test_parse_args(self):
|
||||
results = net_sriov.parse_args(['--start'])
|
||||
self.assertEqual(results.start, True)
|
||||
results = net_sriov.parse_args(['--stop'])
|
||||
self.assertEqual(results.stop, True)
|
||||
results = net_sriov.parse_args(['--restart'])
|
||||
self.assertEqual(results.restart, True)
|
||||
args = [
|
||||
'--start',
|
||||
'--vfs',
|
||||
'eth0:8 eth1:4',
|
||||
'--vfs-blanket',
|
||||
'8'
|
||||
]
|
||||
results = net_sriov.parse_args(args)
|
||||
self.assertEqual(results.vfs, 'eth0:8 eth1:4')
|
||||
self.assertEqual(results.vfs_blanket, '8')
|
||||
|
||||
def test_parse_vfs(self):
|
||||
vfs = ''
|
||||
result = net_sriov.parse_vfs(vfs)
|
||||
expected = {}
|
||||
self.assertEqual(result, expected)
|
||||
vfs = 'eth0:8 eth1:8'
|
||||
result = net_sriov.parse_vfs(vfs)
|
||||
expected = {
|
||||
'eth0': '8',
|
||||
'eth1': '8'
|
||||
}
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.write_sriov_numvfs')
|
||||
def test_configure_vfs_with_vfs(self, m_write_vfs):
|
||||
vfs = {
|
||||
'eth0': '8'
|
||||
}
|
||||
net_sriov.configure_vfs(vfs)
|
||||
m_write_vfs.assert_called_once_with(
|
||||
'/sys/class/net/eth0/device/',
|
||||
'8'
|
||||
)
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.get_totalvfs')
|
||||
@patch('files.neutron_openvswitch_networking_sriov.find_sriov_devices')
|
||||
@patch('files.neutron_openvswitch_networking_sriov.write_sriov_numvfs')
|
||||
def test_configure_vfs_with_blanket_auto(
|
||||
self,
|
||||
m_write_vfs,
|
||||
m_find,
|
||||
m_totvfs):
|
||||
m_find.return_value = [
|
||||
'/dev/one',
|
||||
'/dev/two'
|
||||
]
|
||||
m_totvfs.return_value = '8'
|
||||
net_sriov.configure_vfs({}, 'auto')
|
||||
m_write_vfs.assert_has_calls([
|
||||
call('/dev/one', '8'),
|
||||
call('/dev/two', '8')
|
||||
])
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.get_totalvfs')
|
||||
@patch('files.neutron_openvswitch_networking_sriov.find_sriov_devices')
|
||||
@patch('files.neutron_openvswitch_networking_sriov.write_sriov_numvfs')
|
||||
def test_configure_vfs_with_blanket_too_big(
|
||||
self,
|
||||
m_write_vfs,
|
||||
m_find,
|
||||
m_totvfs):
|
||||
m_find.return_value = [
|
||||
'/dev/one',
|
||||
'/dev/two'
|
||||
]
|
||||
m_totvfs.return_value = '2'
|
||||
net_sriov.configure_vfs({}, '8')
|
||||
m_write_vfs.assert_has_calls([
|
||||
call('/dev/one', '2'),
|
||||
call('/dev/two', '2')
|
||||
])
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.get_totalvfs')
|
||||
@patch('files.neutron_openvswitch_networking_sriov.find_sriov_devices')
|
||||
@patch('files.neutron_openvswitch_networking_sriov.write_sriov_numvfs')
|
||||
def test_configure_vfs_with_blanket_smaller_than_totalvfs(
|
||||
self,
|
||||
m_write_vfs,
|
||||
m_find,
|
||||
m_totvfs):
|
||||
m_find.return_value = [
|
||||
'/dev/one',
|
||||
'/dev/two'
|
||||
]
|
||||
m_totvfs.return_value = '8'
|
||||
net_sriov.configure_vfs({}, '2')
|
||||
m_write_vfs.assert_has_calls([
|
||||
call('/dev/one', '2'),
|
||||
call('/dev/two', '2')
|
||||
])
|
||||
|
||||
@patch('time.sleep')
|
||||
@patch('os.listdir')
|
||||
def test_wait_for_vfs(self, m_listdir, m_sleep):
|
||||
dev_list = [
|
||||
'subsystem_device',
|
||||
'subsystem_vendor',
|
||||
'uevent',
|
||||
'vendor',
|
||||
'virtfn0',
|
||||
'virtfn1',
|
||||
'virtfn2',
|
||||
'virtfn3',
|
||||
]
|
||||
m_listdir.return_value = dev_list
|
||||
net_sriov.wait_for_vfs('dev', '4')
|
||||
m_sleep.assert_called_once_with(0.05)
|
||||
|
||||
@patch('os.walk')
|
||||
def test_find_sriov_devices(self, m_walk):
|
||||
m_walk.return_value = [
|
||||
('/one', ('dir1', 'dir2'), ('file')),
|
||||
('/one/dir1', (), ('sriov_totalvfs')),
|
||||
('/one/dir2', (), ('sriov_totalvfs'))
|
||||
]
|
||||
results = net_sriov.find_sriov_devices()
|
||||
expected = [
|
||||
'/one/dir1',
|
||||
'/one/dir2'
|
||||
]
|
||||
self.assertEqual(results, expected)
|
||||
|
||||
@patch('builtins.open', new_callable=mock_open)
|
||||
def test_get_totalvfs(self, m_open):
|
||||
net_sriov.get_totalvfs('/dev/some')
|
||||
m_open.assert_called_once_with(
|
||||
'/dev/some/sriov_totalvfs'
|
||||
)
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.wait_for_vfs')
|
||||
@patch('builtins.open', new_callable=mock_open)
|
||||
def test_write_sriov_numvfs(self, m_open, m_wait_vfs):
|
||||
net_sriov.write_sriov_numvfs('/dev/sriov', '8')
|
||||
m_open.assert_called_once_with(
|
||||
'/dev/sriov/sriov_numvfs',
|
||||
'w'
|
||||
)
|
||||
m_wait_vfs.assert_called_once_with(
|
||||
'/dev/sriov',
|
||||
'8'
|
||||
)
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.start')
|
||||
@patch('files.neutron_openvswitch_networking_sriov.stop')
|
||||
def test_restart(self, m_stop, m_start):
|
||||
net_sriov.restart([], 'auto')
|
||||
m_stop.assert_called_once_with([])
|
||||
m_start.assert_called_once_with([], 'auto')
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.configure_vfs')
|
||||
def test_start(self, m_config):
|
||||
net_sriov.start([], 'auto')
|
||||
m_config.assert_called_once_with([], 'auto')
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.configure_vfs')
|
||||
def test_stop(self, m_config):
|
||||
net_sriov.stop([])
|
||||
m_config.assert_called_once_with([], stop=True)
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.restart')
|
||||
def test_main_with_restart(self, m_restart):
|
||||
args = ['--restart', '--vfs', 'eth0:8 eth1:2', '--vfs-blanket', 'auto']
|
||||
net_sriov.main(args)
|
||||
vfs = {
|
||||
'eth0': '8',
|
||||
'eth1': '2'
|
||||
}
|
||||
vfs_blanket = 'auto'
|
||||
m_restart.assert_called_once_with(vfs, vfs_blanket)
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.start')
|
||||
def test_main_with_start(self, m_start):
|
||||
args = ['--start', '--vfs', 'eth0:8 eth1:2', '--vfs-blanket', 'auto']
|
||||
net_sriov.main(args)
|
||||
vfs = {
|
||||
'eth0': '8',
|
||||
'eth1': '2'
|
||||
}
|
||||
vfs_blanket = 'auto'
|
||||
m_start.assert_called_once_with(vfs, vfs_blanket)
|
||||
|
||||
@patch('files.neutron_openvswitch_networking_sriov.stop')
|
||||
def test_main_with_stop(self, m_stop):
|
||||
args = ['--stop', '--vfs', 'eth0:8 eth1:2', '--vfs-blanket', 'auto']
|
||||
net_sriov.main(args)
|
||||
vfs = {
|
||||
'eth0': '8',
|
||||
'eth1': '2'
|
||||
}
|
||||
m_stop.assert_called_once_with(vfs)
|
@ -75,6 +75,7 @@ class NeutronOVSHooksTests(CharmTestCase):
|
||||
self._call_hook('install')
|
||||
self.install_packages.assert_called_with()
|
||||
|
||||
@patch('neutron_ovs_hooks.enable_sriov', MagicMock(return_value=False))
|
||||
@patch.object(hooks, 'restart_map')
|
||||
@patch.object(hooks, 'restart_on_change')
|
||||
def test_migrate_ovs_default_file(self, mock_restart, mock_restart_map):
|
||||
|
@ -862,8 +862,9 @@ class TestNeutronOVSUtils(CharmTestCase):
|
||||
mock_pci_devices.get_device_from_interface_name.side_effect = \
|
||||
lambda x: self.pci_devices.get(x)
|
||||
|
||||
@patch('shutil.copy')
|
||||
@patch('os.chmod')
|
||||
def test_configure_sriov_auto(self, _os_chmod):
|
||||
def test_configure_sriov_auto(self, _os_chmod, _sh_copy):
|
||||
self.os_release.return_value = 'mitaka'
|
||||
_config = {
|
||||
'enable-sriov': True,
|
||||
@ -881,8 +882,9 @@ class TestNeutronOVSUtils(CharmTestCase):
|
||||
)
|
||||
self.assertTrue(self.remote_restart.called)
|
||||
|
||||
@patch('shutil.copy')
|
||||
@patch('os.chmod')
|
||||
def test_configure_sriov_auto_mapping(self, _os_chmod):
|
||||
def test_configure_sriov_auto_mapping(self, _os_chmod, _sh_copy):
|
||||
self.os_release.return_value = 'mitaka'
|
||||
_config = {
|
||||
'enable-sriov': True,
|
||||
@ -899,8 +901,9 @@ class TestNeutronOVSUtils(CharmTestCase):
|
||||
)
|
||||
self.assertTrue(self.remote_restart.called)
|
||||
|
||||
@patch('shutil.copy')
|
||||
@patch('os.chmod')
|
||||
def test_configure_sriov_numvfs(self, _os_chmod):
|
||||
def test_configure_sriov_numvfs(self, _os_chmod, _sh_copy):
|
||||
self.os_release.return_value = 'mitaka'
|
||||
_config = {
|
||||
'enable-sriov': True,
|
||||
@ -915,8 +918,9 @@ class TestNeutronOVSUtils(CharmTestCase):
|
||||
|
||||
self.assertTrue(self.remote_restart.called)
|
||||
|
||||
@patch('shutil.copy')
|
||||
@patch('os.chmod')
|
||||
def test_configure_sriov_numvfs_per_device(self, _os_chmod):
|
||||
def test_configure_sriov_numvfs_per_device(self, _os_chmod, _sh_copy):
|
||||
self.os_release.return_value = 'kilo'
|
||||
_config = {
|
||||
'enable-sriov': True,
|
||||
@ -931,8 +935,9 @@ class TestNeutronOVSUtils(CharmTestCase):
|
||||
|
||||
self.assertTrue(self.remote_restart.called)
|
||||
|
||||
@patch('shutil.copy')
|
||||
@patch('os.chmod')
|
||||
def test_configure_sriov_auto_avoid_recall(self, _os_chmod):
|
||||
def test_configure_sriov_auto_avoid_recall(self, _os_chmod, _sh_copy):
|
||||
self.os_release.return_value = 'mitaka'
|
||||
_config = {
|
||||
'enable-sriov': True,
|
||||
|
Loading…
Reference in New Issue
Block a user