1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-24 17:28:08 +00:00

Fix the nat node

Ref #686
This commit is contained in:
Julien Duponchelle 2016-09-23 17:08:05 +02:00
parent dc798dafd0
commit 79b4926cad
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
5 changed files with 50 additions and 19 deletions

View File

@ -214,8 +214,7 @@ class Cloud(BaseNode):
interface=port_info["interface"])) interface=port_info["interface"]))
elif port_info["type"] == "tap": elif port_info["type"] == "tap":
yield from self._ubridge_send('bridge add_nio_tap {name} "{interface}"'.format(name=bridge_name, yield from self._ubridge_send('bridge add_nio_tap {name} "{interface}"'.format(name=bridge_name, interface=port_info["interface"]))
interface=port_info["interface"]))
elif port_info["type"] == "udp": elif port_info["type"] == "udp":
yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name,

View File

@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys import sys
import asyncio
from .cloud import Cloud from .cloud import Cloud
from ...error import NodeError from ...error import NodeError
@ -28,15 +29,19 @@ class Nat(Cloud):
nat access to the outside nat access to the outside
""" """
_nat_id = 0
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if "virbr0" not in [interface["name"] for interface in gns3server.utils.interfaces.interfaces()]: if "virbr0" not in [interface["name"] for interface in gns3server.utils.interfaces.interfaces()]:
raise NodeError("virbr0 is missing. You need to install libvirt") raise NodeError("virbr0 is missing. You need to install libvirt")
self._interface = "gns3nat{}".format(Nat._nat_id)
Nat._nat_id += 1
ports = [ ports = [
{ {
"name": "nat0", "name": "nat0",
"type": "ethernet", "type": "tap",
"interface": "virbr0", "interface": self._interface,
"port_number": 0 "port_number": 0
} }
] ]
@ -51,6 +56,11 @@ class Nat(Cloud):
# It's not allowed to change it # It's not allowed to change it
pass pass
@asyncio.coroutine
def add_nio(self, nio, port_number):
yield from super().add_nio(nio, port_number)
yield from self._ubridge_send('brctl addif virbr0 "{interface}"'.format(interface=self._interface))
@classmethod @classmethod
def is_supported(self): def is_supported(self):
return sys.platform.startswith("linux") return sys.platform.startswith("linux")

View File

@ -120,15 +120,15 @@ class Hypervisor(UBridgeHypervisor):
@asyncio.coroutine @asyncio.coroutine
def _check_ubridge_version(self): def _check_ubridge_version(self):
""" """
Checks if the ubridge executable version is >= 0.9.4 Checks if the ubridge executable version is >= 0.9.5
""" """
try: try:
output = yield from subprocess_check_output(self._path, "-v", cwd=self._working_dir) output = yield from subprocess_check_output(self._path, "-v", cwd=self._working_dir)
match = re.search("ubridge version ([0-9a-z\.]+)", output) match = re.search("ubridge version ([0-9a-z\.]+)", output)
if match: if match:
version = match.group(1) version = match.group(1)
if parse_version(version) < parse_version("0.9.4"): if parse_version(version) < parse_version("0.9.5"):
raise UbridgeError("uBridge executable version must be >= 0.9.4") raise UbridgeError("uBridge executable version must be >= 0.9.5")
else: else:
raise UbridgeError("Could not determine uBridge version for {}".format(self._path)) raise UbridgeError("Could not determine uBridge version for {}".format(self._path))
except (OSError, subprocess.SubprocessError) as e: except (OSError, subprocess.SubprocessError) as e:

View File

@ -18,8 +18,16 @@
import uuid import uuid
import pytest import pytest
from unittest.mock import MagicMock from unittest.mock import MagicMock
from tests.utils import asyncio_patch
from gns3server.compute.builtin.nodes.nat import Nat from gns3server.compute.builtin.nodes.nat import Nat
from gns3server.compute.vpcs import VPCS
def test_init(on_gns3vm, project):
nat1 = Nat("nat1", str(uuid.uuid4()), project, MagicMock())
nat2 = Nat("nat2", str(uuid.uuid4()), project, MagicMock())
assert nat1.ports_mapping[0]["interface"] != nat2.ports_mapping[0]["interface"]
def test_json(on_gns3vm, project): def test_json(on_gns3vm, project):
@ -31,10 +39,20 @@ def test_json(on_gns3vm, project):
"status": "started", "status": "started",
"ports_mapping": [ "ports_mapping": [
{ {
"interface": "virbr0", "interface": nat._interface,
"name": "nat0", "name": "nat0",
"port_number": 0, "port_number": 0,
"type": "ethernet" "type": "tap"
} }
] ]
} }
def test_add_nio(on_gns3vm, project, async_run):
nio = VPCS.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
nat = Nat("nat1", str(uuid.uuid4()), project, MagicMock())
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.add_nio") as cloud_add_nio_mock:
with asyncio_patch("gns3server.compute.base_node.BaseNode._ubridge_send") as nat_ubridge_send_mock:
async_run(nat.add_nio(0, nio))
assert cloud_add_nio_mock.called
nat_ubridge_send_mock.assert_called_with("brctl addif virbr0 \"{}\"".format(nat._interface))

View File

@ -58,6 +58,7 @@ def test_nat_get(http_compute, project, vm):
def test_nat_nio_create_udp(http_compute, vm): def test_nat_nio_create_udp(http_compute, vm):
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.add_nio"):
response = http_compute.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp", response = http_compute.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
@ -69,11 +70,14 @@ def test_nat_nio_create_udp(http_compute, vm):
def test_nat_delete_nio(http_compute, vm): def test_nat_delete_nio(http_compute, vm):
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.add_nio"):
http_compute.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp", http_compute.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}) "rhost": "127.0.0.1"})
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.remove_nio") as mock_remove_nio:
response = http_compute.delete("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True) response = http_compute.delete("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock_remove_nio.called
assert response.status == 204 assert response.status == 204
assert response.route == "/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"