Skip to content

Commit

Permalink
Merge pull request #307 from KatharaFramework/306-cannot-enable-ipv6-…
Browse files Browse the repository at this point in the history
…docker

Kathará v3.7.7
  • Loading branch information
tcaiazzi authored Sep 6, 2024
2 parents 8f63323 + 5c68b3a commit 027865a
Show file tree
Hide file tree
Showing 17 changed files with 121 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
2 changes: 1 addition & 1 deletion scripts/Linux-Deb/Makefile
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 1 addition & 2 deletions scripts/Linux-Deb/debian/changelog
Original file line number Diff line number Diff line change
@@ -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 <[email protected]> __DATE__
2 changes: 1 addition & 1 deletion scripts/Linux-Pkg/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/make -f

VERSION=3.7.6
VERSION=3.7.7
PACKAGE_VERSION=1
AUR_NAME=user
AUR_MAIL[email protected]
Expand Down
3 changes: 1 addition & 2 deletions scripts/Linux-Pkg/pkginfo/kathara.changelog
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion scripts/Linux-Rpm/Makefile
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 1 addition & 2 deletions scripts/Linux-Rpm/rpm/kathara.spec
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion scripts/OSX/Makefile
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions scripts/Windows/WindowsBuild.bat
Original file line number Diff line number Diff line change
Expand Up @@ -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%
Expand Down
2 changes: 1 addition & 1 deletion scripts/Windows/installer.iss
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = kathara
version = 3.7.6
version = 3.7.7
author = Kathara Framework
author_email = [email protected]
description = A lightweight container-based network emulation tool.
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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='[email protected]',
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",
Expand Down
48 changes: 27 additions & 21 deletions src/Kathara/manager/docker/DockerMachine.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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():
Expand Down
2 changes: 1 addition & 1 deletion src/Kathara/version.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Tuple

CURRENT_VERSION = "3.7.6"
CURRENT_VERSION = "3.7.7"


def parse(version: str) -> Tuple:
Expand Down
83 changes: 77 additions & 6 deletions tests/manager/docker/docker_machine_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, './')

Expand All @@ -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)


Expand Down Expand Up @@ -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
}
)


Expand All @@ -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
}
)


Expand Down Expand Up @@ -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
#
Expand Down

0 comments on commit 027865a

Please sign in to comment.