From efc2734b849636f8bab5af91357a06fa6f11680b Mon Sep 17 00:00:00 2001 From: Tommaso Caiazzi Date: Tue, 3 Sep 2024 15:48:40 +0200 Subject: [PATCH 1/4] Properly configure `driver_opt` for new interfaces (#306) Co-Authored-By: Lorenzo Ariemma --- src/Kathara/manager/docker/DockerMachine.py | 48 ++++++++++++--------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/Kathara/manager/docker/DockerMachine.py b/src/Kathara/manager/docker/DockerMachine.py index 15082b84..a8c46f47 100644 --- a/src/Kathara/manager/docker/DockerMachine.py +++ b/src/Kathara/manager/docker/DockerMachine.py @@ -11,7 +11,7 @@ import docker.models.containers from docker import DockerClient from docker.errors import APIError -from docker.utils import version_lt +from docker.utils import version_lt, version_gte from .DockerImage import DockerImage from .stats.DockerMachineStats import DockerMachineStats @@ -293,8 +293,7 @@ def create(self, machine: Machine) -> None: networking_config = None if first_machine_iface: - driver_opt = {'kathara.mac_addr': first_machine_iface.mac_address} \ - if first_machine_iface.mac_address else None + driver_opt = self._create_driver_opt(machine, first_machine_iface) networking_config = { first_network.name: self.client.api.create_endpoint_config( @@ -341,8 +340,7 @@ def create(self, machine: Machine) -> None: machine.api_object = machine_container - @staticmethod - def connect_interface(machine: Machine, interface: Interface) -> None: + def connect_interface(self, machine: Machine, interface: Interface) -> None: """Connect the Docker container representing the machine to a specified collision domain. Args: @@ -359,9 +357,8 @@ def connect_interface(machine: Machine, interface: Interface) -> None: attached_networks = machine.api_object.attrs["NetworkSettings"]["Networks"] if interface.link.api_object.name not in attached_networks: + driver_opt = self._create_driver_opt(machine, interface) try: - driver_opt = {'kathara.mac_addr': interface.mac_address} if interface.mac_address else None - interface.link.api_object.connect( machine.api_object, driver_opt=driver_opt @@ -374,6 +371,28 @@ def connect_interface(machine: Machine, interface: Interface) -> None: else: raise e + def _create_driver_opt(self, machine: Machine, interface: Interface) -> dict[str, str]: + """Create a dict containing the default network driver options for a device. + + Args: + machine (Kathara.model.Machine.Machine): The Kathara device to be attached to the interface. + interface (Kathara.model.Interface.Interface): The interface to be attached to the device. + + Returns: + dict[str, str]: A dict containing the default network driver options for a device. + """ + driver_opt = {} + if version_gte(self._engine_version, "27.0.0"): + if machine.is_ipv6_enabled(): + driver_opt["com.docker.network.endpoint.sysctls"] = \ + "net.ipv6.conf.IFNAME.disable_ipv6=0,net.ipv6.conf.IFNAME.forwarding=1" + else: + driver_opt["com.docker.network.endpoint.sysctls"] = \ + "net.ipv6.conf.IFNAME.disable_ipv6=1" + if interface.mac_address: + driver_opt['kathara.mac_addr'] = interface.mac_address + return driver_opt + @staticmethod def disconnect_from_link(machine: Machine, link: Link) -> None: """Disconnect the Docker container representing the machine from a specified collision domain. @@ -427,20 +446,7 @@ def start(self, machine: Machine) -> None: f"Connecting device `{machine.name}` to collision domain `{machine_iface.link.name}` " f"on interface {iface_num}..." ) - try: - driver_opt = {'kathara.mac_addr': machine_iface.mac_address} if machine_iface.mac_address else None - - machine_iface.link.api_object.connect( - machine.api_object, - driver_opt=driver_opt - ) - except APIError as e: - if e.response.status_code == 500 and \ - ("network does not exist" in e.explanation or "endpoint does not exist" in e.explanation): - raise DockerPluginError( - "Kathara has been left in an inconsistent state! Please run `kathara wipe`.") - else: - raise e + self.connect_interface(machine, machine_iface) # Bridged connection required but not added in `deploy` method. if "bridge_connected" not in machine.meta and machine.is_bridged(): From f9a8fa7bbceac67610be42319da1dd10eaa0ec47 Mon Sep 17 00:00:00 2001 From: Tommaso Caiazzi Date: Tue, 3 Sep 2024 15:49:06 +0200 Subject: [PATCH 2/4] Add/Fix unit tests (#306) --- tests/manager/docker/docker_machine_test.py | 83 +++++++++++++++++++-- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/tests/manager/docker/docker_machine_test.py b/tests/manager/docker/docker_machine_test.py index 3928bdbf..eb2c7b4b 100644 --- a/tests/manager/docker/docker_machine_test.py +++ b/tests/manager/docker/docker_machine_test.py @@ -3,6 +3,8 @@ from unittest.mock import Mock, call import pytest +from docker.errors import APIError +from requests import Response sys.path.insert(0, './') @@ -21,6 +23,7 @@ @mock.patch("src.Kathara.manager.docker.DockerImage.DockerImage") @mock.patch("docker.DockerClient") def docker_machine(mock_docker_client, mock_docker_image): + mock_docker_client.version.return_value = {"Version": "27.0.0"} return DockerMachine(mock_docker_client, mock_docker_image) @@ -586,7 +589,10 @@ def test_start_one_mac_addr(docker_machine, default_device, default_link, defaul docker_machine.client.api.exec_inspect.assert_called_once() default_link_b.api_object.connect.assert_called_once_with( default_device.api_object, - driver_opt={'kathara.mac_addr': expected_mac_addr} + driver_opt={ + 'com.docker.network.endpoint.sysctls': 'net.ipv6.conf.IFNAME.disable_ipv6=1', + 'kathara.mac_addr': expected_mac_addr + } ) @@ -611,11 +617,17 @@ def test_start_two_mac_addr(docker_machine, default_device, default_link, defaul docker_machine.client.api.exec_inspect.assert_called_once() default_link_b.api_object.connect.assert_called_once_with( default_device.api_object, - driver_opt={'kathara.mac_addr': expected_mac_addr_1} + driver_opt={ + 'com.docker.network.endpoint.sysctls': 'net.ipv6.conf.IFNAME.disable_ipv6=1', + 'kathara.mac_addr': expected_mac_addr_1 + } ) default_link_c.api_object.connect.assert_called_once_with( default_device.api_object, - driver_opt={'kathara.mac_addr': expected_mac_addr_2} + driver_opt={ + 'com.docker.network.endpoint.sysctls': 'net.ipv6.conf.IFNAME.disable_ipv6=1', + 'kathara.mac_addr': expected_mac_addr_2 + } ) @@ -831,24 +843,83 @@ def test_connect_interface_mac_addr(docker_machine, default_device, default_link assert not default_link.api_object.connect.called default_link_b.api_object.connect.assert_called_once_with( default_device.api_object, - driver_opt={'kathara.mac_addr': expected_mac_addr} + driver_opt={ + 'com.docker.network.endpoint.sysctls': 'net.ipv6.conf.IFNAME.disable_ipv6=1', + 'kathara.mac_addr': expected_mac_addr + } ) def test_connect_interface_plugin_error_network(default_device, default_link, docker_machine): interface = default_device.add_interface(default_link) - default_link.api_object.connect.side_effect = DockerPluginError("network does not exists") + response = Response() + response.status_code = 500 + error = APIError("error", + response=response, + explanation="network does not exists") + default_link.api_object.connect.side_effect = error with pytest.raises(DockerPluginError): docker_machine.connect_interface(default_device, interface) def test_connect_interface_plugin_error_endpoint(default_device, default_link, docker_machine): interface = default_device.add_interface(default_link) - default_link.api_object.connect.side_effect = DockerPluginError("endpoint does not exists") + response = Response() + response.status_code = 500 + error = APIError("error", + response=response, + explanation="endpoint does not exists") + default_link.api_object.connect.side_effect = error with pytest.raises(DockerPluginError): docker_machine.connect_interface(default_device, interface) +def test_connect_interface_plugin_api_error(default_device, default_link, docker_machine): + interface = default_device.add_interface(default_link) + response = Response() + response.status_code = 510 + error = APIError("error", + response=response) + default_link.api_object.connect.side_effect = error + with pytest.raises(APIError): + docker_machine.connect_interface(default_device, interface) +# +# TEST:_create_driver_opt +# +def test_create_driver_opt_no_ipv6(docker_machine, default_device, default_link): + interface = default_device.add_interface(default_link) + driver_opt = docker_machine._create_driver_opt(default_device, interface) + assert driver_opt == { + 'com.docker.network.endpoint.sysctls': 'net.ipv6.conf.IFNAME.disable_ipv6=1', + } + + +def test_create_driver_opt_mac_address(docker_machine, default_device, default_link): + interface = default_device.add_interface(default_link) + interface.mac_address = '00:00:00:00:00:01' + driver_opt = docker_machine._create_driver_opt(default_device, interface) + assert driver_opt == { + 'com.docker.network.endpoint.sysctls': 'net.ipv6.conf.IFNAME.disable_ipv6=1', + 'kathara.mac_addr': '00:00:00:00:00:01' + } + + +def test_create_driver_opt_ipv6(docker_machine, default_device, default_link): + interface = default_device.add_interface(default_link) + default_device.add_meta('ipv6', True) + driver_opt = docker_machine._create_driver_opt(default_device, interface) + assert driver_opt == { + 'com.docker.network.endpoint.sysctls': 'net.ipv6.conf.IFNAME.disable_ipv6=0,net.ipv6.conf.IFNAME.forwarding=1', + } + + +def test_create_driver_old_docker(docker_machine, default_device, default_link): + docker_machine._engine_version = '25.0.0' + interface = default_device.add_interface(default_link) + driver_opt = docker_machine._create_driver_opt(default_device, interface) + assert driver_opt == {} + + # # TEST: disconnect_from_link # From b9258750790dada2fb0a655c44fda803f4ba7198 Mon Sep 17 00:00:00 2001 From: Tommaso Caiazzi Date: Tue, 3 Sep 2024 17:03:27 +0200 Subject: [PATCH 3/4] Bump version number and changelog (3.7.7) --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- SECURITY.md | 2 +- pyproject.toml | 2 +- scripts/Linux-Deb/Makefile | 2 +- scripts/Linux-Deb/debian/changelog | 3 +-- scripts/Linux-Pkg/Makefile | 2 +- scripts/Linux-Pkg/pkginfo/kathara.changelog | 3 +-- scripts/Linux-Rpm/Makefile | 2 +- scripts/Linux-Rpm/rpm/kathara.spec | 3 +-- scripts/OSX/Makefile | 2 +- scripts/Windows/installer.iss | 2 +- setup.cfg | 2 +- setup.py | 4 ++-- src/Kathara/version.py | 2 +- 14 files changed, 15 insertions(+), 18 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 471f0132..3482de4f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -22,7 +22,7 @@ body: attributes: label: KatharĂ¡ Version description: "Please provide the KatharĂ¡ version you are using (`kathara -v`)." - placeholder: "3.7.6" + placeholder: "3.7.7" validations: required: true - type: textarea diff --git a/SECURITY.md b/SECURITY.md index 510efe98..c82bc870 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,7 @@ We release patches for security vulnerabilities only for the last version: | Version | Supported Versions | |---------|--------------------| -| 3.7.6 | :white_check_mark: | +| 3.7.7 | :white_check_mark: | ## Reporting a Vulnerability diff --git a/pyproject.toml b/pyproject.toml index 0cfb3f6e..c2c9a479 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kathara" -version = "3.7.6" +version = "3.7.7" description = "A lightweight container-based network emulation tool." readme = "README.md" requires-python = ">=3.9" diff --git a/scripts/Linux-Deb/Makefile b/scripts/Linux-Deb/Makefile index e610912c..7ae1958e 100644 --- a/scripts/Linux-Deb/Makefile +++ b/scripts/Linux-Deb/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f -VERSION=3.7.6 +VERSION=3.7.7 DEBIAN_PACKAGE_VERSION=1 LAUNCHPAD_NAME=user NO_BINARY_PACKAGES=pyroute2|pyuv|deepdiff diff --git a/scripts/Linux-Deb/debian/changelog b/scripts/Linux-Deb/debian/changelog index d17a887d..0e63c497 100644 --- a/scripts/Linux-Deb/debian/changelog +++ b/scripts/Linux-Deb/debian/changelog @@ -1,7 +1,6 @@ kathara (__VERSION__-__DEBIAN_PACKAGE_VERSION____UBUNTU_VERSION__) __UBUNTU_VERSION__; urgency=low - * Fix IPv6 disabling issue - * Add the possibility to exclude machines while deploying a network scenario, both from CLI and Python APIs + * Properly set driver options to disable/enable IPV6 * Minor fixes -- Kathara Team __DATE__ diff --git a/scripts/Linux-Pkg/Makefile b/scripts/Linux-Pkg/Makefile index 5aaa156e..010c61bc 100644 --- a/scripts/Linux-Pkg/Makefile +++ b/scripts/Linux-Pkg/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f -VERSION=3.7.6 +VERSION=3.7.7 PACKAGE_VERSION=1 AUR_NAME=user AUR_MAIL=contact@kathara.org diff --git a/scripts/Linux-Pkg/pkginfo/kathara.changelog b/scripts/Linux-Pkg/pkginfo/kathara.changelog index 65885a81..0708e5f3 100644 --- a/scripts/Linux-Pkg/pkginfo/kathara.changelog +++ b/scripts/Linux-Pkg/pkginfo/kathara.changelog @@ -1,6 +1,5 @@ __DATE__ Kathara Team <******@kathara.org> * Release v__VERSION__ - * Fix IPv6 disabling issue - * Add the possibility to exclude machines while deploying a network scenario, both from CLI and Python APIs + * Properly set driver options to disable/enable IPV6 * Minor fixes \ No newline at end of file diff --git a/scripts/Linux-Rpm/Makefile b/scripts/Linux-Rpm/Makefile index dc766274..d4dac322 100644 --- a/scripts/Linux-Rpm/Makefile +++ b/scripts/Linux-Rpm/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/make -f -VERSION=3.7.6 +VERSION=3.7.7 PACKAGE_VERSION=1 .PHONY: all clean docker-build-image prepare-source prepare-man-pages prepare-bash-completion pack-source build diff --git a/scripts/Linux-Rpm/rpm/kathara.spec b/scripts/Linux-Rpm/rpm/kathara.spec index 68eceb74..b35e34d9 100644 --- a/scripts/Linux-Rpm/rpm/kathara.spec +++ b/scripts/Linux-Rpm/rpm/kathara.spec @@ -68,6 +68,5 @@ chmod g+s %{_libdir}/kathara/kathara %changelog * __DATE__ Kathara Team <******@kathara.org> - __VERSION__-__PACKAGE_VERSION__ -- Fix IPv6 disabling issue -- Add the possibility to exclude machines while deploying a network scenario, both from CLI and Python APIs +- Properly set driver options to disable/enable IPV6 - Minor fixes \ No newline at end of file diff --git a/scripts/OSX/Makefile b/scripts/OSX/Makefile index 44ccbcb5..47009793 100644 --- a/scripts/OSX/Makefile +++ b/scripts/OSX/Makefile @@ -1,7 +1,7 @@ #!/usr/bin/make -s PRODUCT=Kathara -VERSION=3.7.6 +VERSION=3.7.7 TARGET_DIRECTORY=Output APPLE_DEVELOPER_CERTIFICATE_ID=FakeID ROFF_DIR=../../docs/Roff diff --git a/scripts/Windows/installer.iss b/scripts/Windows/installer.iss index e9af5849..100f61a3 100644 --- a/scripts/Windows/installer.iss +++ b/scripts/Windows/installer.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "Kathara" -#define MyAppVersion "3.7.6" +#define MyAppVersion "3.7.7" #define MyAppPublisher "Kathara Team" #define MyAppURL "https://www.kathara.org" #define MyAppExeName "kathara.exe" diff --git a/setup.cfg b/setup.cfg index a185c702..7499ba28 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = kathara -version = 3.7.6 +version = 3.7.7 author = Kathara Framework author_email = contact@kathara.org description = A lightweight container-based network emulation tool. diff --git a/setup.py b/setup.py index 94443330..57215c78 100644 --- a/setup.py +++ b/setup.py @@ -7,13 +7,13 @@ package_dir={'': 'src'}, packages=find_packages('src'), py_modules=['kathara'], - version='3.7.6', + version='3.7.7', license='gpl-3.0', description='A lightweight container-based network emulation tool.', author='Kathara Framework', author_email='contact@kathara.org', url='https://www.kathara.org', - download_url='https://github.com/KatharaFramework/Kathara/archive/refs/tags/3.7.6.tar.gz', + download_url='https://github.com/KatharaFramework/Kathara/archive/refs/tags/3.7.7.tar.gz', keywords=['NETWORK-EMULATION', 'CONTAINERS', 'NFV'], install_requires=[ "binaryornot>=0.4.4", diff --git a/src/Kathara/version.py b/src/Kathara/version.py index 22a59e8c..f7dacb0b 100644 --- a/src/Kathara/version.py +++ b/src/Kathara/version.py @@ -1,6 +1,6 @@ from typing import Tuple -CURRENT_VERSION = "3.7.6" +CURRENT_VERSION = "3.7.7" def parse(version: str) -> Tuple: From 5c68b3acd3a0d3a7668fd74a8fee58ddd109cd77 Mon Sep 17 00:00:00 2001 From: Tommaso Caiazzi Date: Tue, 3 Sep 2024 17:22:14 +0200 Subject: [PATCH 4/4] Fix compilation for Windows Fix pyinstaller version to "6.9.0" --- scripts/Windows/WindowsBuild.bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Windows/WindowsBuild.bat b/scripts/Windows/WindowsBuild.bat index 5aaea2cd..a77b5ae1 100644 --- a/scripts/Windows/WindowsBuild.bat +++ b/scripts/Windows/WindowsBuild.bat @@ -7,8 +7,8 @@ if %errorlevel% neq 0 exit /b %errorlevel% CALL %VENV_DIR%\Scripts\activate if %errorlevel% neq 0 exit /b %errorlevel% -pip install win_inet_pton -pip install pyinstaller +pip install win_inet_ptonkat +pip install pyinstaller==6.9.0 pip install -r ..\..\src\requirements.txt pip install pytest if %errorlevel% neq 0 exit /b %errorlevel%