os-vif 4.2.0__tar.gz → 4.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of os-vif might be problematic. Click here for more details.
- {os_vif-4.2.0 → os_vif-4.3.0}/.zuul.yaml +0 -12
- {os_vif-4.2.0 → os_vif-4.3.0}/AUTHORS +3 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/ChangeLog +15 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/PKG-INFO +11 -2
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/internal/ip/ip_command.py +6 -2
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/internal/ip/linux/impl_pyroute2.py +10 -1
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/vif.py +25 -5
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/functional/internal/command/ip/test_impl_pyroute2.py +111 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/internal/ip/linux/test_impl_pyroute2.py +66 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/test_objects.py +60 -3
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif.egg-info/PKG-INFO +11 -2
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif.egg-info/SOURCES.txt +2 -0
- os_vif-4.3.0/os_vif.egg-info/pbr.json +1 -0
- os_vif-4.3.0/releasenotes/notes/add-tap-creation-support-2069718-abc123.yaml +24 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/2024.1.rst +1 -1
- os_vif-4.3.0/releasenotes/source/2025.2.rst +6 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/index.rst +1 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/exception.py +6 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/linux_net.py +23 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/ovs.py +58 -1
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/functional/ovsdb/test_ovsdb_lib.py +1 -6
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/functional/test_plugin.py +57 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/unit/test_linux_net.py +44 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/unit/test_plugin.py +266 -0
- os_vif-4.2.0/os_vif.egg-info/pbr.json +0 -1
- {os_vif-4.2.0 → os_vif-4.3.0}/.coveragerc +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/.mailmap +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/.pre-commit-config.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/.stestr.conf +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/CONTRIBUTING.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/HACKING.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/LICENSE +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/README.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/bindep.txt +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/requirements.txt +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/conf.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/contributor/contributing.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/index.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/reference/glossary.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/user/host-info.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/user/plugins/linux-bridge.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/user/plugins/noop.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/user/plugins/ovs.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/user/usage.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/doc/source/user/vif-types.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/exception.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/i18n.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/internal/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/internal/ip/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/internal/ip/api.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/internal/ip/linux/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/base.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/fields.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/fixed_ip.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/host_info.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/instance_info.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/network.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/route.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/objects/subnet.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/opts.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/plugin.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/functional/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/functional/base.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/functional/internal/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/functional/internal/command/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/functional/internal/command/ip/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/functional/privsep.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/base.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/internal/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/internal/ip/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/internal/ip/linux/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/internal/ip/test_api.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/test_base.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/test_exception.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/test_host_info.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/test_os_vif.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/unit/test_vif.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/utils.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif/version.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif.egg-info/dependency_links.txt +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif.egg-info/entry_points.txt +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif.egg-info/not-zip-safe +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif.egg-info/requires.txt +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/os_vif.egg-info/top_level.txt +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/playbooks/openstack-tox-functional-ovs-with-sudo/Debian.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/playbooks/openstack-tox-functional-ovs-with-sudo/Gentoo.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/playbooks/openstack-tox-functional-ovs-with-sudo/RedHat.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/playbooks/openstack-tox-functional-ovs-with-sudo/Suse.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/playbooks/openstack-tox-functional-ovs-with-sudo/pre.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/pyproject.toml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/OVSVif-hybrid-unplug-f37bf57bc8e913de.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/add-abstract-ovsdb-api-8f04df58d4ed5b73.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/add-fast-path-vhostuser-support-fe87e558326909b6.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/add-no-op-plugin-763a6703e7328a24.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/add-ovs-representor-portprofile-5f8290e5a40bf0a4.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/add-ovs-vhostuser-support-2ba8de51c1f3a244.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/add-ovsdb-native-322fffb49c91503d.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/always-plug-vifs-for-ovs-1d033fc49a9c6c4e.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/brctl-removal-a5b0e69b865afa57.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/bug-1892132-812e6d5ce0588ebb.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/contextlib-and-nested-with-statements-2747a9ebb9a5bfd7.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/default-qos-policy-for-ovs-26f8806046a59c82.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/default-to-native-ovsdb-driver-112fb5adf6e19a30.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/deprecate-linuxbridge-support-d278d4bbdff8e8bc.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/deprecate-windows-support-49f5ca1b1a1f4d66.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/do-not-force-mac-ageing-c6e8d750130c5740.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/drop-py36-support-0e9b07073f6ad73f.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/drop-python2-support-7a4bc7d31253c1e5.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/ensure-ovs-bridge-a0c1b51f469c92d0.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/extend-vhostuser-object-fada14a1457d4e56.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/fix-broken-dataplane-on-nova-restart-with-isolate_vif-71617a41741b33e8.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/fix-ovs-plugin-describe-049750609559f1ba.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/fix-stevedore-entrypoints-8002ec7a5166c977.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/fix-vif-openvswitch-fa0d19be9dd668e1.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/generic-datapath-offloads-41cabb6842b41533.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/initial-release-2c71d6bbf55f763b.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/oslo-config-opts-entrypoints-e83f907b686d774a.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/per-port-bridge-c6a50179a0256de3.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/port-profile-info-linux-bridge-4800f5a0b7328615.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/port-profile-info-ovs-63b46a3eafc11de2.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/prevent-lb-reply-arp-6459133bfb056069.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/remove-py38-e0701b3363079bbf.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/remove-windows-23df1c587d505d72.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/remove_iptools_implementation-2eb866573a680e61.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/revert-always-plug-port-for-ovs-hybrid-plug-false-dc015985cbc5443b.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/vhost-user-mtu-support-cbc7d02a6665fab1.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/notes/vhost-user-reconnect-fa4cbb731b787f71.yaml +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/2023.1.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/2023.2.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/2024.2.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/2025.1.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/_static/.placeholder +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/_templates/.placeholder +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/conf.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/newton.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/ocata.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/pike.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/queens.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/rocky.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/stein.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/train.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/unreleased.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/ussuri.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/victoria.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/wallaby.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/xena.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/yoga.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/releasenotes/source/zed.rst +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/requirements.txt +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/setup.cfg +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/setup.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/test-requirements.txt +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/tox.ini +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/constants.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/iptables.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/linux_bridge.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/linux_net.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/privsep.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/tests/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/tests/unit/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/tests/unit/test_linux_net.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_linux_bridge/tests/unit/test_plugin.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_noop/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_noop/noop.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_noop/tests/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_noop/tests/unit/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_noop/tests/unit/test_plugin.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/constants.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/ovsdb/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/ovsdb/api.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/ovsdb/impl_idl.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/ovsdb/impl_vsctl.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/ovsdb/ovsdb_lib.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/privsep.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/functional/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/functional/base.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/functional/ovsdb/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/unit/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/unit/ovsdb/__init__.py +0 -0
- {os_vif-4.2.0 → os_vif-4.3.0}/vif_plug_ovs/tests/unit/ovsdb/test_ovsdb_lib.py +0 -0
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
devstack_plugins:
|
|
27
27
|
neutron: https://opendev.org/openstack/neutron.git
|
|
28
28
|
devstack_localrc:
|
|
29
|
-
USE_PYTHON3: true
|
|
30
29
|
FORCE_CONFIG_DRIVE: true
|
|
31
30
|
ENABLE_VOLUME_MULTIATTACH: true
|
|
32
31
|
# NOTE(sean-k-mooney) we do not have to set
|
|
@@ -120,15 +119,6 @@
|
|
|
120
119
|
os_vif_ovs:
|
|
121
120
|
per_port_bridge: true
|
|
122
121
|
|
|
123
|
-
# TODO(gmann): As per the 2025.1 testing runtime, we need to run at least
|
|
124
|
-
# one job on Focal. This job can be removed in the nexy cycle (2025.2)
|
|
125
|
-
- job:
|
|
126
|
-
name: os-vif-ovn-ubuntu-jammy
|
|
127
|
-
description: |
|
|
128
|
-
os-vif ovn job (tests hybrid-plug=false) testing on Ubuntu Focal(20.04)
|
|
129
|
-
parent: os-vif-ovn
|
|
130
|
-
nodeset: openstack-single-node-jammy
|
|
131
|
-
|
|
132
122
|
- project:
|
|
133
123
|
templates:
|
|
134
124
|
- check-requirements
|
|
@@ -140,11 +130,9 @@
|
|
|
140
130
|
jobs:
|
|
141
131
|
- openstack-tox-functional-ovs-with-sudo
|
|
142
132
|
- os-vif-ovn
|
|
143
|
-
- os-vif-ovn-ubuntu-jammy
|
|
144
133
|
- os-vif-ovs-iptables
|
|
145
134
|
gate:
|
|
146
135
|
jobs:
|
|
147
136
|
- openstack-tox-functional-ovs-with-sudo
|
|
148
137
|
- os-vif-ovn
|
|
149
|
-
- os-vif-ovn-ubuntu-jammy
|
|
150
138
|
- os-vif-ovs-iptables
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
Adrian Chiris <adrianc@mellanox.com>
|
|
2
|
+
Adrien Cunin <a.cunin@syseleven.de>
|
|
2
3
|
Alin Balutoiu <abalutoiu@cloudbasesolutions.com>
|
|
3
4
|
Andreas Jaeger <aj@suse.com>
|
|
4
5
|
Balazs Gibizer <gibi@redhat.com>
|
|
5
6
|
Bence Romsics <bence.romsics@gmail.com>
|
|
7
|
+
Bodo Petermann <b.petermann@syseleven.de>
|
|
6
8
|
Brian Haley <brian.haley@hpe.com>
|
|
7
9
|
Cao Xuan Hoang <hoangcx@vn.fujitsu.com>
|
|
8
10
|
Carlos Goncalves <cgoncalves@redhat.com>
|
|
@@ -10,6 +12,7 @@ ChangBo Guo(gcb) <eric.guo@easystack.cn>
|
|
|
10
12
|
Charles Short <chucks@redhat.com>
|
|
11
13
|
Claudiu Belu <cbelu@cloudbasesolutions.com>
|
|
12
14
|
Corey Bryant <corey.bryant@canonical.com>
|
|
15
|
+
Cyril Roelandt <cyril@redhat.com>
|
|
13
16
|
Daniel P. Berrange <berrange@redhat.com>
|
|
14
17
|
Davanum Srinivas <davanum@gmail.com>
|
|
15
18
|
David Vallee Delisle <dvd@redhat.com>
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
CHANGES
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
4.3.0
|
|
5
|
+
-----
|
|
6
|
+
|
|
7
|
+
* Add TAP device pre-creation support for OVS/OVN
|
|
8
|
+
* Fixed bridge name when per\_port\_bridge is used
|
|
9
|
+
* Stabilize functional test
|
|
10
|
+
* reno: Update master for unmaintained/2024.1
|
|
11
|
+
* Update master for stable/2025.2
|
|
12
|
+
* Remove remaining job with Ubuntu Jammy (22.04)
|
|
13
|
+
|
|
14
|
+
4.2.1
|
|
15
|
+
-----
|
|
16
|
+
|
|
17
|
+
* Zuul: do not use USE\_PYTHON3
|
|
18
|
+
|
|
4
19
|
4.2.0
|
|
5
20
|
-----
|
|
6
21
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: os_vif
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3.0
|
|
4
4
|
Summary: A library for plugging and unplugging virtual interfaces in OpenStack.
|
|
5
5
|
Home-page: https://docs.openstack.org/os-vif/latest/
|
|
6
6
|
Author: OpenStack
|
|
@@ -33,6 +33,15 @@ Requires-Dist: ovsdbapp>=0.12.1
|
|
|
33
33
|
Requires-Dist: pyroute2>=0.5.2
|
|
34
34
|
Requires-Dist: stevedore>=1.20.0
|
|
35
35
|
Requires-Dist: debtcollector>=1.19.0
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: classifier
|
|
39
|
+
Dynamic: description
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
Dynamic: requires-dist
|
|
43
|
+
Dynamic: requires-python
|
|
44
|
+
Dynamic: summary
|
|
36
45
|
|
|
37
46
|
========================
|
|
38
47
|
Team and repository tags
|
|
@@ -18,6 +18,7 @@ class IpCommand(metaclass=abc.ABCMeta):
|
|
|
18
18
|
TYPE_VETH = 'veth'
|
|
19
19
|
TYPE_VLAN = 'vlan'
|
|
20
20
|
TYPE_BRIDGE = 'bridge'
|
|
21
|
+
TYPE_TUNTAP = 'tuntap'
|
|
21
22
|
|
|
22
23
|
@abc.abstractmethod
|
|
23
24
|
def set(self, device, check_exit_code=None, state=None, mtu=None,
|
|
@@ -37,11 +38,12 @@ class IpCommand(metaclass=abc.ABCMeta):
|
|
|
37
38
|
|
|
38
39
|
@abc.abstractmethod
|
|
39
40
|
def add(self, device, dev_type, check_exit_code=None, peer=None, link=None,
|
|
40
|
-
vlan_id=None, ageing=None):
|
|
41
|
+
vlan_id=None, ageing=None, mode=None, multiqueue=False):
|
|
41
42
|
"""Method to add an interface.
|
|
42
43
|
|
|
43
44
|
:param device: A network device (string)
|
|
44
|
-
:param dev_type: String network device type (TYPE_VETH, TYPE_VLAN
|
|
45
|
+
:param dev_type: String network device type (TYPE_VETH, TYPE_VLAN,
|
|
46
|
+
TYPE_BRIDGE, TYPE_TUNTAP)
|
|
45
47
|
:param check_exit_code: List of integers of allowed execution exit
|
|
46
48
|
codes
|
|
47
49
|
:param peer: String peer name, for veth interfaces
|
|
@@ -50,6 +52,8 @@ class IpCommand(metaclass=abc.ABCMeta):
|
|
|
50
52
|
:param vlan_id: Integer VLAN ID for VLAN devices
|
|
51
53
|
:param ageing: integer value in seconds before learned
|
|
52
54
|
mac addresses are forgotten.
|
|
55
|
+
:param mode: String mode for tuntap devices ('tap' or 'tun')
|
|
56
|
+
:param multiqueue: Boolean to enable multiqueue for tuntap devices
|
|
53
57
|
:return: status of the command execution
|
|
54
58
|
"""
|
|
55
59
|
|
|
@@ -74,7 +74,7 @@ class PyRoute2(ip_command.IpCommand):
|
|
|
74
74
|
return idx[0]
|
|
75
75
|
|
|
76
76
|
def add(self, device, dev_type, check_exit_code=None, peer=None, link=None,
|
|
77
|
-
vlan_id=None, ageing=None):
|
|
77
|
+
vlan_id=None, ageing=None, mode=None, multiqueue=False):
|
|
78
78
|
check_exit_code = check_exit_code or []
|
|
79
79
|
with iproute.IPRoute() as ip:
|
|
80
80
|
args = {'ifname': device,
|
|
@@ -102,6 +102,15 @@ class PyRoute2(ip_command.IpCommand):
|
|
|
102
102
|
# what policy to use and keep this code generic.
|
|
103
103
|
if ageing is not None:
|
|
104
104
|
args['IFLA_BR_AGEING_TIME'] = ageing
|
|
105
|
+
elif self.TYPE_TUNTAP == dev_type:
|
|
106
|
+
# Set mode (default to 'tap' if not specified)
|
|
107
|
+
# This matches the 'ip tuntap add' command behavior
|
|
108
|
+
tap_mode = mode if mode else 'tap'
|
|
109
|
+
args['mode'] = tap_mode
|
|
110
|
+
# Enable multiqueue if requested
|
|
111
|
+
# This sets the IFF_MULTI_QUEUE flag in IFTUN_IFR
|
|
112
|
+
if multiqueue:
|
|
113
|
+
args['multi_queue'] = True
|
|
105
114
|
else:
|
|
106
115
|
raise exception.NetworkInterfaceTypeNotDefined(type=dev_type)
|
|
107
116
|
|
|
@@ -327,7 +327,8 @@ class VIFPortProfileOpenVSwitch(VIFPortProfileBase):
|
|
|
327
327
|
# Version 1.1: Added 'datapath_type'
|
|
328
328
|
# Version 1.2: VIFPortProfileBase updated to 1.1 from 1.0
|
|
329
329
|
# Version 1.3: Added 'create_port'
|
|
330
|
-
|
|
330
|
+
# Version 1.4: Added 'create_tap' and 'multiqueue'
|
|
331
|
+
VERSION = '1.4'
|
|
331
332
|
|
|
332
333
|
fields = {
|
|
333
334
|
#: A UUID to uniquely identify the interface. If omitted one will be
|
|
@@ -342,10 +343,21 @@ class VIFPortProfileOpenVSwitch(VIFPortProfileBase):
|
|
|
342
343
|
|
|
343
344
|
#: Whether the os-vif plugin should add the port to the bridge.
|
|
344
345
|
'create_port': fields.BooleanField(default=False),
|
|
346
|
+
|
|
347
|
+
#: Whether the os-vif plugin should create the TAP device.
|
|
348
|
+
'create_tap': fields.BooleanField(default=False),
|
|
349
|
+
|
|
350
|
+
#: Whether to enable multiqueue on the TAP device.
|
|
351
|
+
'multiqueue': fields.BooleanField(default=False),
|
|
345
352
|
}
|
|
346
353
|
|
|
347
354
|
def obj_make_compatible(self, primitive, target_version):
|
|
348
355
|
target_version = versionutils.convert_version_to_tuple(target_version)
|
|
356
|
+
if target_version < (1, 4):
|
|
357
|
+
if 'create_tap' in primitive:
|
|
358
|
+
del primitive['create_tap']
|
|
359
|
+
if 'multiqueue' in primitive:
|
|
360
|
+
del primitive['multiqueue']
|
|
349
361
|
if target_version < (1, 3) and 'create_port' in primitive:
|
|
350
362
|
del primitive['create_port']
|
|
351
363
|
if target_version < (1, 1) and 'datapath_type' in primitive:
|
|
@@ -370,7 +382,8 @@ class VIFPortProfileFPOpenVSwitch(VIFPortProfileOpenVSwitch):
|
|
|
370
382
|
# Version 1.1: VIFPortProfileOpenVSwitch updated to 1.1 from 1.0
|
|
371
383
|
# Version 1.2: VIFPortProfileOpenVSwitch updated to 1.2 from 1.1
|
|
372
384
|
# Version 1.3: VIFPortProfileOpenVSwitch updated to 1.3 from 1.2
|
|
373
|
-
|
|
385
|
+
# Version 1.4: VIFPortProfileOpenVSwitch updated to 1.4 from 1.3
|
|
386
|
+
VERSION = '1.4'
|
|
374
387
|
|
|
375
388
|
fields = {
|
|
376
389
|
#: Name of the bridge (managed by fast path) to connect to.
|
|
@@ -391,9 +404,12 @@ class VIFPortProfileFPOpenVSwitch(VIFPortProfileOpenVSwitch):
|
|
|
391
404
|
elif target_version < (1, 3):
|
|
392
405
|
super(VIFPortProfileFPOpenVSwitch, self).obj_make_compatible(
|
|
393
406
|
primitive, '1.2')
|
|
394
|
-
|
|
407
|
+
elif target_version < (1, 4):
|
|
395
408
|
super(VIFPortProfileFPOpenVSwitch, self).obj_make_compatible(
|
|
396
409
|
primitive, '1.3')
|
|
410
|
+
else:
|
|
411
|
+
super(VIFPortProfileFPOpenVSwitch, self).obj_make_compatible(
|
|
412
|
+
primitive, '1.4')
|
|
397
413
|
|
|
398
414
|
|
|
399
415
|
@removals.removed_class("VIFPortProfileOVSRepresentor",
|
|
@@ -421,7 +437,8 @@ class VIFPortProfileOVSRepresentor(VIFPortProfileOpenVSwitch):
|
|
|
421
437
|
# Version 1.1: VIFPortProfileOpenVSwitch updated to 1.1 from 1.0
|
|
422
438
|
# Version 1.2: VIFPortProfileOpenVSwitch updated to 1.2 from 1.1
|
|
423
439
|
# Version 1.3: VIFPortProfileOpenVSwitch updated to 1.3 from 1.2
|
|
424
|
-
|
|
440
|
+
# Version 1.4: VIFPortProfileOpenVSwitch updated to 1.4 from 1.3
|
|
441
|
+
VERSION = '1.4'
|
|
425
442
|
|
|
426
443
|
fields = {
|
|
427
444
|
#: Name to set on the representor (if set).
|
|
@@ -442,9 +459,12 @@ class VIFPortProfileOVSRepresentor(VIFPortProfileOpenVSwitch):
|
|
|
442
459
|
elif target_version < (1, 3):
|
|
443
460
|
super(VIFPortProfileOVSRepresentor, self).obj_make_compatible(
|
|
444
461
|
primitive, '1.2')
|
|
445
|
-
|
|
462
|
+
elif target_version < (1, 4):
|
|
446
463
|
super(VIFPortProfileOVSRepresentor, self).obj_make_compatible(
|
|
447
464
|
primitive, '1.3')
|
|
465
|
+
else:
|
|
466
|
+
super(VIFPortProfileOVSRepresentor, self).obj_make_compatible(
|
|
467
|
+
primitive, '1.4')
|
|
448
468
|
|
|
449
469
|
|
|
450
470
|
@base.VersionedObjectRegistry.register
|
{os_vif-4.2.0 → os_vif-4.3.0}/os_vif/tests/functional/internal/command/ip/test_impl_pyroute2.py
RENAMED
|
@@ -81,6 +81,22 @@ class ShellIpCommands(object):
|
|
|
81
81
|
return
|
|
82
82
|
return match.group('state')
|
|
83
83
|
|
|
84
|
+
def is_admin_up(self, device):
|
|
85
|
+
"""Check if device is administratively up (UP flag set).
|
|
86
|
+
|
|
87
|
+
This differs from show_state() which returns the operational state.
|
|
88
|
+
TAP devices without a carrier will have state=DOWN but can still
|
|
89
|
+
be administratively UP (UP in flags like <NO-CARRIER,BROADCAST,UP>).
|
|
90
|
+
"""
|
|
91
|
+
# Flags are in angle brackets on the first line, e.g. <NO-CARRIER,UP>
|
|
92
|
+
first_line = self.show_device(device)[0]
|
|
93
|
+
regex = re.compile(r".*<(?P<flags>[^>]+)>")
|
|
94
|
+
match = regex.match(first_line)
|
|
95
|
+
if match is None:
|
|
96
|
+
return False
|
|
97
|
+
flags = match.group('flags').split(',')
|
|
98
|
+
return 'UP' in flags
|
|
99
|
+
|
|
84
100
|
def show_promisc(self, device):
|
|
85
101
|
regex = re.compile(r".*(PROMISC)")
|
|
86
102
|
match = regex.match(self.show_device(device)[0])
|
|
@@ -263,3 +279,98 @@ class TestIpCommand(ShellIpCommands, base.BaseFunctionalTestCase):
|
|
|
263
279
|
_ip_cmd_set(device, master=bridge)
|
|
264
280
|
path = "/sys/class/net/{}/brif/{}".format(bridge, device)
|
|
265
281
|
self.assertTrue(os.path.exists(path))
|
|
282
|
+
|
|
283
|
+
def test_add_tap(self):
|
|
284
|
+
"""Test creating a tap device."""
|
|
285
|
+
device = "test_tap_1"
|
|
286
|
+
self.addCleanup(self.del_device, device)
|
|
287
|
+
_ip_cmd_add(device, 'tuntap', mode='tap')
|
|
288
|
+
self.assertTrue(self.exist_device(device))
|
|
289
|
+
|
|
290
|
+
# Verify it's a tap device by checking /sys/class/net/<dev>/tun_flags
|
|
291
|
+
tun_flags_path = "/sys/class/net/{}/tun_flags".format(device)
|
|
292
|
+
if os.path.exists(tun_flags_path):
|
|
293
|
+
with open(tun_flags_path, 'r') as f:
|
|
294
|
+
flags_hex = f.read().strip()
|
|
295
|
+
flags = int(flags_hex, 16)
|
|
296
|
+
# IFF_TAP = 0x0002
|
|
297
|
+
IFF_TAP = 0x0002
|
|
298
|
+
self.assertTrue(flags & IFF_TAP,
|
|
299
|
+
"TAP flag not set. Flags: {}".format(flags_hex))
|
|
300
|
+
|
|
301
|
+
def test_add_tap_with_multiqueue(self):
|
|
302
|
+
"""Test creating a tap device with multiqueue parameter.
|
|
303
|
+
|
|
304
|
+
Note: The IFF_MULTI_QUEUE flag (0x0100) cannot be set via netlink.
|
|
305
|
+
It is only set when a process opens /dev/net/tun with the
|
|
306
|
+
IFF_MULTI_QUEUE flag in the ioctl. Libvirt sets this when attaching
|
|
307
|
+
to the TAP device. This test verifies that:
|
|
308
|
+
1. The TAP device can be created with multiqueue=True without error
|
|
309
|
+
2. The device is properly created as a TAP device
|
|
310
|
+
"""
|
|
311
|
+
device = "test_tap_mq"
|
|
312
|
+
self.addCleanup(self.del_device, device)
|
|
313
|
+
_ip_cmd_add(device, 'tuntap', mode='tap', multiqueue=True)
|
|
314
|
+
self.assertTrue(self.exist_device(device))
|
|
315
|
+
|
|
316
|
+
# Verify it's a tap device by checking /sys/class/net/<dev>/tun_flags
|
|
317
|
+
tun_flags_path = "/sys/class/net/{}/tun_flags".format(device)
|
|
318
|
+
if os.path.exists(tun_flags_path):
|
|
319
|
+
with open(tun_flags_path, 'r') as f:
|
|
320
|
+
flags_hex = f.read().strip()
|
|
321
|
+
flags = int(flags_hex, 16)
|
|
322
|
+
# IFF_TAP = 0x0002 - verify it's a TAP device
|
|
323
|
+
IFF_TAP = 0x0002
|
|
324
|
+
self.assertTrue(
|
|
325
|
+
flags & IFF_TAP,
|
|
326
|
+
"TAP flag not set. Flags: %s" % flags_hex)
|
|
327
|
+
|
|
328
|
+
def test_add_tap_idempotent(self):
|
|
329
|
+
"""Test tap device creation is idempotent with exit code handling."""
|
|
330
|
+
device = "test_tap_idemp"
|
|
331
|
+
self.addCleanup(self.del_device, device)
|
|
332
|
+
|
|
333
|
+
# Create the device
|
|
334
|
+
_ip_cmd_add(device, 'tuntap', mode='tap')
|
|
335
|
+
self.assertTrue(self.exist_device(device))
|
|
336
|
+
|
|
337
|
+
# Try to create again with EEXIST in check_exit_code (17)
|
|
338
|
+
# This should not raise an exception
|
|
339
|
+
_ip_cmd_add(device, 'tuntap', mode='tap', check_exit_code=[0, 17])
|
|
340
|
+
self.assertTrue(self.exist_device(device))
|
|
341
|
+
|
|
342
|
+
def test_add_tun_device(self):
|
|
343
|
+
"""Test creating a tun device (not tap)."""
|
|
344
|
+
device = "test_tun_1"
|
|
345
|
+
self.addCleanup(self.del_device, device)
|
|
346
|
+
_ip_cmd_add(device, 'tuntap', mode='tun')
|
|
347
|
+
self.assertTrue(self.exist_device(device))
|
|
348
|
+
|
|
349
|
+
# Verify it's a tun device
|
|
350
|
+
tun_flags_path = "/sys/class/net/{}/tun_flags".format(device)
|
|
351
|
+
if os.path.exists(tun_flags_path):
|
|
352
|
+
with open(tun_flags_path, 'r') as f:
|
|
353
|
+
flags_hex = f.read().strip()
|
|
354
|
+
flags = int(flags_hex, 16)
|
|
355
|
+
# IFF_TUN = 0x0001
|
|
356
|
+
IFF_TUN = 0x0001
|
|
357
|
+
self.assertTrue(flags & IFF_TUN,
|
|
358
|
+
"TUN flag not set. Flags: {}".format(flags_hex))
|
|
359
|
+
|
|
360
|
+
def test_tap_set_properties(self):
|
|
361
|
+
"""Test setting properties on a tap device."""
|
|
362
|
+
device = "test_tap_props"
|
|
363
|
+
mac = "36:a7:e4:f9:01:02"
|
|
364
|
+
self.addCleanup(self.del_device, device)
|
|
365
|
+
|
|
366
|
+
# Create tap device
|
|
367
|
+
_ip_cmd_add(device, 'tuntap', mode='tap')
|
|
368
|
+
self.assertTrue(self.exist_device(device))
|
|
369
|
+
|
|
370
|
+
# Set MAC address and state
|
|
371
|
+
_ip_cmd_set(device, address=mac, state='up')
|
|
372
|
+
# TAP devices without a carrier will show state=DOWN but should be
|
|
373
|
+
# administratively UP (UP flag in interface flags)
|
|
374
|
+
self.assertTrue(self.is_admin_up(device),
|
|
375
|
+
"Device should be administratively UP")
|
|
376
|
+
self.assertEqual(mac, self.show_mac(device))
|
|
@@ -175,3 +175,69 @@ class TestIpCommand(base.TestCase):
|
|
|
175
175
|
|
|
176
176
|
self.assertRaises(ipexc.NetlinkError, self.ip.delete, self.DEVICE,
|
|
177
177
|
check_exit_code=[self.OTHER_ERROR_CODE])
|
|
178
|
+
|
|
179
|
+
def test_add_tap(self):
|
|
180
|
+
"""Test creating a basic tap device."""
|
|
181
|
+
self.ip.add(self.DEVICE, 'tuntap', mode='tap')
|
|
182
|
+
args = {'ifname': self.DEVICE,
|
|
183
|
+
'kind': 'tuntap',
|
|
184
|
+
'mode': 'tap'}
|
|
185
|
+
self.ip_link.assert_called_once_with('add', **args)
|
|
186
|
+
|
|
187
|
+
def test_add_tap_default_mode(self):
|
|
188
|
+
"""Test creating tap device with default mode (should be 'tap')."""
|
|
189
|
+
self.ip.add(self.DEVICE, 'tuntap')
|
|
190
|
+
args = {'ifname': self.DEVICE,
|
|
191
|
+
'kind': 'tuntap',
|
|
192
|
+
'mode': 'tap'}
|
|
193
|
+
self.ip_link.assert_called_once_with('add', **args)
|
|
194
|
+
|
|
195
|
+
def test_add_tap_with_multiqueue(self):
|
|
196
|
+
"""Test creating tap device with multiqueue enabled."""
|
|
197
|
+
self.ip.add(self.DEVICE, 'tuntap', mode='tap', multiqueue=True)
|
|
198
|
+
|
|
199
|
+
# Verify the call includes multiqueue flag
|
|
200
|
+
args = {'ifname': self.DEVICE,
|
|
201
|
+
'kind': 'tuntap',
|
|
202
|
+
'mode': 'tap',
|
|
203
|
+
'multi_queue': True}
|
|
204
|
+
self.ip_link.assert_called_once_with('add', **args)
|
|
205
|
+
|
|
206
|
+
def test_add_tun_device(self):
|
|
207
|
+
"""Test creating a tun device (not tap)."""
|
|
208
|
+
self.ip.add(self.DEVICE, 'tuntap', mode='tun')
|
|
209
|
+
args = {'ifname': self.DEVICE,
|
|
210
|
+
'kind': 'tuntap',
|
|
211
|
+
'mode': 'tun'}
|
|
212
|
+
self.ip_link.assert_called_once_with('add', **args)
|
|
213
|
+
|
|
214
|
+
def test_add_tap_exit_code(self):
|
|
215
|
+
"""Test tap device creation with exit code handling."""
|
|
216
|
+
self.ip_link.side_effect = ipexc.NetlinkError(self.ERROR_CODE,
|
|
217
|
+
msg="Error message")
|
|
218
|
+
|
|
219
|
+
# Should not raise when error code matches
|
|
220
|
+
self.ip.add(self.DEVICE, 'tuntap', mode='tap',
|
|
221
|
+
check_exit_code=[self.ERROR_CODE])
|
|
222
|
+
self.ip_link.assert_called_once()
|
|
223
|
+
|
|
224
|
+
# Should raise when exit code doesn't match
|
|
225
|
+
self.assertRaises(
|
|
226
|
+
ipexc.NetlinkError,
|
|
227
|
+
self.ip.add, self.DEVICE, 'tuntap', mode='tap',
|
|
228
|
+
check_exit_code=[self.OTHER_ERROR_CODE])
|
|
229
|
+
|
|
230
|
+
def test_set_no_multiqueue_parameter(self):
|
|
231
|
+
"""Verify set() no longer accepts multiqueue parameter."""
|
|
232
|
+
with mock.patch.object(
|
|
233
|
+
iproute.IPRoute, 'link_lookup', return_value=[1],
|
|
234
|
+
create=True):
|
|
235
|
+
self.ip_link.return_value = [{'flags': 0}]
|
|
236
|
+
|
|
237
|
+
# Should work without multiqueue
|
|
238
|
+
self.ip.set(self.DEVICE, state=self.UP, mtu=self.MTU,
|
|
239
|
+
address=self.MAC)
|
|
240
|
+
|
|
241
|
+
# Should raise TypeError if multiqueue is passed
|
|
242
|
+
self.assertRaises(TypeError, self.ip.set, self.DEVICE,
|
|
243
|
+
multiqueue=True)
|
|
@@ -40,12 +40,12 @@ object_data = {
|
|
|
40
40
|
'VIFPortProfile8021Qbg': '1.1-b3011621809dca9216b50579ce9d6b19',
|
|
41
41
|
'VIFPortProfile8021Qbh': '1.1-226b61b2e76ba452f7b31530cff80ac9',
|
|
42
42
|
'VIFPortProfileBase': '1.1-4982d1621df12ebd1f3b07948f3d0e5f',
|
|
43
|
-
'VIFPortProfileOpenVSwitch': '1.
|
|
44
|
-
'VIFPortProfileFPOpenVSwitch': '1.
|
|
43
|
+
'VIFPortProfileOpenVSwitch': '1.4-54fb321f2b70c37d392fadc226c889e7',
|
|
44
|
+
'VIFPortProfileFPOpenVSwitch': '1.4-20904c1dcdac0641cabf7b02525973bd',
|
|
45
45
|
'VIFPortProfileFPBridge': '1.1-49f1952bf50bab7a95112c908534751f',
|
|
46
46
|
'VIFPortProfileFPTap': '1.1-fd178229477604dfb65de5ce929488e5',
|
|
47
47
|
'VIFVHostUser': '1.1-1f95b43be1f884f090ca1f4d79adfd35',
|
|
48
|
-
'VIFPortProfileOVSRepresentor': '1.
|
|
48
|
+
'VIFPortProfileOVSRepresentor': '1.4-82b7292ee4cd6f808b724d2f5648932b',
|
|
49
49
|
'VIFNestedDPDK': '1.0-fdbaf6b20afd116529929b21aa7158dc',
|
|
50
50
|
'VIFPortProfileK8sDPDK': '1.1-e2a2abd112b14e0239e76b99d9b252ae',
|
|
51
51
|
'DatapathOffloadBase': '1.0-77509ea1ea0dd750d5864b9bd87d3f9d',
|
|
@@ -78,3 +78,60 @@ class TestObjectVersions(base.TestCase):
|
|
|
78
78
|
self.assertIn('vif_name', primitive)
|
|
79
79
|
vif.obj_make_compatible(primitive, '1.0')
|
|
80
80
|
self.assertNotIn('vif_name', primitive)
|
|
81
|
+
|
|
82
|
+
def test_vif_port_profile_ovs_obj_make_compatible_1_4(self):
|
|
83
|
+
"""Test obj_make_compatible removes create_tap and multiqueue for
|
|
84
|
+
versions < 1.4.
|
|
85
|
+
"""
|
|
86
|
+
profile = objects.vif.VIFPortProfileOpenVSwitch(
|
|
87
|
+
interface_id='e65867e0-9340-4a7f-a256-09af6eb7a3aa',
|
|
88
|
+
create_tap=True,
|
|
89
|
+
multiqueue=True)
|
|
90
|
+
primitive = profile.obj_to_primitive()['versioned_object.data']
|
|
91
|
+
self.assertIn('create_tap', primitive)
|
|
92
|
+
self.assertIn('multiqueue', primitive)
|
|
93
|
+
|
|
94
|
+
# For version 1.3, both create_tap and multiqueue should be removed
|
|
95
|
+
profile.obj_make_compatible(primitive, '1.3')
|
|
96
|
+
self.assertNotIn('create_tap', primitive)
|
|
97
|
+
self.assertNotIn('multiqueue', primitive)
|
|
98
|
+
|
|
99
|
+
def test_vif_port_profile_ovs_obj_make_compatible_1_3(self):
|
|
100
|
+
"""Test obj_make_compatible removes create_port for versions < 1.3."""
|
|
101
|
+
profile = objects.vif.VIFPortProfileOpenVSwitch(
|
|
102
|
+
interface_id='e65867e0-9340-4a7f-a256-09af6eb7a3aa',
|
|
103
|
+
create_port=True)
|
|
104
|
+
primitive = profile.obj_to_primitive()['versioned_object.data']
|
|
105
|
+
self.assertIn('create_port', primitive)
|
|
106
|
+
|
|
107
|
+
# For version 1.2, create_port should be removed
|
|
108
|
+
profile.obj_make_compatible(primitive, '1.2')
|
|
109
|
+
self.assertNotIn('create_port', primitive)
|
|
110
|
+
|
|
111
|
+
def test_vif_port_profile_ovs_create_tap_multiqueue_fields(self):
|
|
112
|
+
"""Test that create_tap and multiqueue fields can be set."""
|
|
113
|
+
profile = objects.vif.VIFPortProfileOpenVSwitch(
|
|
114
|
+
interface_id='e65867e0-9340-4a7f-a256-09af6eb7a3aa',
|
|
115
|
+
create_tap=True,
|
|
116
|
+
multiqueue=True)
|
|
117
|
+
self.assertTrue(profile.create_tap)
|
|
118
|
+
self.assertTrue(profile.multiqueue)
|
|
119
|
+
|
|
120
|
+
# Test explicitly set default values
|
|
121
|
+
profile_default = objects.vif.VIFPortProfileOpenVSwitch(
|
|
122
|
+
interface_id='e65867e0-9340-4a7f-a256-09af6eb7a3aa',
|
|
123
|
+
create_tap=False,
|
|
124
|
+
multiqueue=False)
|
|
125
|
+
self.assertFalse(profile_default.create_tap)
|
|
126
|
+
self.assertFalse(profile_default.multiqueue)
|
|
127
|
+
|
|
128
|
+
def test_vif_port_profile_ovs_in_operator(self):
|
|
129
|
+
"""Test that 'in' operator works for checking field existence."""
|
|
130
|
+
profile = objects.vif.VIFPortProfileOpenVSwitch(
|
|
131
|
+
interface_id='e65867e0-9340-4a7f-a256-09af6eb7a3aa',
|
|
132
|
+
create_tap=True,
|
|
133
|
+
multiqueue=True)
|
|
134
|
+
self.assertIn('create_tap', profile)
|
|
135
|
+
self.assertIn('multiqueue', profile)
|
|
136
|
+
self.assertIn('interface_id', profile)
|
|
137
|
+
self.assertNotIn('nonexistent_field', profile)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: os_vif
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3.0
|
|
4
4
|
Summary: A library for plugging and unplugging virtual interfaces in OpenStack.
|
|
5
5
|
Home-page: https://docs.openstack.org/os-vif/latest/
|
|
6
6
|
Author: OpenStack
|
|
@@ -33,6 +33,15 @@ Requires-Dist: ovsdbapp>=0.12.1
|
|
|
33
33
|
Requires-Dist: pyroute2>=0.5.2
|
|
34
34
|
Requires-Dist: stevedore>=1.20.0
|
|
35
35
|
Requires-Dist: debtcollector>=1.19.0
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: classifier
|
|
39
|
+
Dynamic: description
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
Dynamic: requires-dist
|
|
43
|
+
Dynamic: requires-python
|
|
44
|
+
Dynamic: summary
|
|
36
45
|
|
|
37
46
|
========================
|
|
38
47
|
Team and repository tags
|
|
@@ -91,6 +91,7 @@ releasenotes/notes/add-no-op-plugin-763a6703e7328a24.yaml
|
|
|
91
91
|
releasenotes/notes/add-ovs-representor-portprofile-5f8290e5a40bf0a4.yaml
|
|
92
92
|
releasenotes/notes/add-ovs-vhostuser-support-2ba8de51c1f3a244.yaml
|
|
93
93
|
releasenotes/notes/add-ovsdb-native-322fffb49c91503d.yaml
|
|
94
|
+
releasenotes/notes/add-tap-creation-support-2069718-abc123.yaml
|
|
94
95
|
releasenotes/notes/always-plug-vifs-for-ovs-1d033fc49a9c6c4e.yaml
|
|
95
96
|
releasenotes/notes/brctl-removal-a5b0e69b865afa57.yaml
|
|
96
97
|
releasenotes/notes/bug-1892132-812e6d5ce0588ebb.yaml
|
|
@@ -126,6 +127,7 @@ releasenotes/source/2023.2.rst
|
|
|
126
127
|
releasenotes/source/2024.1.rst
|
|
127
128
|
releasenotes/source/2024.2.rst
|
|
128
129
|
releasenotes/source/2025.1.rst
|
|
130
|
+
releasenotes/source/2025.2.rst
|
|
129
131
|
releasenotes/source/conf.py
|
|
130
132
|
releasenotes/source/index.rst
|
|
131
133
|
releasenotes/source/newton.rst
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"git_version": "8cbe6ee", "is_release": true}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
features:
|
|
3
|
+
- |
|
|
4
|
+
Added support for os-vif to pre-create TAP devices when using OVS/OVN.
|
|
5
|
+
The ``VIFPortProfileOpenVSwitch`` object now supports two new fields:
|
|
6
|
+
|
|
7
|
+
* ``create_tap``: When set to ``True``, os-vif will create the TAP device
|
|
8
|
+
with the correct MAC address and MTU before adding it to OVS.
|
|
9
|
+
* ``multiqueue``: When set to ``True`` along with ``create_tap``, the TAP
|
|
10
|
+
device will be created with multiqueue support enabled for improved
|
|
11
|
+
performance with multiple vCPUs. The multiqueue setting is determined
|
|
12
|
+
by Nova from the ``hw:vif_multiqueue_enabled`` flavor extra spec or
|
|
13
|
+
image property.
|
|
14
|
+
|
|
15
|
+
When the ``[ovn]/ovs_create_tap`` config option is enabled in
|
|
16
|
+
Neutron's ML2/OVN mechanism driver, Neutron sets the ``ovs_create_tap``
|
|
17
|
+
flag in the vif_details during port binding. Nova then reads this value and
|
|
18
|
+
propagates it to os-vif via the ``create_tap`` field, and configures
|
|
19
|
+
libvirt with ``managed="no"`` so it uses the pre-created TAP device. This
|
|
20
|
+
reduces live migration downtime by ensuring the network is fully wired
|
|
21
|
+
before the VM starts.
|
|
22
|
+
|
|
23
|
+
See `bug 2069718 <https://bugs.launchpad.net/neutron/+bug/2069718>`_.
|
|
24
|
+
|
|
@@ -35,3 +35,9 @@ class RepresentorNotFound(osv_exception.ExceptionBase):
|
|
|
35
35
|
|
|
36
36
|
class PciDeviceNotFoundById(osv_exception.ExceptionBase):
|
|
37
37
|
msg_fmt = _("PCI device %(id)s not found")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TapCreationNotSupported(osv_exception.ExceptionBase):
|
|
41
|
+
msg_fmt = _('Tap device creation requested for unsupported VIF type. '
|
|
42
|
+
'create_tap is only supported for VIFOpenVSwitch, got '
|
|
43
|
+
'%(vif_type)s')
|
|
@@ -90,6 +90,29 @@ def update_veth_pair(dev1_name, dev2_name, mtu):
|
|
|
90
90
|
_update_device_mtu(dev, mtu)
|
|
91
91
|
|
|
92
92
|
|
|
93
|
+
@privsep.vif_plug.entrypoint
|
|
94
|
+
def create_tap(dev, mtu, mac, multiqueue=False):
|
|
95
|
+
"""Create a tap device with the specified configuration.
|
|
96
|
+
|
|
97
|
+
Creates a tap device using pyroute2's netlink interface, with optional
|
|
98
|
+
multiqueue support for better performance with multiple VCPUs.
|
|
99
|
+
|
|
100
|
+
:param dev: Device name (string)
|
|
101
|
+
:param mtu: MTU value (integer)
|
|
102
|
+
:param mac: MAC address (string)
|
|
103
|
+
:param multiqueue: Enable multiqueue support (boolean, default False)
|
|
104
|
+
Requires Linux kernel 3.8+
|
|
105
|
+
"""
|
|
106
|
+
# Create the tap device with optional multiqueue support
|
|
107
|
+
# Use check_exit_code=[0, 17] to handle EEXIST (device already exists)
|
|
108
|
+
ip_lib.add(dev, 'tuntap', mode='tap', multiqueue=multiqueue,
|
|
109
|
+
check_exit_code=[0, 17])
|
|
110
|
+
# Configure the device state and MAC address
|
|
111
|
+
ip_lib.set(dev, state='up', address=mac, check_exit_code=[0, 2, 254])
|
|
112
|
+
# Set MTU if specified
|
|
113
|
+
_update_device_mtu(dev, mtu)
|
|
114
|
+
|
|
115
|
+
|
|
93
116
|
def _disable_ipv6(bridge):
|
|
94
117
|
"""Disable ipv6 if available for bridge. Must be called from
|
|
95
118
|
privsep context.
|