mirror of
https://github.com/GNS3/gns3-server.git
synced 2024-12-18 20:37:57 +00:00
Refactor tests
* Use pytest-aiohttp * Use the async def / await syntax. * Fix tests to run with Python 3.8
This commit is contained in:
parent
f498ab06b4
commit
d3ea67da24
@ -1,6 +1,7 @@
|
||||
-rrequirements.txt
|
||||
|
||||
sphinx==1.8.3
|
||||
pytest==4.4.1
|
||||
pytest==5.4.3
|
||||
pep8==1.7.1
|
||||
pytest-timeout==1.3.3
|
||||
pytest-aiohttp==0.3.0
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -26,17 +26,20 @@ from tests.utils import asyncio_patch
|
||||
|
||||
@pytest.fixture
|
||||
def nio():
|
||||
|
||||
return NIOUDP(4242, "127.0.0.1", 4343)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager():
|
||||
|
||||
m = MagicMock()
|
||||
m.module_name = "builtins"
|
||||
return m
|
||||
|
||||
|
||||
def test_json_with_ports(on_gns3vm, project, manager):
|
||||
async def test_json_with_ports(on_gns3vm, compute_project, manager):
|
||||
|
||||
ports = [
|
||||
{
|
||||
"interface": "virbr0",
|
||||
@ -45,11 +48,11 @@ def test_json_with_ports(on_gns3vm, project, manager):
|
||||
"type": "ethernet",
|
||||
}
|
||||
]
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), project, manager, ports=ports)
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), compute_project, manager, ports=ports)
|
||||
assert cloud.__json__() == {
|
||||
"name": "cloud1",
|
||||
"node_id": cloud.id,
|
||||
"project_id": project.id,
|
||||
"project_id": compute_project.id,
|
||||
"remote_console_host": "",
|
||||
"remote_console_http_path": "/",
|
||||
"remote_console_port": 23,
|
||||
@ -72,15 +75,16 @@ def test_json_with_ports(on_gns3vm, project, manager):
|
||||
}
|
||||
|
||||
|
||||
def test_json_without_ports(on_gns3vm, project, manager):
|
||||
def test_json_without_ports(on_gns3vm, compute_project, manager):
|
||||
"""
|
||||
If no interface is provide the cloud is prefill with non special interfaces
|
||||
If no interface is provide the cloud is pre-fill with non special interfaces
|
||||
"""
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), project, manager, ports=None)
|
||||
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), compute_project, manager, ports=None)
|
||||
assert cloud.__json__() == {
|
||||
"name": "cloud1",
|
||||
"node_id": cloud.id,
|
||||
"project_id": project.id,
|
||||
"project_id": compute_project.id,
|
||||
"remote_console_host": "",
|
||||
"remote_console_http_path": "/",
|
||||
"remote_console_port": 23,
|
||||
@ -109,10 +113,11 @@ def test_json_without_ports(on_gns3vm, project, manager):
|
||||
}
|
||||
|
||||
|
||||
def test_update_port_mappings(on_gns3vm, project):
|
||||
async def test_update_port_mappings(on_gns3vm, compute_project):
|
||||
"""
|
||||
We don't allow an empty interface in the middle of port list
|
||||
"""
|
||||
|
||||
ports1 = [
|
||||
{
|
||||
"interface": "eth0",
|
||||
@ -127,7 +132,7 @@ def test_update_port_mappings(on_gns3vm, project):
|
||||
"type": "ethernet"
|
||||
}
|
||||
]
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), project, MagicMock(), ports=ports1)
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), compute_project, MagicMock(), ports=ports1)
|
||||
assert cloud.ports_mapping == ports1
|
||||
|
||||
ports2 = [
|
||||
@ -144,11 +149,11 @@ def test_update_port_mappings(on_gns3vm, project):
|
||||
"type": "ethernet"
|
||||
}
|
||||
]
|
||||
cloud = Cloud("cloud2", str(uuid.uuid4()), project, MagicMock(), ports=ports2)
|
||||
cloud = Cloud("cloud2", str(uuid.uuid4()), compute_project, MagicMock(), ports=ports2)
|
||||
assert cloud.ports_mapping == ports1
|
||||
|
||||
|
||||
def test_linux_ethernet_raw_add_nio(linux_platform, project, async_run, nio):
|
||||
async def test_linux_ethernet_raw_add_nio(linux_platform, compute_project, nio):
|
||||
ports = [
|
||||
{
|
||||
"interface": "eth0",
|
||||
@ -157,14 +162,14 @@ def test_linux_ethernet_raw_add_nio(linux_platform, project, async_run, nio):
|
||||
"type": "ethernet"
|
||||
}
|
||||
]
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), project, MagicMock(), ports=ports)
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), compute_project, MagicMock(), ports=ports)
|
||||
cloud.status = "started"
|
||||
|
||||
with patch("shutil.which", return_value="/bin/ubridge"):
|
||||
with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._ubridge_send") as ubridge_mock:
|
||||
with patch("gns3server.compute.builtin.nodes.cloud.Cloud._interfaces", return_value=[{"name": "eth0"}]):
|
||||
async_run(cloud.add_nio(nio, 0))
|
||||
await cloud.add_nio(nio, 0)
|
||||
|
||||
ubridge_mock.assert_has_calls([
|
||||
call("bridge create {}-0".format(cloud._id)),
|
||||
@ -175,7 +180,7 @@ def test_linux_ethernet_raw_add_nio(linux_platform, project, async_run, nio):
|
||||
])
|
||||
|
||||
|
||||
def test_linux_ethernet_raw_add_nio_bridge(linux_platform, project, async_run, nio):
|
||||
async def test_linux_ethernet_raw_add_nio_bridge(linux_platform, compute_project, nio):
|
||||
"""
|
||||
Bridge can't be connected directly to a cloud we use a tap in the middle
|
||||
"""
|
||||
@ -187,7 +192,7 @@ def test_linux_ethernet_raw_add_nio_bridge(linux_platform, project, async_run, n
|
||||
"type": "ethernet"
|
||||
}
|
||||
]
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), project, MagicMock(), ports=ports)
|
||||
cloud = Cloud("cloud1", str(uuid.uuid4()), compute_project, MagicMock(), ports=ports)
|
||||
cloud.status = "started"
|
||||
|
||||
with patch("shutil.which", return_value="/bin/ubridge"):
|
||||
@ -195,7 +200,7 @@ def test_linux_ethernet_raw_add_nio_bridge(linux_platform, project, async_run, n
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._ubridge_send") as ubridge_mock:
|
||||
with patch("gns3server.compute.builtin.nodes.cloud.Cloud._interfaces", return_value=[{"name": "bridge0"}]):
|
||||
with patch("gns3server.utils.interfaces.is_interface_bridge", return_value=True):
|
||||
async_run(cloud.add_nio(nio, 0))
|
||||
await cloud.add_nio(nio, 0)
|
||||
|
||||
tap = "gns3tap0-0"
|
||||
ubridge_mock.assert_has_calls([
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,18 +16,18 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import uuid
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from gns3server.compute.builtin.nodes.nat import Nat
|
||||
|
||||
|
||||
def test_json_gns3vm(on_gns3vm, project):
|
||||
nat = Nat("nat1", str(uuid.uuid4()), project, MagicMock())
|
||||
def test_json_gns3vm(on_gns3vm, compute_project):
|
||||
|
||||
nat = Nat("nat1", str(uuid.uuid4()), compute_project, MagicMock())
|
||||
assert nat.__json__() == {
|
||||
"name": "nat1",
|
||||
"node_id": nat.id,
|
||||
"project_id": project.id,
|
||||
"project_id": compute_project.id,
|
||||
"status": "started",
|
||||
"ports_mapping": [
|
||||
{
|
||||
@ -40,15 +40,16 @@ def test_json_gns3vm(on_gns3vm, project):
|
||||
}
|
||||
|
||||
|
||||
def test_json_darwin(darwin_platform, project):
|
||||
def test_json_darwin(darwin_platform, compute_project):
|
||||
|
||||
with patch("gns3server.utils.interfaces.interfaces", return_value=[
|
||||
{"name": "eth0", "special": False, "type": "ethernet"},
|
||||
{"name": "vmnet8", "special": True, "type": "ethernet"}]):
|
||||
nat = Nat("nat1", str(uuid.uuid4()), project, MagicMock())
|
||||
nat = Nat("nat1", str(uuid.uuid4()), compute_project, MagicMock())
|
||||
assert nat.__json__() == {
|
||||
"name": "nat1",
|
||||
"node_id": nat.id,
|
||||
"project_id": project.id,
|
||||
"project_id": compute_project.id,
|
||||
"status": "started",
|
||||
"ports_mapping": [
|
||||
{
|
||||
@ -78,4 +79,4 @@ def test_json_windows_with_full_name_of_interface(windows_platform, project):
|
||||
"type": "ethernet"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,7 +16,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import asyncio
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
@ -25,7 +24,8 @@ from gns3server.compute.docker.docker_error import DockerError, DockerHttp404Err
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vm():
|
||||
async def vm(loop):
|
||||
|
||||
vm = Docker()
|
||||
vm._connected = True
|
||||
vm._session = MagicMock()
|
||||
@ -33,7 +33,7 @@ def vm():
|
||||
return vm
|
||||
|
||||
|
||||
def test_query_success(loop, vm):
|
||||
async def test_query_success(vm):
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
@ -44,7 +44,7 @@ def test_query_success(loop, vm):
|
||||
|
||||
response.read.side_effect = read
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
data = loop.run_until_complete(asyncio.ensure_future(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
data = await vm.query("POST", "test", data={"a": True}, params={"b": 1})
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/v1.25/test',
|
||||
data='{"a": true}',
|
||||
@ -55,7 +55,7 @@ def test_query_success(loop, vm):
|
||||
assert data == {"c": False}
|
||||
|
||||
|
||||
def test_query_error(loop, vm):
|
||||
async def test_query_error(vm):
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 404
|
||||
@ -66,7 +66,7 @@ def test_query_error(loop, vm):
|
||||
response.read.side_effect = read
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
with pytest.raises(DockerError):
|
||||
data = loop.run_until_complete(asyncio.ensure_future(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
await vm.query("POST", "test", data={"a": True}, params={"b": 1})
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/v1.25/test',
|
||||
data='{"a": true}',
|
||||
@ -75,7 +75,7 @@ def test_query_error(loop, vm):
|
||||
timeout=300)
|
||||
|
||||
|
||||
def test_query_error_json(loop, vm):
|
||||
async def test_query_error_json(vm):
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 404
|
||||
@ -86,7 +86,7 @@ def test_query_error_json(loop, vm):
|
||||
response.read.side_effect = read
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
with pytest.raises(DockerError):
|
||||
data = loop.run_until_complete(asyncio.ensure_future(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
await vm.query("POST", "test", data={"a": True}, params={"b": 1})
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/v1.25/test',
|
||||
data='{"a": true}',
|
||||
@ -95,7 +95,8 @@ def test_query_error_json(loop, vm):
|
||||
timeout=300)
|
||||
|
||||
|
||||
def test_list_images(loop):
|
||||
async def test_list_images():
|
||||
|
||||
response = [
|
||||
{
|
||||
"RepoTags": [
|
||||
@ -123,7 +124,7 @@ def test_list_images(loop):
|
||||
]
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
images = loop.run_until_complete(asyncio.ensure_future(Docker.instance().list_images()))
|
||||
images = await Docker.instance().list_images()
|
||||
mock.assert_called_with("GET", "images/json", params={"all": 0})
|
||||
assert len(images) == 5
|
||||
assert {"image": "ubuntu:12.04"} in images
|
||||
@ -133,10 +134,11 @@ def test_list_images(loop):
|
||||
assert {"image": "ubuntu:quantal"} in images
|
||||
|
||||
|
||||
def test_pull_image(loop):
|
||||
async def test_pull_image():
|
||||
|
||||
class Response:
|
||||
"""
|
||||
Simulate a response splitted in multiple packets
|
||||
Simulate a response split in multiple packets
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
@ -156,11 +158,12 @@ def test_pull_image(loop):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", side_effect=DockerHttp404Error("404")):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.http_query", return_value=mock_query) as mock:
|
||||
images = loop.run_until_complete(asyncio.ensure_future(Docker.instance().pull_image("ubuntu")))
|
||||
await Docker.instance().pull_image("ubuntu")
|
||||
mock.assert_called_with("POST", "images/create", params={"fromImage": "ubuntu"}, timeout=None)
|
||||
|
||||
|
||||
def test_docker_check_connection_docker_minimum_version(vm, loop):
|
||||
async def test_docker_check_connection_docker_minimum_version(vm):
|
||||
|
||||
response = {
|
||||
'ApiVersion': '1.01',
|
||||
'Version': '1.12'
|
||||
@ -170,10 +173,11 @@ def test_docker_check_connection_docker_minimum_version(vm, loop):
|
||||
asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response):
|
||||
vm._connected = False
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_connection()))
|
||||
await vm._check_connection()
|
||||
|
||||
|
||||
def test_docker_check_connection_docker_preferred_version_against_newer(vm, loop):
|
||||
async def test_docker_check_connection_docker_preferred_version_against_newer(vm):
|
||||
|
||||
response = {
|
||||
'ApiVersion': '1.31'
|
||||
}
|
||||
@ -181,11 +185,12 @@ def test_docker_check_connection_docker_preferred_version_against_newer(vm, loop
|
||||
with patch("gns3server.compute.docker.Docker.connector"), \
|
||||
asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response):
|
||||
vm._connected = False
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_connection()))
|
||||
await vm._check_connection()
|
||||
assert vm._api_version == DOCKER_PREFERRED_API_VERSION
|
||||
|
||||
|
||||
def test_docker_check_connection_docker_preferred_version_against_older(vm, loop):
|
||||
async def test_docker_check_connection_docker_preferred_version_against_older(vm):
|
||||
|
||||
response = {
|
||||
'ApiVersion': '1.27',
|
||||
}
|
||||
@ -193,5 +198,5 @@ def test_docker_check_connection_docker_preferred_version_against_older(vm, loop
|
||||
with patch("gns3server.compute.docker.Docker.connector"), \
|
||||
asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response):
|
||||
vm._connected = False
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_connection()))
|
||||
assert vm._api_version == DOCKER_MINIMUM_API_VERSION
|
||||
await vm._check_connection()
|
||||
assert vm._api_version == DOCKER_MINIMUM_API_VERSION
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -21,7 +21,6 @@ import tempfile
|
||||
import sys
|
||||
import uuid
|
||||
import os
|
||||
import asyncio
|
||||
|
||||
from gns3server.compute.dynamips import Dynamips
|
||||
from gns3server.compute.dynamips.dynamips_error import DynamipsError
|
||||
@ -30,13 +29,15 @@ from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = Dynamips.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
def test_vm_invalid_dynamips_path(manager):
|
||||
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"dynamips_path": "/bin/test_fake"}):
|
||||
with pytest.raises(DynamipsError):
|
||||
manager.find_dynamips()
|
||||
@ -51,6 +52,7 @@ def test_vm_non_executable_dynamips_path(manager):
|
||||
|
||||
|
||||
def test_get_dynamips_id(manager):
|
||||
|
||||
project_1 = str(uuid.uuid4())
|
||||
project_2 = str(uuid.uuid4())
|
||||
project_3 = str(uuid.uuid4())
|
||||
@ -64,8 +66,8 @@ def test_get_dynamips_id(manager):
|
||||
|
||||
|
||||
def test_take_dynamips_id(manager):
|
||||
project_1 = str(uuid.uuid4())
|
||||
|
||||
project_1 = str(uuid.uuid4())
|
||||
manager.take_dynamips_id(project_1, 1)
|
||||
assert manager.get_dynamips_id(project_1) == 2
|
||||
with pytest.raises(DynamipsError):
|
||||
@ -73,9 +75,9 @@ def test_take_dynamips_id(manager):
|
||||
|
||||
|
||||
def test_release_dynamips_id(manager):
|
||||
|
||||
project_1 = str(uuid.uuid4())
|
||||
project_2 = str(uuid.uuid4())
|
||||
|
||||
manager.take_dynamips_id(project_1, 1)
|
||||
manager.release_dynamips_id(project_1, 1)
|
||||
assert manager.get_dynamips_id(project_1) == 1
|
||||
@ -83,45 +85,43 @@ def test_release_dynamips_id(manager):
|
||||
manager.release_dynamips_id(project_2, 0)
|
||||
|
||||
|
||||
def test_project_closed(manager, project, async_run):
|
||||
async def test_project_closed(manager, compute_project):
|
||||
|
||||
manager._dynamips_ids[project.id] = set([1, 2, 3])
|
||||
manager._dynamips_ids[compute_project.id] = set([1, 2, 3])
|
||||
|
||||
project_dir = project.module_working_path(manager.module_name.lower())
|
||||
project_dir = compute_project.module_working_path(manager.module_name.lower())
|
||||
os.makedirs(project_dir)
|
||||
open(os.path.join(project_dir, "test.ghost"), "w+").close()
|
||||
|
||||
async_run(manager.project_closed(project))
|
||||
|
||||
await manager.project_closed(compute_project)
|
||||
assert not os.path.exists(os.path.join(project_dir, "test.ghost"))
|
||||
assert project.id not in manager._dynamips_ids
|
||||
assert compute_project.id not in manager._dynamips_ids
|
||||
|
||||
|
||||
def test_duplicate_node(manager, project, async_run):
|
||||
async def test_duplicate_node(manager, compute_project):
|
||||
"""
|
||||
Duplicate dynamips do nothing it's manage outside the
|
||||
filesystem
|
||||
"""
|
||||
with asyncio_patch('gns3server.compute.dynamips.nodes.c7200.C7200.create'):
|
||||
source_node = async_run(manager.create_node(
|
||||
source_node = await manager.create_node(
|
||||
'R1',
|
||||
project.id,
|
||||
compute_project.id,
|
||||
str(uuid.uuid4()),
|
||||
platform="c7200"
|
||||
))
|
||||
destination_node = async_run(manager.create_node(
|
||||
)
|
||||
destination_node = await manager.create_node(
|
||||
'R2',
|
||||
project.id,
|
||||
compute_project.id,
|
||||
str(uuid.uuid4()),
|
||||
platform="c7200"
|
||||
))
|
||||
)
|
||||
destination_node._hypervisor = AsyncioMagicMock()
|
||||
|
||||
with open(os.path.join(source_node.working_dir, 'c3600_i1_nvram'), 'w+') as f:
|
||||
f.write("1")
|
||||
with open(source_node.startup_config_path, 'w+') as f:
|
||||
f.write('hostname R1\necho TEST')
|
||||
async_run(manager.duplicate_node(source_node.id, destination_node.id))
|
||||
await manager.duplicate_node(source_node.id, destination_node.id)
|
||||
assert not os.path.exists(os.path.join(destination_node.working_dir, 'c3600_i1_nvram'))
|
||||
with open(destination_node.startup_config_path) as f:
|
||||
content = f.read()
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -19,9 +19,7 @@ import os
|
||||
import uuid
|
||||
import pytest
|
||||
import asyncio
|
||||
import configparser
|
||||
|
||||
from unittest.mock import patch
|
||||
from gns3server.compute.dynamips.nodes.router import Router
|
||||
from gns3server.compute.dynamips.dynamips_error import DynamipsError
|
||||
from gns3server.compute.dynamips import Dynamips
|
||||
@ -29,47 +27,51 @@ from gns3server.config import Config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = Dynamips.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def router(project, manager):
|
||||
return Router("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def router(compute_project, manager):
|
||||
|
||||
return Router("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
|
||||
|
||||
def test_router(project, manager):
|
||||
router = Router("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def test_router(compute_project, manager):
|
||||
|
||||
router = Router("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
assert router.name == "test"
|
||||
assert router.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
|
||||
|
||||
def test_convert_project_before_2_0_0_b3(project, manager):
|
||||
def test_convert_project_before_2_0_0_b3(compute_project, manager):
|
||||
|
||||
node_id = str(uuid.uuid4())
|
||||
wdir = project.module_working_directory(manager.module_name.lower())
|
||||
wdir = compute_project.module_working_directory(manager.module_name.lower())
|
||||
os.makedirs(os.path.join(wdir, node_id))
|
||||
os.makedirs(os.path.join(wdir, "configs"))
|
||||
open(os.path.join(wdir, "configs", "i1_startup-config.cfg"), "w+").close()
|
||||
open(os.path.join(wdir, "configs", "i2_startup-config.cfg"), "w+").close()
|
||||
open(os.path.join(wdir, "c7200_i1_nvram"), "w+").close()
|
||||
open(os.path.join(wdir, "c7200_i2_nvram"), "w+").close()
|
||||
router = Router("test", node_id, project, manager, dynamips_id=1)
|
||||
router = Router("test", node_id, compute_project, manager, dynamips_id=1)
|
||||
assert os.path.exists(os.path.join(wdir, node_id, "configs", "i1_startup-config.cfg"))
|
||||
assert not os.path.exists(os.path.join(wdir, node_id, "configs", "i2_startup-config.cfg"))
|
||||
assert os.path.exists(os.path.join(wdir, node_id, "c7200_i1_nvram"))
|
||||
assert not os.path.exists(os.path.join(wdir, node_id, "c7200_i2_nvram"))
|
||||
|
||||
|
||||
def test_router_invalid_dynamips_path(project, manager, loop):
|
||||
async def test_router_invalid_dynamips_path(compute_project, manager):
|
||||
|
||||
config = Config.instance()
|
||||
config.set("Dynamips", "dynamips_path", "/bin/test_fake")
|
||||
config.set("Dynamips", "allocate_aux_console_ports", False)
|
||||
|
||||
with pytest.raises(DynamipsError):
|
||||
router = Router("test", "00010203-0405-0607-0809-0a0b0c0d0e0e", project, manager)
|
||||
loop.run_until_complete(asyncio.ensure_future(router.create()))
|
||||
router = Router("test", "00010203-0405-0607-0809-0a0b0c0d0e0e", compute_project, manager)
|
||||
await router.create()
|
||||
assert router.name == "test"
|
||||
assert router.id == "00010203-0405-0607-0809-0a0b0c0d0e0e"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2017 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,11 +16,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from tests.utils import AsyncioMagicMock
|
||||
#from gns3server.compute.dynamips.nodes.ethernet_switch import EthernetSwitchConsole
|
||||
from gns3server.compute.nios.nio_udp import NIOUDP
|
||||
|
||||
|
||||
def test_mac_command(async_run):
|
||||
def test_mac_command():
|
||||
|
||||
node = AsyncioMagicMock()
|
||||
node.name = "Test"
|
||||
node.nios = {}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,7 +16,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import os
|
||||
import stat
|
||||
@ -24,10 +23,10 @@ import socket
|
||||
import sys
|
||||
import uuid
|
||||
import shutil
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
|
||||
from unittest.mock import patch, MagicMock, PropertyMock, call
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
|
||||
@ -36,29 +35,29 @@ if not sys.platform.startswith("win"):
|
||||
from gns3server.compute.iou.iou_error import IOUError
|
||||
from gns3server.compute.iou import IOU
|
||||
|
||||
from gns3server.config import Config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = IOU.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(project, manager, tmpdir, fake_iou_bin, iourc_file):
|
||||
vm = IOUVM("test", str(uuid.uuid4()), project, manager, application_id=1)
|
||||
async def vm(loop, compute_project, manager, tmpdir, fake_iou_bin, iourc_file):
|
||||
|
||||
vm = IOUVM("test", str(uuid.uuid4()), compute_project, manager, application_id=1)
|
||||
config = manager.config.get_section_config("IOU")
|
||||
config["iourc_path"] = iourc_file
|
||||
manager.config.set_section_config("IOU", config)
|
||||
|
||||
vm.path = "iou.bin"
|
||||
return vm
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def iourc_file(tmpdir):
|
||||
|
||||
path = str(tmpdir / "iourc")
|
||||
with open(path, "w+") as f:
|
||||
hostname = socket.gethostname()
|
||||
@ -77,21 +76,23 @@ def fake_iou_bin(images_dir):
|
||||
return path
|
||||
|
||||
|
||||
def test_vm(project, manager):
|
||||
vm = IOUVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def test_vm(compute_project, manager):
|
||||
|
||||
vm = IOUVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
|
||||
|
||||
def test_vm_startup_config_content(project, manager):
|
||||
vm = IOUVM("test", "00010203-0405-0607-0808-0a0b0c0d0e0f", project, manager, application_id=1)
|
||||
def test_vm_startup_config_content(compute_project, manager):
|
||||
|
||||
vm = IOUVM("test", "00010203-0405-0607-0808-0a0b0c0d0e0f", compute_project, manager, application_id=1)
|
||||
vm.startup_config_content = "hostname %h"
|
||||
assert vm.name == "test"
|
||||
assert vm.startup_config_content == "hostname test"
|
||||
assert vm.id == "00010203-0405-0607-0808-0a0b0c0d0e0f"
|
||||
|
||||
|
||||
def test_start(loop, vm):
|
||||
async def test_start(vm):
|
||||
|
||||
mock_process = MagicMock()
|
||||
vm._check_requirements = AsyncioMagicMock(return_value=True)
|
||||
@ -101,7 +102,7 @@ def test_start(loop, vm):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=mock_process) as mock_exec:
|
||||
mock_process.returncode = None
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock_exec.call_args[0])
|
||||
|
||||
@ -113,7 +114,7 @@ def test_start(loop, vm):
|
||||
vm._ubridge_send.assert_any_call("iol_bridge start IOL-BRIDGE-513")
|
||||
|
||||
|
||||
def test_start_with_iourc(loop, vm, tmpdir):
|
||||
async def test_start_with_iourc(vm, tmpdir):
|
||||
|
||||
fake_file = str(tmpdir / "iourc")
|
||||
with open(fake_file, "w+") as f:
|
||||
@ -129,13 +130,13 @@ def test_start_with_iourc(loop, vm, tmpdir):
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"iourc_path": fake_file}):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=mock_process) as exec_mock:
|
||||
mock_process.returncode = None
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
arsgs, kwargs = exec_mock.call_args
|
||||
assert kwargs["env"]["IOURC"] == fake_file
|
||||
|
||||
|
||||
def test_rename_nvram_file(loop, vm):
|
||||
async def test_rename_nvram_file(vm):
|
||||
"""
|
||||
It should rename the nvram file to the correct name before launching the VM
|
||||
"""
|
||||
@ -151,9 +152,9 @@ def test_rename_nvram_file(loop, vm):
|
||||
assert os.path.exists(os.path.join(vm.working_dir, "vlan.dat-0000{}".format(vm.application_id)))
|
||||
|
||||
|
||||
def test_stop(loop, vm):
|
||||
process = MagicMock()
|
||||
async def test_stop(vm):
|
||||
|
||||
process = MagicMock()
|
||||
vm._check_requirements = AsyncioMagicMock(return_value=True)
|
||||
vm._check_iou_licence = AsyncioMagicMock(return_value=True)
|
||||
vm._start_ioucon = AsyncioMagicMock(return_value=True)
|
||||
@ -167,17 +168,17 @@ def test_stop(loop, vm):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.start()
|
||||
process.returncode = None
|
||||
assert vm.is_running()
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
await vm.stop()
|
||||
assert vm.is_running() is False
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
|
||||
def test_reload(loop, vm, fake_iou_bin):
|
||||
process = MagicMock()
|
||||
async def test_reload(vm, fake_iou_bin):
|
||||
|
||||
process = MagicMock()
|
||||
vm._check_requirements = AsyncioMagicMock(return_value=True)
|
||||
vm._check_iou_licence = AsyncioMagicMock(return_value=True)
|
||||
vm._start_ioucon = AsyncioMagicMock(return_value=True)
|
||||
@ -192,33 +193,35 @@ def test_reload(loop, vm, fake_iou_bin):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.reload()))
|
||||
await vm.reload()
|
||||
assert vm.is_running() is True
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
|
||||
def test_close(vm, port_manager, loop):
|
||||
async def test_close(vm, port_manager):
|
||||
|
||||
vm._start_ubridge = AsyncioMagicMock(return_value=True)
|
||||
vm._ubridge_send = AsyncioMagicMock()
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.start()
|
||||
port = vm.console
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
await vm.close()
|
||||
# Raise an exception if the port is not free
|
||||
port_manager.reserve_tcp_port(port, vm.project)
|
||||
assert vm.is_running() is False
|
||||
|
||||
|
||||
def test_path(vm, fake_iou_bin, config):
|
||||
|
||||
config.set_section_config("Server", {"local": True})
|
||||
vm.path = fake_iou_bin
|
||||
assert vm.path == fake_iou_bin
|
||||
|
||||
|
||||
def test_path_relative(vm, fake_iou_bin, tmpdir):
|
||||
def test_path_relative(vm, fake_iou_bin):
|
||||
|
||||
vm.path = "iou.bin"
|
||||
assert vm.path == fake_iou_bin
|
||||
@ -249,9 +252,9 @@ def test_create_netmap_config(vm):
|
||||
assert "513:15/3 1:15/3" in content
|
||||
|
||||
|
||||
def test_build_command(vm, loop):
|
||||
async def test_build_command(vm):
|
||||
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._build_command())) == [vm.path, str(vm.application_id)]
|
||||
assert await vm._build_command() == [vm.path, str(vm.application_id)]
|
||||
|
||||
|
||||
def test_get_startup_config(vm):
|
||||
@ -262,6 +265,7 @@ def test_get_startup_config(vm):
|
||||
|
||||
|
||||
def test_update_startup_config(vm):
|
||||
|
||||
content = "service timestamps debug datetime msec\nservice timestamps log datetime msec\nno service password-encryption"
|
||||
vm.startup_config_content = content
|
||||
filepath = os.path.join(vm.working_dir, "startup-config.cfg")
|
||||
@ -271,6 +275,7 @@ def test_update_startup_config(vm):
|
||||
|
||||
|
||||
def test_update_startup_config_empty(vm):
|
||||
|
||||
content = "service timestamps debug datetime msec\nservice timestamps log datetime msec\nno service password-encryption"
|
||||
vm.startup_config_content = content
|
||||
filepath = os.path.join(vm.working_dir, "startup-config.cfg")
|
||||
@ -283,6 +288,7 @@ def test_update_startup_config_empty(vm):
|
||||
|
||||
|
||||
def test_update_startup_config_content_hostname(vm):
|
||||
|
||||
content = "hostname %h\n"
|
||||
vm.name = "pc1"
|
||||
vm.startup_config_content = content
|
||||
@ -290,7 +296,8 @@ def test_update_startup_config_content_hostname(vm):
|
||||
assert f.read() == "hostname pc1\n"
|
||||
|
||||
|
||||
def test_change_name(vm, tmpdir):
|
||||
def test_change_name(vm):
|
||||
|
||||
path = os.path.join(vm.working_dir, "startup-config.cfg")
|
||||
vm.name = "world"
|
||||
with open(path, 'w+') as f:
|
||||
@ -309,50 +316,48 @@ def test_change_name(vm, tmpdir):
|
||||
assert f.read() == "no service password-encryption\nhostname charlie\nno ip icmp rate-limit unreachable"
|
||||
|
||||
|
||||
def test_library_check(loop, vm):
|
||||
async def test_library_check(vm):
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="") as mock:
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value=""):
|
||||
await vm._library_check()
|
||||
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._library_check()))
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="libssl => not found") as mock:
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="libssl => not found"):
|
||||
with pytest.raises(IOUError):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._library_check()))
|
||||
await vm._library_check()
|
||||
|
||||
|
||||
def test_enable_l1_keepalives(loop, vm):
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="***************************************************************\n\n-l Enable Layer 1 keepalive messages\n-u <n> UDP port base for distributed networks\n") as mock:
|
||||
async def test_enable_l1_keepalives(vm):
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="***************************************************************\n\n-l Enable Layer 1 keepalive messages\n-u <n> UDP port base for distributed networks\n"):
|
||||
command = ["test"]
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._enable_l1_keepalives(command)))
|
||||
await vm._enable_l1_keepalives(command)
|
||||
assert command == ["test", "-l"]
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="***************************************************************\n\n-u <n> UDP port base for distributed networks\n") as mock:
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="***************************************************************\n\n-u <n> UDP port base for distributed networks\n"):
|
||||
|
||||
command = ["test"]
|
||||
with pytest.raises(IOUError):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._enable_l1_keepalives(command)))
|
||||
await vm._enable_l1_keepalives(command)
|
||||
assert command == ["test"]
|
||||
|
||||
|
||||
def test_start_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
async def test_start_capture(vm, tmpdir, manager, free_console_port):
|
||||
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, 0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start_capture(0, 0, output_file)))
|
||||
await vm.adapter_add_nio_binding(0, 0, nio)
|
||||
await vm.start_capture(0, 0, output_file)
|
||||
assert vm._adapters[0].get_nio(0).capturing
|
||||
|
||||
|
||||
def test_stop_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
async def test_stop_capture(vm, tmpdir, manager, free_console_port):
|
||||
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, 0, nio)))
|
||||
loop.run_until_complete(vm.start_capture(0, 0, output_file))
|
||||
await vm.adapter_add_nio_binding(0, 0, nio)
|
||||
await vm.start_capture(0, 0, output_file)
|
||||
assert vm._adapters[0].get_nio(0).capturing
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop_capture(0, 0)))
|
||||
await vm.stop_capture(0, 0)
|
||||
assert vm._adapters[0].get_nio(0).capturing is False
|
||||
|
||||
|
||||
@ -361,46 +366,45 @@ def test_get_legacy_vm_workdir():
|
||||
assert IOU.get_legacy_vm_workdir(42, "bla") == "iou/device-42"
|
||||
|
||||
|
||||
def test_invalid_iou_file(loop, vm, iourc_file):
|
||||
async def test_invalid_iou_file(vm, iourc_file):
|
||||
|
||||
hostname = socket.gethostname()
|
||||
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
await vm._check_iou_licence()
|
||||
|
||||
# Missing ;
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[license]\n{} = aaaaaaaaaaaaaaaa".format(hostname))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
await vm._check_iou_licence()
|
||||
|
||||
# Key too short
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[license]\n{} = aaaaaaaaaaaaaa;".format(hostname))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
await vm._check_iou_licence()
|
||||
|
||||
# Invalid hostname
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[license]\nbla = aaaaaaaaaaaaaa;")
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
await vm._check_iou_licence()
|
||||
|
||||
# Missing licence section
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[licensetest]\n{} = aaaaaaaaaaaaaaaa;")
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
await vm._check_iou_licence()
|
||||
|
||||
# Broken config file
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[")
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
await vm._check_iou_licence()
|
||||
|
||||
# Missing file
|
||||
with pytest.raises(IOUError):
|
||||
os.remove(iourc_file)
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
await vm._check_iou_licence()
|
||||
|
||||
|
||||
def test_iourc_content(vm):
|
||||
@ -437,11 +441,11 @@ def test_extract_configs(vm):
|
||||
assert len(private_config) == 0
|
||||
|
||||
|
||||
def test_application_id(project, manager):
|
||||
def test_application_id(compute_project, manager):
|
||||
"""
|
||||
Checks if uses local manager to get application_id when not set
|
||||
"""
|
||||
vm = IOUVM("test", str(uuid.uuid4()), project, manager, application_id=1)
|
||||
vm = IOUVM("test", str(uuid.uuid4()), compute_project, manager, application_id=1)
|
||||
assert vm.application_id == 1
|
||||
|
||||
vm.application_id = 3
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -18,7 +18,6 @@
|
||||
import os
|
||||
import pytest
|
||||
import shutil
|
||||
import asyncio
|
||||
|
||||
from gns3server.compute.qemu.utils.qcow2 import Qcow2, Qcow2Error
|
||||
|
||||
@ -40,34 +39,39 @@ def qemu_img():
|
||||
|
||||
|
||||
def test_valid_base_file():
|
||||
|
||||
qcow2 = Qcow2("tests/resources/empty8G.qcow2")
|
||||
assert qcow2.version == 3
|
||||
assert qcow2.backing_file is None
|
||||
|
||||
|
||||
def test_valid_linked_file():
|
||||
|
||||
qcow2 = Qcow2("tests/resources/linked.qcow2")
|
||||
assert qcow2.version == 3
|
||||
assert qcow2.backing_file == "empty8G.qcow2"
|
||||
|
||||
|
||||
def test_invalid_file():
|
||||
|
||||
with pytest.raises(Qcow2Error):
|
||||
Qcow2("tests/resources/nvram_iou")
|
||||
|
||||
|
||||
def test_invalid_empty_file(tmpdir):
|
||||
|
||||
open(str(tmpdir / 'a'), 'w+').close()
|
||||
with pytest.raises(Qcow2Error):
|
||||
Qcow2(str(tmpdir / 'a'))
|
||||
|
||||
|
||||
@pytest.mark.skipif(qemu_img() is None, reason="qemu-img is not available")
|
||||
def test_rebase(tmpdir, loop):
|
||||
async def test_rebase(loop, tmpdir):
|
||||
|
||||
shutil.copy("tests/resources/empty8G.qcow2", str(tmpdir / "empty16G.qcow2"))
|
||||
shutil.copy("tests/resources/linked.qcow2", str(tmpdir / "linked.qcow2"))
|
||||
qcow2 = Qcow2(str(tmpdir / "linked.qcow2"))
|
||||
assert qcow2.version == 3
|
||||
assert qcow2.backing_file == "empty8G.qcow2"
|
||||
loop.run_until_complete(asyncio.ensure_future(qcow2.rebase(qemu_img(), str(tmpdir / "empty16G.qcow2"))))
|
||||
await qcow2.rebase(qemu_img(), str(tmpdir / "empty16G.qcow2"))
|
||||
assert qcow2.backing_file == str(tmpdir / "empty16G.qcow2")
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
import os
|
||||
import stat
|
||||
import asyncio
|
||||
import sys
|
||||
import pytest
|
||||
import platform
|
||||
@ -25,6 +24,7 @@ import platform
|
||||
from gns3server.compute.qemu import Qemu
|
||||
from gns3server.compute.qemu.qemu_error import QemuError
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
||||
@ -38,18 +38,19 @@ def fake_qemu_img_binary(tmpdir):
|
||||
return bin_path
|
||||
|
||||
|
||||
def test_get_qemu_version(loop):
|
||||
async def test_get_qemu_version():
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.subprocess_check_output", return_value="QEMU emulator version 2.2.0, Copyright (c) 2003-2008 Fabrice Bellard") as mock:
|
||||
version = loop.run_until_complete(asyncio.ensure_future(Qemu.get_qemu_version("/tmp/qemu-test")))
|
||||
with asyncio_patch("gns3server.compute.qemu.subprocess_check_output", return_value="QEMU emulator version 2.2.0, Copyright (c) 2003-2008 Fabrice Bellard"):
|
||||
version = await Qemu.get_qemu_version("/tmp/qemu-test")
|
||||
if sys.platform.startswith("win"):
|
||||
assert version == ""
|
||||
else:
|
||||
assert version == "2.2.0"
|
||||
|
||||
|
||||
def test_binary_list(loop):
|
||||
async def test_binary_list(monkeypatch, tmpdir):
|
||||
|
||||
monkeypatch.setenv("PATH", str(tmpdir))
|
||||
files_to_create = ["qemu-system-x86", "qemu-system-x42", "qemu-kvm", "hello", "qemu-system-x86_64-spice"]
|
||||
|
||||
for file_to_create in files_to_create:
|
||||
@ -64,7 +65,7 @@ def test_binary_list(loop):
|
||||
else:
|
||||
version = "2.2.0"
|
||||
|
||||
qemus = loop.run_until_complete(asyncio.ensure_future(Qemu.binary_list()))
|
||||
qemus = await Qemu.binary_list()
|
||||
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} in qemus
|
||||
@ -72,14 +73,14 @@ def test_binary_list(loop):
|
||||
assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86_64-spice"), "version": version} not in qemus
|
||||
|
||||
qemus = loop.run_until_complete(asyncio.ensure_future(Qemu.binary_list(["x86"])))
|
||||
qemus = await Qemu.binary_list(["x86"])
|
||||
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} not in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x42"), "version": version} not in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus
|
||||
|
||||
qemus = loop.run_until_complete(asyncio.ensure_future(Qemu.binary_list(["x86", "x42"])))
|
||||
qemus = await Qemu.binary_list(["x86", "x42"])
|
||||
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} not in qemus
|
||||
@ -87,8 +88,9 @@ def test_binary_list(loop):
|
||||
assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus
|
||||
|
||||
|
||||
def test_img_binary_list(loop):
|
||||
async def test_img_binary_list(monkeypatch, tmpdir):
|
||||
|
||||
monkeypatch.setenv("PATH", str(tmpdir))
|
||||
files_to_create = ["qemu-img", "qemu-io", "qemu-system-x86", "qemu-system-x42", "qemu-kvm", "hello"]
|
||||
|
||||
for file_to_create in files_to_create:
|
||||
@ -98,7 +100,7 @@ def test_img_binary_list(loop):
|
||||
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.subprocess_check_output", return_value="qemu-img version 2.2.0, Copyright (c) 2004-2008 Fabrice Bellard") as mock:
|
||||
qemus = loop.run_until_complete(asyncio.ensure_future(Qemu.img_binary_list()))
|
||||
qemus = await Qemu.img_binary_list()
|
||||
|
||||
version = "2.2.0"
|
||||
|
||||
@ -115,7 +117,8 @@ def test_get_legacy_vm_workdir():
|
||||
assert Qemu.get_legacy_vm_workdir(42, "bla") == os.path.join("qemu", "vm-42")
|
||||
|
||||
|
||||
def test_create_image_abs_path(loop, tmpdir, fake_qemu_img_binary):
|
||||
async def test_create_image_abs_path(tmpdir, fake_qemu_img_binary):
|
||||
|
||||
options = {
|
||||
"format": "qcow2",
|
||||
"preallocation": "metadata",
|
||||
@ -125,7 +128,7 @@ def test_create_image_abs_path(loop, tmpdir, fake_qemu_img_binary):
|
||||
"size": 100
|
||||
}
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
loop.run_until_complete(asyncio.ensure_future(Qemu.instance().create_disk(fake_qemu_img_binary, str(tmpdir / "hda.qcow2"), options)))
|
||||
await Qemu.instance().create_disk(fake_qemu_img_binary, str(tmpdir / "hda.qcow2"), options)
|
||||
args, kwargs = process.call_args
|
||||
assert args == (
|
||||
fake_qemu_img_binary,
|
||||
@ -145,14 +148,15 @@ def test_create_image_abs_path(loop, tmpdir, fake_qemu_img_binary):
|
||||
)
|
||||
|
||||
|
||||
def test_create_image_relative_path(loop, tmpdir, fake_qemu_img_binary):
|
||||
async def test_create_image_relative_path(tmpdir, fake_qemu_img_binary):
|
||||
|
||||
options = {
|
||||
"format": "raw",
|
||||
"size": 100
|
||||
}
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
with patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
loop.run_until_complete(asyncio.ensure_future(Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)))
|
||||
await Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)
|
||||
args, kwargs = process.call_args
|
||||
assert args == (
|
||||
fake_qemu_img_binary,
|
||||
@ -164,9 +168,9 @@ def test_create_image_relative_path(loop, tmpdir, fake_qemu_img_binary):
|
||||
)
|
||||
|
||||
|
||||
def test_create_image_exist(loop, tmpdir, fake_qemu_img_binary):
|
||||
open(str(tmpdir / "hda.qcow2"), "w+").close()
|
||||
async def test_create_image_exist(tmpdir, fake_qemu_img_binary):
|
||||
|
||||
open(str(tmpdir / "hda.qcow2"), "w+").close()
|
||||
options = {
|
||||
"format": "raw",
|
||||
"size": 100
|
||||
@ -174,11 +178,12 @@ def test_create_image_exist(loop, tmpdir, fake_qemu_img_binary):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
with patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
with pytest.raises(QemuError):
|
||||
loop.run_until_complete(asyncio.ensure_future(Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)))
|
||||
await Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)
|
||||
assert not process.called
|
||||
|
||||
|
||||
def test_create_image_with_not_supported_characters_by_filesystem(loop, tmpdir, fake_qemu_img_binary):
|
||||
async def test_create_image_with_not_supported_characters_by_filesystem(tmpdir, fake_qemu_img_binary):
|
||||
|
||||
open(str(tmpdir / "hda.qcow2"), "w+").close()
|
||||
|
||||
options = {
|
||||
@ -193,20 +198,19 @@ def test_create_image_with_not_supported_characters_by_filesystem(loop, tmpdir,
|
||||
patch("os.makedirs"):
|
||||
|
||||
with pytest.raises(QemuError):
|
||||
loop.run_until_complete(asyncio.ensure_future(Qemu.instance().create_disk(
|
||||
fake_qemu_img_binary, "hda.qcow2", options)))
|
||||
await Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)
|
||||
assert not process.called
|
||||
|
||||
|
||||
def test_get_kvm_archs_kvm_ok(loop):
|
||||
async def test_get_kvm_archs_kvm_ok():
|
||||
|
||||
with patch("os.path.exists", return_value=True):
|
||||
archs = loop.run_until_complete(asyncio.ensure_future(Qemu.get_kvm_archs()))
|
||||
archs = await Qemu.get_kvm_archs()
|
||||
if platform.machine() == 'x86_64':
|
||||
assert archs == ['x86_64', 'i386']
|
||||
else:
|
||||
assert archs == [platform.machine()]
|
||||
|
||||
with patch("os.path.exists", return_value=False):
|
||||
archs = loop.run_until_complete(asyncio.ensure_future(Qemu.get_kvm_archs()))
|
||||
archs = await Qemu.get_kvm_archs()
|
||||
assert archs == []
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,12 +16,10 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
import stat
|
||||
import re
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
|
||||
@ -36,15 +34,17 @@ from gns3server.compute.notification_manager import NotificationManager
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = Qemu.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_qemu_img_binary():
|
||||
def fake_qemu_img_binary(monkeypatch, tmpdir):
|
||||
|
||||
monkeypatch.setenv("PATH", str(tmpdir))
|
||||
bin_path = os.path.join(os.environ["PATH"], "qemu-img")
|
||||
with open(bin_path, "w+") as f:
|
||||
f.write("1")
|
||||
@ -53,8 +53,9 @@ def fake_qemu_img_binary():
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_qemu_binary():
|
||||
def fake_qemu_binary(monkeypatch, tmpdir):
|
||||
|
||||
monkeypatch.setenv("PATH", str(tmpdir))
|
||||
if sys.platform.startswith("win"):
|
||||
bin_path = os.path.join(os.environ["PATH"], "qemu-system-x86_64w.exe")
|
||||
else:
|
||||
@ -66,9 +67,10 @@ def fake_qemu_binary():
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(project, manager, fake_qemu_binary, fake_qemu_img_binary):
|
||||
async def vm(loop, compute_project, manager, fake_qemu_binary, fake_qemu_img_binary):
|
||||
|
||||
manager.port_manager.console_host = "127.0.0.1"
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, qemu_path=fake_qemu_binary)
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, qemu_path=fake_qemu_binary)
|
||||
vm._process_priority = "normal" # Avoid complexity for Windows tests
|
||||
vm._start_ubridge = AsyncioMagicMock()
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
@ -79,49 +81,52 @@ def vm(project, manager, fake_qemu_binary, fake_qemu_img_binary):
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def running_subprocess_mock():
|
||||
|
||||
mm = MagicMock()
|
||||
mm.returncode = None
|
||||
return mm
|
||||
|
||||
|
||||
def test_vm(project, manager, fake_qemu_binary):
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, qemu_path=fake_qemu_binary)
|
||||
def test_vm(compute_project, manager, fake_qemu_binary):
|
||||
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, qemu_path=fake_qemu_binary)
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
|
||||
|
||||
def test_vm_create(loop, tmpdir, project, manager, fake_qemu_binary):
|
||||
async def test_vm_create(tmpdir, compute_project, manager, fake_qemu_binary):
|
||||
|
||||
fake_img = str(tmpdir / 'hello')
|
||||
|
||||
with open(fake_img, 'w+') as f:
|
||||
f.write('hello')
|
||||
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, qemu_path=fake_qemu_binary)
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, qemu_path=fake_qemu_binary)
|
||||
vm._hda_disk_image = fake_img
|
||||
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
await vm.create()
|
||||
|
||||
# tests if `create` created md5sums
|
||||
assert os.path.exists(str(tmpdir / 'hello.md5sum'))
|
||||
|
||||
|
||||
def test_vm_invalid_qemu_with_platform(project, manager, fake_qemu_binary):
|
||||
def test_vm_invalid_qemu_with_platform(compute_project, manager, fake_qemu_binary):
|
||||
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, qemu_path="/usr/fake/bin/qemu-system-64", platform="x86_64")
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, qemu_path="/usr/fake/bin/qemu-system-64", platform="x86_64")
|
||||
|
||||
assert vm.qemu_path == fake_qemu_binary
|
||||
assert vm.platform == "x86_64"
|
||||
|
||||
|
||||
def test_vm_invalid_qemu_without_platform(project, manager, fake_qemu_binary):
|
||||
def test_vm_invalid_qemu_without_platform(compute_project, manager, fake_qemu_binary):
|
||||
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, qemu_path="/usr/fake/bin/qemu-system-x86_64")
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, qemu_path="/usr/fake/bin/qemu-system-x86_64")
|
||||
|
||||
assert vm.qemu_path == fake_qemu_binary
|
||||
assert vm.platform == "x86_64"
|
||||
|
||||
|
||||
def test_is_running(vm, running_subprocess_mock):
|
||||
async def test_is_running(vm, running_subprocess_mock):
|
||||
|
||||
vm._process = None
|
||||
assert vm.is_running() is False
|
||||
@ -131,18 +136,19 @@ def test_is_running(vm, running_subprocess_mock):
|
||||
assert vm.is_running() is False
|
||||
|
||||
|
||||
def test_start(loop, vm, running_subprocess_mock):
|
||||
async def test_start(vm, running_subprocess_mock):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=running_subprocess_mock) as mock:
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock.call_args[0])
|
||||
|
||||
|
||||
def test_stop(loop, vm, running_subprocess_mock):
|
||||
process = running_subprocess_mock
|
||||
async def test_stop(vm, running_subprocess_mock):
|
||||
|
||||
process = running_subprocess_mock
|
||||
# Wait process kill success
|
||||
future = asyncio.Future()
|
||||
future.set_result(True)
|
||||
@ -152,31 +158,30 @@ def test_stop(loop, vm, running_subprocess_mock):
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
nio = Qemu.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.adapter_add_nio_binding(0, nio)
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
await vm.stop()
|
||||
assert vm.is_running() is False
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
|
||||
def test_termination_callback(vm, async_run):
|
||||
async def test_termination_callback(vm):
|
||||
|
||||
vm.status = "started"
|
||||
|
||||
with NotificationManager.instance().queue() as queue:
|
||||
async_run(vm._termination_callback(0))
|
||||
await vm._termination_callback(0)
|
||||
assert vm.status == "stopped"
|
||||
|
||||
async_run(queue.get(1)) # Ping
|
||||
await queue.get(1) # Ping
|
||||
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
(action, event, kwargs) = await queue.get(1)
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_termination_callback_error(vm, tmpdir, async_run):
|
||||
async def test_termination_callback_error(vm, tmpdir):
|
||||
|
||||
with open(str(tmpdir / "qemu.log"), "w+") as f:
|
||||
f.write("BOOMM")
|
||||
@ -185,10 +190,10 @@ def test_termination_callback_error(vm, tmpdir, async_run):
|
||||
vm._stdout_file = str(tmpdir / "qemu.log")
|
||||
|
||||
with NotificationManager.instance().queue() as queue:
|
||||
async_run(vm._termination_callback(1))
|
||||
await vm._termination_callback(1)
|
||||
assert vm.status == "stopped"
|
||||
|
||||
async_run(queue.get(1)) # Ping
|
||||
await queue.get(1) # Ping
|
||||
|
||||
(action, event, kwargs) = queue.get_nowait()
|
||||
assert action == "node.updated"
|
||||
@ -199,46 +204,48 @@ def test_termination_callback_error(vm, tmpdir, async_run):
|
||||
assert event["message"] == "QEMU process has stopped, return code: 1\nBOOMM"
|
||||
|
||||
|
||||
def test_reload(loop, vm):
|
||||
async def test_reload(vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM._control_vm") as mock:
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.reload()))
|
||||
await vm.reload()
|
||||
assert mock.called_with("system_reset")
|
||||
|
||||
|
||||
def test_suspend(loop, vm):
|
||||
async def test_suspend(vm):
|
||||
|
||||
control_vm_result = MagicMock()
|
||||
control_vm_result.match.group.decode.return_value = "running"
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM._control_vm", return_value=control_vm_result) as mock:
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.suspend()))
|
||||
await vm.suspend()
|
||||
assert mock.called_with("system_reset")
|
||||
|
||||
|
||||
def test_add_nio_binding_udp(vm, loop):
|
||||
async def test_add_nio_binding_udp(vm):
|
||||
|
||||
nio = Qemu.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
assert nio.lport == 4242
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
await vm.adapter_add_nio_binding(0, nio)
|
||||
assert nio.lport == 4242
|
||||
|
||||
|
||||
async def test_port_remove_nio_binding(vm):
|
||||
|
||||
def test_port_remove_nio_binding(vm, loop):
|
||||
nio = Qemu.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_remove_nio_binding(0)))
|
||||
await vm.adapter_add_nio_binding(0, nio)
|
||||
await vm.adapter_remove_nio_binding(0)
|
||||
assert vm._ethernet_adapters[0].ports[0] is None
|
||||
|
||||
|
||||
def test_close(vm, port_manager, loop):
|
||||
async def test_close(vm, port_manager):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.start()
|
||||
|
||||
console_port = vm.console
|
||||
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
await vm.close()
|
||||
|
||||
# Raise an exception if the port is not free
|
||||
port_manager.reserve_tcp_port(console_port, vm.project)
|
||||
@ -287,7 +294,7 @@ def test_set_qemu_path_environ(vm, tmpdir, fake_qemu_binary):
|
||||
assert vm.platform == "x86_64"
|
||||
|
||||
|
||||
def test_set_qemu_path_windows(vm, tmpdir):
|
||||
def test_set_qemu_path_windows(vm):
|
||||
|
||||
bin_path = os.path.join(os.environ["PATH"], "qemu-system-x86_64w.EXE")
|
||||
open(bin_path, "w+").close()
|
||||
@ -300,7 +307,7 @@ def test_set_qemu_path_windows(vm, tmpdir):
|
||||
assert vm.platform == "x86_64"
|
||||
|
||||
|
||||
def test_set_qemu_path_old_windows(vm, tmpdir):
|
||||
def test_set_qemu_path_old_windows(vm):
|
||||
|
||||
bin_path = os.path.join(os.environ["PATH"], "qemu.exe")
|
||||
open(bin_path, "w+").close()
|
||||
@ -314,7 +321,7 @@ def test_set_qemu_path_old_windows(vm, tmpdir):
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_set_qemu_path_kvm_binary(vm, tmpdir, fake_qemu_binary):
|
||||
def test_set_qemu_path_kvm_binary(vm, fake_qemu_binary):
|
||||
|
||||
bin_path = os.path.join(os.environ["PATH"], "qemu-kvm")
|
||||
with open(bin_path, "w+") as f:
|
||||
@ -328,11 +335,11 @@ def test_set_qemu_path_kvm_binary(vm, tmpdir, fake_qemu_binary):
|
||||
assert vm.platform == "x86_64"
|
||||
|
||||
|
||||
def test_set_platform(project, manager):
|
||||
def test_set_platform(compute_project, manager):
|
||||
|
||||
with patch("shutil.which", return_value="/bin/qemu-system-x86_64") as which_mock:
|
||||
with patch("gns3server.compute.qemu.QemuVM._check_qemu_path"):
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, platform="x86_64")
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, platform="x86_64")
|
||||
if sys.platform.startswith("win"):
|
||||
which_mock.assert_called_with("qemu-system-x86_64w.exe", path=mock.ANY)
|
||||
else:
|
||||
@ -341,13 +348,13 @@ def test_set_platform(project, manager):
|
||||
assert vm.qemu_path == "/bin/qemu-system-x86_64"
|
||||
|
||||
|
||||
def test_disk_options(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
async def test_disk_options(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
vm._hda_disk_image = str(tmpdir / "test.qcow2")
|
||||
open(vm._hda_disk_image, "w+").close()
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._disk_options()))
|
||||
options = await vm._disk_options()
|
||||
assert process.called
|
||||
args, kwargs = process.call_args
|
||||
assert args == (fake_qemu_img_binary, "create", "-o", "backing_file={}".format(vm._hda_disk_image), "-f", "qcow2", os.path.join(vm.working_dir, "hda_disk.qcow2"))
|
||||
@ -355,44 +362,44 @@ def test_disk_options(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
assert options == ['-drive', 'file=' + os.path.join(vm.working_dir, "hda_disk.qcow2") + ',if=ide,index=0,media=disk,id=drive0']
|
||||
|
||||
|
||||
def test_cdrom_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
async def test_cdrom_option(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
vm._cdrom_image = str(tmpdir / "test.iso")
|
||||
open(vm._cdrom_image, "w+").close()
|
||||
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
options = await vm._build_command()
|
||||
|
||||
assert ' '.join(['-cdrom', str(tmpdir / "test.iso")]) in ' '.join(options)
|
||||
|
||||
|
||||
def test_bios_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
async def test_bios_option(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
vm._bios_image = str(tmpdir / "test.img")
|
||||
open(vm._bios_image, "w+").close()
|
||||
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
|
||||
options = await vm._build_command()
|
||||
assert ' '.join(['-bios', str(tmpdir / "test.img")]) in ' '.join(options)
|
||||
|
||||
|
||||
def test_vnc_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
async def test_vnc_option(vm, fake_qemu_img_binary):
|
||||
|
||||
vm._console_type = 'vnc'
|
||||
vm._console = 5905
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
options = await vm._build_command()
|
||||
assert '-vnc 127.0.0.1:5' in ' '.join(options)
|
||||
|
||||
|
||||
def test_spice_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
async def test_spice_option(vm, fake_qemu_img_binary):
|
||||
|
||||
vm._console_type = 'spice'
|
||||
vm._console = 5905
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
options = await vm._build_command()
|
||||
assert '-spice addr=127.0.0.1,port=5905,disable-ticketing' in ' '.join(options)
|
||||
assert '-vga qxl' in ' '.join(options)
|
||||
|
||||
|
||||
def test_disk_options_multiple_disk(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
async def test_disk_options_multiple_disk(vm, tmpdir, fake_qemu_img_binary):
|
||||
|
||||
vm._hda_disk_image = str(tmpdir / "test0.qcow2")
|
||||
vm._hdb_disk_image = str(tmpdir / "test1.qcow2")
|
||||
@ -403,8 +410,8 @@ def test_disk_options_multiple_disk(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
open(vm._hdc_disk_image, "w+").close()
|
||||
open(vm._hdd_disk_image, "w+").close()
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._disk_options()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
options = await vm._disk_options()
|
||||
|
||||
assert options == [
|
||||
'-drive', 'file=' + os.path.join(vm.working_dir, "hda_disk.qcow2") + ',if=ide,index=0,media=disk,id=drive0',
|
||||
@ -415,70 +422,70 @@ def test_disk_options_multiple_disk(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_set_process_priority(vm, loop, fake_qemu_img_binary):
|
||||
async def test_set_process_priority(vm, fake_qemu_img_binary):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
vm._process = MagicMock()
|
||||
vm._process.pid = 42
|
||||
vm._process_priority = "low"
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._set_process_priority()))
|
||||
await vm._set_process_priority()
|
||||
assert process.called
|
||||
args, kwargs = process.call_args
|
||||
assert args == ("renice", "-n", "5", "-p", "42")
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_set_process_priority_normal(vm, loop, fake_qemu_img_binary):
|
||||
async def test_set_process_priority_normal(vm, fake_qemu_img_binary):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
vm._process = MagicMock()
|
||||
vm._process.pid = 42
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._set_process_priority()))
|
||||
await vm._set_process_priority()
|
||||
assert not process.called
|
||||
|
||||
|
||||
def test_json(vm, project):
|
||||
def test_json(vm, compute_project):
|
||||
|
||||
json = vm.__json__()
|
||||
assert json["name"] == vm.name
|
||||
assert json["project_id"] == project.id
|
||||
assert json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_control_vm(vm, loop):
|
||||
async def test_control_vm(vm):
|
||||
|
||||
vm._process = MagicMock()
|
||||
reader = MagicMock()
|
||||
writer = MagicMock()
|
||||
with asyncio_patch("asyncio.open_connection", return_value=(reader, writer)) as open_connect:
|
||||
res = loop.run_until_complete(asyncio.ensure_future(vm._control_vm("test")))
|
||||
with asyncio_patch("asyncio.open_connection", return_value=(reader, writer)):
|
||||
res = await vm._control_vm("test")
|
||||
assert writer.write.called_with("test")
|
||||
assert res is None
|
||||
|
||||
|
||||
def test_control_vm_expect_text(vm, loop, running_subprocess_mock):
|
||||
async def test_control_vm_expect_text(vm, running_subprocess_mock):
|
||||
|
||||
vm._process = running_subprocess_mock
|
||||
reader = MagicMock()
|
||||
writer = MagicMock()
|
||||
with asyncio_patch("asyncio.open_connection", return_value=(reader, writer)) as open_connect:
|
||||
with asyncio_patch("asyncio.open_connection", return_value=(reader, writer)):
|
||||
|
||||
future = asyncio.Future()
|
||||
future.set_result(b"epic product")
|
||||
reader.readline.return_value = future
|
||||
|
||||
vm._monitor = 4242
|
||||
res = loop.run_until_complete(asyncio.ensure_future(vm._control_vm("test", [b"epic"])))
|
||||
res = await vm._control_vm("test", [b"epic"])
|
||||
assert writer.write.called_with("test")
|
||||
|
||||
assert res == "epic product"
|
||||
|
||||
|
||||
def test_build_command(vm, loop, fake_qemu_binary, port_manager):
|
||||
async def test_build_command(vm, fake_qemu_binary):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
cmd = await vm._build_command()
|
||||
nio = vm._local_udp_tunnels[0][0]
|
||||
assert cmd == [
|
||||
fake_qemu_binary,
|
||||
@ -505,7 +512,7 @@ def test_build_command(vm, loop, fake_qemu_binary, port_manager):
|
||||
]
|
||||
|
||||
|
||||
def test_build_command_manual_uuid(vm, loop, fake_qemu_binary, port_manager):
|
||||
async def test_build_command_manual_uuid(vm):
|
||||
"""
|
||||
If user has set a uuid we keep it
|
||||
"""
|
||||
@ -513,13 +520,13 @@ def test_build_command_manual_uuid(vm, loop, fake_qemu_binary, port_manager):
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0")
|
||||
vm.options = "-uuid e1c307a4-896f-11e6-81a5-3c07547807cc"
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
cmd = await vm._build_command()
|
||||
assert "e1c307a4-896f-11e6-81a5-3c07547807cc" in cmd
|
||||
assert vm.id not in cmd
|
||||
|
||||
|
||||
def test_build_command_kvm(linux_platform, vm, loop, fake_qemu_binary, port_manager):
|
||||
async def test_build_command_kvm(linux_platform, vm, fake_qemu_binary):
|
||||
"""
|
||||
Qemu 2.4 introduce an issue with KVM
|
||||
"""
|
||||
@ -528,7 +535,7 @@ def test_build_command_kvm(linux_platform, vm, loop, fake_qemu_binary, port_mana
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._run_with_hardware_acceleration", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
cmd = await vm._build_command()
|
||||
nio = vm._local_udp_tunnels[0][0]
|
||||
assert cmd == [
|
||||
fake_qemu_binary,
|
||||
@ -555,7 +562,7 @@ def test_build_command_kvm(linux_platform, vm, loop, fake_qemu_binary, port_mana
|
||||
]
|
||||
|
||||
|
||||
def test_build_command_kvm_2_4(linux_platform, vm, loop, fake_qemu_binary, port_manager):
|
||||
async def test_build_command_kvm_2_4(linux_platform, vm, fake_qemu_binary):
|
||||
"""
|
||||
Qemu 2.4 introduce an issue with KVM
|
||||
"""
|
||||
@ -564,7 +571,7 @@ def test_build_command_kvm_2_4(linux_platform, vm, loop, fake_qemu_binary, port_
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._run_with_hardware_acceleration", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
cmd = await vm._build_command()
|
||||
nio = vm._local_udp_tunnels[0][0]
|
||||
assert cmd == [
|
||||
fake_qemu_binary,
|
||||
@ -594,22 +601,22 @@ def test_build_command_kvm_2_4(linux_platform, vm, loop, fake_qemu_binary, port_
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_build_command_without_display(vm, loop, fake_qemu_binary):
|
||||
async def test_build_command_without_display(vm):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.5.0")
|
||||
os.environ["DISPLAY"] = ""
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
cmd = await vm._build_command()
|
||||
assert "-nographic" in cmd
|
||||
|
||||
|
||||
def test_build_command_two_adapters(vm, loop, fake_qemu_binary, port_manager):
|
||||
async def test_build_command_two_adapters(vm, fake_qemu_binary):
|
||||
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.5.0")
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
vm.adapters = 2
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
cmd = await vm._build_command()
|
||||
nio1 = vm._local_udp_tunnels[0][0]
|
||||
nio2 = vm._local_udp_tunnels[1][0]
|
||||
assert cmd == [
|
||||
@ -640,7 +647,7 @@ def test_build_command_two_adapters(vm, loop, fake_qemu_binary, port_manager):
|
||||
]
|
||||
|
||||
|
||||
def test_build_command_two_adapters_mac_address(vm, loop, fake_qemu_binary, port_manager):
|
||||
async def test_build_command_two_adapters_mac_address(vm):
|
||||
"""
|
||||
Should support multiple base vmac address
|
||||
"""
|
||||
@ -651,8 +658,8 @@ def test_build_command_two_adapters_mac_address(vm, loop, fake_qemu_binary, port
|
||||
mac_0 = vm._mac_address
|
||||
mac_1 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 1)
|
||||
assert mac_0[:8] == "00:00:ab"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
cmd = await vm._build_command()
|
||||
assert "e1000,mac={},netdev=gns3-0".format(mac_0) in cmd
|
||||
assert "e1000,mac={},netdev=gns3-1".format(mac_1) in cmd
|
||||
|
||||
@ -660,16 +667,17 @@ def test_build_command_two_adapters_mac_address(vm, loop, fake_qemu_binary, port
|
||||
mac_0 = vm._mac_address
|
||||
mac_1 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 1)
|
||||
assert mac_0[:8] == "00:42:ab"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
|
||||
cmd = await vm._build_command()
|
||||
assert "e1000,mac={},netdev=gns3-0".format(mac_0) in cmd
|
||||
assert "e1000,mac={},netdev=gns3-1".format(mac_1) in cmd
|
||||
|
||||
|
||||
def test_build_command_large_number_of_adapters(vm, loop, fake_qemu_binary, port_manager):
|
||||
async def test_build_command_large_number_of_adapters(vm):
|
||||
"""
|
||||
When we have more than 28 interface we need to add a pci bridge for
|
||||
additionnal interfaces
|
||||
additional interfaces
|
||||
"""
|
||||
|
||||
# It's supported only with Qemu 2.4 and later
|
||||
@ -680,8 +688,8 @@ def test_build_command_large_number_of_adapters(vm, loop, fake_qemu_binary, port
|
||||
mac_0 = vm._mac_address
|
||||
mac_1 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 1)
|
||||
assert mac_0[:8] == "00:00:ab"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
cmd = await vm._build_command()
|
||||
|
||||
# Count if we have 100 e1000 adapters in the command
|
||||
assert len([l for l in cmd if "e1000" in l ]) == 100
|
||||
@ -704,21 +712,19 @@ def test_build_command_large_number_of_adapters(vm, loop, fake_qemu_binary, port
|
||||
# Qemu < 2.4 doesn't support large number of adapters
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.0.0")
|
||||
with pytest.raises(QemuError):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
await vm._build_command()
|
||||
vm.adapters = 5
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
|
||||
# Windows accept this kind of mistake
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
await vm._build_command()
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_build_command_with_invalid_options(vm, loop, fake_qemu_binary):
|
||||
async def test_build_command_with_invalid_options(vm):
|
||||
|
||||
vm.options = "'test"
|
||||
with pytest.raises(QemuError):
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
await vm._build_command()
|
||||
|
||||
|
||||
def test_hda_disk_image(vm, images_dir):
|
||||
@ -731,7 +737,7 @@ def test_hda_disk_image(vm, images_dir):
|
||||
assert vm.hda_disk_image == force_unix_path(os.path.join(images_dir, "QEMU", "test2"))
|
||||
|
||||
|
||||
def test_hda_disk_image_non_linked_clone(vm, images_dir, project, manager, fake_qemu_binary, fake_qemu_img_binary):
|
||||
def test_hda_disk_image_non_linked_clone(vm, images_dir, compute_project, manager, fake_qemu_binary):
|
||||
"""
|
||||
Two non linked can't use the same image at the same time
|
||||
"""
|
||||
@ -741,7 +747,7 @@ def test_hda_disk_image_non_linked_clone(vm, images_dir, project, manager, fake_
|
||||
vm.hda_disk_image = os.path.join(images_dir, "test1")
|
||||
vm.manager._nodes[vm.id] = vm
|
||||
|
||||
vm2 = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0eaa", project, manager, qemu_path=fake_qemu_binary)
|
||||
vm2 = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0eaa", compute_project, manager, qemu_path=fake_qemu_binary)
|
||||
vm2.linked_clone = False
|
||||
with pytest.raises(QemuError):
|
||||
vm2.hda_disk_image = os.path.join(images_dir, "test1")
|
||||
@ -833,58 +839,58 @@ def test_options_windows(windows_platform, vm):
|
||||
|
||||
def test_get_qemu_img(vm, tmpdir):
|
||||
|
||||
open(str(tmpdir / "qemu-sytem-x86_64"), "w+").close()
|
||||
open(str(tmpdir / "qemu-system-x86_64"), "w+").close()
|
||||
open(str(tmpdir / "qemu-img"), "w+").close()
|
||||
vm._qemu_path = str(tmpdir / "qemu-sytem-x86_64")
|
||||
vm._qemu_path = str(tmpdir / "qemu-system-x86_64")
|
||||
assert vm._get_qemu_img() == str(tmpdir / "qemu-img")
|
||||
|
||||
|
||||
def test_get_qemu_img_not_exist(vm, tmpdir):
|
||||
|
||||
open(str(tmpdir / "qemu-sytem-x86_64"), "w+").close()
|
||||
vm._qemu_path = str(tmpdir / "qemu-sytem-x86_64")
|
||||
with pytest.raises(QemuError):
|
||||
vm._get_qemu_img()
|
||||
# def test_get_qemu_img_not_exist(vm, tmpdir):
|
||||
#
|
||||
# open(str(tmpdir / "qemu-system-x86_64"), "w+").close()
|
||||
# vm._qemu_path = str(tmpdir / "qemu-system-x86_64")
|
||||
# with pytest.raises(QemuError):
|
||||
# vm._get_qemu_img()
|
||||
|
||||
|
||||
def test_run_with_hardware_acceleration_darwin(darwin_platform, vm, loop):
|
||||
async def test_run_with_hardware_acceleration_darwin(darwin_platform, vm):
|
||||
|
||||
vm.manager.config.set("Qemu", "enable_hardware_acceleration", False)
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._run_with_hardware_acceleration("qemu-system-x86_64", ""))) is False
|
||||
assert await vm._run_with_hardware_acceleration("qemu-system-x86_64", "") is False
|
||||
|
||||
|
||||
def test_run_with_hardware_acceleration_windows(windows_platform, vm, loop):
|
||||
async def test_run_with_hardware_acceleration_windows(windows_platform, vm):
|
||||
|
||||
vm.manager.config.set("Qemu", "enable_hardware_acceleration", False)
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._run_with_hardware_acceleration("qemu-system-x86_64", ""))) is False
|
||||
assert await vm._run_with_hardware_acceleration("qemu-system-x86_64", "") is False
|
||||
|
||||
|
||||
def test_run_with_kvm_linux(linux_platform, vm, loop):
|
||||
async def test_run_with_kvm_linux(linux_platform, vm):
|
||||
|
||||
with patch("os.path.exists", return_value=True) as os_path:
|
||||
vm.manager.config.set("Qemu", "enable_kvm", True)
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._run_with_hardware_acceleration("qemu-system-x86_64", ""))) is True
|
||||
assert await vm._run_with_hardware_acceleration("qemu-system-x86_64", "") is True
|
||||
os_path.assert_called_with("/dev/kvm")
|
||||
|
||||
|
||||
def test_run_with_kvm_linux_options_no_kvm(linux_platform, vm, loop):
|
||||
async def test_run_with_kvm_linux_options_no_kvm(linux_platform, vm):
|
||||
|
||||
with patch("os.path.exists", return_value=True) as os_path:
|
||||
vm.manager.config.set("Qemu", "enable_kvm", True)
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._run_with_hardware_acceleration("qemu-system-x86_64", "-no-kvm"))) is False
|
||||
assert await vm._run_with_hardware_acceleration("qemu-system-x86_64", "-no-kvm") is False
|
||||
|
||||
|
||||
def test_run_with_kvm_not_x86(linux_platform, vm, loop):
|
||||
async def test_run_with_kvm_not_x86(linux_platform, vm):
|
||||
|
||||
with patch("os.path.exists", return_value=True) as os_path:
|
||||
with patch("os.path.exists", return_value=True):
|
||||
vm.manager.config.set("Qemu", "enable_kvm", True)
|
||||
with pytest.raises(QemuError):
|
||||
ret = loop.run_until_complete(asyncio.ensure_future(vm._run_with_hardware_acceleration("qemu-system-arm", "")))
|
||||
await vm._run_with_hardware_acceleration("qemu-system-arm", "")
|
||||
|
||||
|
||||
def test_run_with_kvm_linux_dev_kvm_missing(linux_platform, vm, loop):
|
||||
async def test_run_with_kvm_linux_dev_kvm_missing(linux_platform, vm):
|
||||
|
||||
with patch("os.path.exists", return_value=False) as os_path:
|
||||
with patch("os.path.exists", return_value=False):
|
||||
vm.manager.config.set("Qemu", "enable_kvm", True)
|
||||
with pytest.raises(QemuError):
|
||||
ret = loop.run_until_complete(asyncio.ensure_future(vm._run_with_hardware_acceleration("qemu-system-x86_64", "")))
|
||||
await vm._run_with_hardware_acceleration("qemu-system-x86_64", "")
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -14,43 +14,44 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
import pytest
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
from gns3server.compute.vpcs.vpcs_vm import VPCSVM
|
||||
from gns3server.compute.docker.docker_vm import DockerVM
|
||||
from gns3server.compute.vpcs.vpcs_error import VPCSError
|
||||
from gns3server.compute.error import NodeError
|
||||
from gns3server.compute.vpcs import VPCS
|
||||
from gns3server.compute.nios.nio_udp import NIOUDP
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = VPCS.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def node(project, manager):
|
||||
return VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def node(compute_project, manager):
|
||||
|
||||
return VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
|
||||
|
||||
def test_temporary_directory(project, manager):
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def test_temporary_directory(compute_project, manager):
|
||||
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
assert isinstance(node.temporary_directory, str)
|
||||
|
||||
|
||||
def test_console(project, manager):
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def test_console(compute_project, manager):
|
||||
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
node.console = 5011
|
||||
assert node.console == 5011
|
||||
node.console = None
|
||||
@ -58,6 +59,7 @@ def test_console(project, manager):
|
||||
|
||||
|
||||
def test_change_console_port(node, port_manager):
|
||||
|
||||
port1 = port_manager.get_free_tcp_port(node.project)
|
||||
port2 = port_manager.get_free_tcp_port(node.project)
|
||||
port_manager.release_tcp_port(port1, node.project)
|
||||
@ -68,22 +70,23 @@ def test_change_console_port(node, port_manager):
|
||||
port_manager.reserve_tcp_port(port1, node.project)
|
||||
|
||||
|
||||
def test_console_vnc_invalid(project, manager):
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def test_console_vnc_invalid(compute_project, manager):
|
||||
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
node._console_type = "vnc"
|
||||
with pytest.raises(NodeError):
|
||||
node.console = 2012
|
||||
|
||||
|
||||
def test_close(node, loop, port_manager):
|
||||
assert node.console is not None
|
||||
async def test_close(node, port_manager):
|
||||
|
||||
assert node.console is not None
|
||||
aux = port_manager.get_free_tcp_port(node.project)
|
||||
port_manager.release_tcp_port(aux, node.project)
|
||||
|
||||
node.aux = aux
|
||||
port = node.console
|
||||
assert loop.run_until_complete(asyncio.ensure_future(node.close()))
|
||||
assert await node.close()
|
||||
# Raise an exception if the port is not free
|
||||
port_manager.reserve_tcp_port(port, node.project)
|
||||
# Raise an exception if the port is not free
|
||||
@ -92,29 +95,32 @@ def test_close(node, loop, port_manager):
|
||||
assert node.aux is None
|
||||
|
||||
# Called twice closed should return False
|
||||
assert loop.run_until_complete(asyncio.ensure_future(node.close())) is False
|
||||
assert await node.close() is False
|
||||
|
||||
|
||||
def test_aux(project, manager, port_manager):
|
||||
aux = port_manager.get_free_tcp_port(project)
|
||||
port_manager.release_tcp_port(aux, project)
|
||||
def test_aux(compute_project, manager, port_manager):
|
||||
|
||||
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "ubuntu", aux=aux)
|
||||
aux = port_manager.get_free_tcp_port(compute_project)
|
||||
port_manager.release_tcp_port(aux, compute_project)
|
||||
|
||||
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "ubuntu", aux=aux)
|
||||
assert node.aux == aux
|
||||
node.aux = None
|
||||
assert node.aux is None
|
||||
|
||||
|
||||
def test_allocate_aux(project, manager):
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def test_allocate_aux(compute_project, manager):
|
||||
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
assert node.aux is None
|
||||
|
||||
# Docker has an aux port by default
|
||||
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "ubuntu")
|
||||
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "ubuntu")
|
||||
assert node.aux is not None
|
||||
|
||||
|
||||
def test_change_aux_port(node, port_manager):
|
||||
|
||||
port1 = port_manager.get_free_tcp_port(node.project)
|
||||
port2 = port_manager.get_free_tcp_port(node.project)
|
||||
port_manager.release_tcp_port(port1, node.project)
|
||||
@ -125,7 +131,8 @@ def test_change_aux_port(node, port_manager):
|
||||
port_manager.reserve_tcp_port(port1, node.project)
|
||||
|
||||
|
||||
def test_update_ubridge_udp_connection(node, async_run):
|
||||
async def test_update_ubridge_udp_connection(node):
|
||||
|
||||
filters = {
|
||||
"latency": [10]
|
||||
}
|
||||
@ -134,27 +141,29 @@ def test_update_ubridge_udp_connection(node, async_run):
|
||||
dnio = NIOUDP(1245, "localhost", 1244)
|
||||
dnio.filters = filters
|
||||
with asyncio_patch("gns3server.compute.base_node.BaseNode._ubridge_apply_filters") as mock:
|
||||
async_run(node.update_ubridge_udp_connection('VPCS-10', snio, dnio))
|
||||
await node.update_ubridge_udp_connection('VPCS-10', snio, dnio)
|
||||
mock.assert_called_with("VPCS-10", filters)
|
||||
|
||||
|
||||
def test_ubridge_apply_filters(node, async_run):
|
||||
async def test_ubridge_apply_filters(node):
|
||||
|
||||
filters = OrderedDict((
|
||||
('latency', [10]),
|
||||
('bpf', ["icmp[icmptype] == 8\ntcp src port 53"])
|
||||
))
|
||||
node._ubridge_send = AsyncioMagicMock()
|
||||
async_run(node._ubridge_apply_filters("VPCS-10", filters))
|
||||
await node._ubridge_apply_filters("VPCS-10", filters)
|
||||
node._ubridge_send.assert_any_call("bridge reset_packet_filters VPCS-10")
|
||||
node._ubridge_send.assert_any_call("bridge add_packet_filter VPCS-10 filter0 latency 10")
|
||||
|
||||
|
||||
def test_ubridge_apply_bpf_filters(node, async_run):
|
||||
async def test_ubridge_apply_bpf_filters(node):
|
||||
|
||||
filters = {
|
||||
"bpf": ["icmp[icmptype] == 8\ntcp src port 53"]
|
||||
}
|
||||
node._ubridge_send = AsyncioMagicMock()
|
||||
async_run(node._ubridge_apply_filters("VPCS-10", filters))
|
||||
await node._ubridge_apply_filters("VPCS-10", filters)
|
||||
node._ubridge_send.assert_any_call("bridge reset_packet_filters VPCS-10")
|
||||
node._ubridge_send.assert_any_call("bridge add_packet_filter VPCS-10 filter0 bpf \"icmp[icmptype] == 8\"")
|
||||
node._ubridge_send.assert_any_call("bridge add_packet_filter VPCS-10 filter1 bpf \"tcp src port 53\"")
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -19,8 +19,7 @@ import uuid
|
||||
import os
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
from tests.utils import AsyncioMagicMock, asyncio_patch
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.compute.vpcs import VPCS
|
||||
from gns3server.compute.dynamips import Dynamips
|
||||
@ -30,7 +29,8 @@ from gns3server.utils import force_unix_path
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vpcs(port_manager):
|
||||
async def vpcs(loop, port_manager):
|
||||
|
||||
VPCS._instance = None
|
||||
vpcs = VPCS.instance()
|
||||
vpcs.port_manager = port_manager
|
||||
@ -38,49 +38,53 @@ def vpcs(port_manager):
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def qemu(port_manager):
|
||||
async def qemu(loop, port_manager):
|
||||
|
||||
Qemu._instance = None
|
||||
qemu = Qemu.instance()
|
||||
qemu.port_manager = port_manager
|
||||
return qemu
|
||||
|
||||
|
||||
def test_create_node_new_topology(loop, project, vpcs):
|
||||
async def test_create_node_new_topology(compute_project, vpcs):
|
||||
|
||||
node_id = str(uuid.uuid4())
|
||||
node = loop.run_until_complete(vpcs.create_node("PC 1", project.id, node_id))
|
||||
assert node in project.nodes
|
||||
node = await vpcs.create_node("PC 1", compute_project.id, node_id)
|
||||
assert node in compute_project.nodes
|
||||
|
||||
|
||||
def test_create_twice_same_node_new_topology(loop, project, vpcs):
|
||||
project._nodes = set()
|
||||
async def test_create_twice_same_node_new_topology(compute_project, vpcs):
|
||||
|
||||
compute_project._nodes = set()
|
||||
node_id = str(uuid.uuid4())
|
||||
node = loop.run_until_complete(vpcs.create_node("PC 1", project.id, node_id, console=2222))
|
||||
assert node in project.nodes
|
||||
assert len(project.nodes) == 1
|
||||
node = loop.run_until_complete(vpcs.create_node("PC 2", project.id, node_id, console=2222))
|
||||
assert len(project.nodes) == 1
|
||||
node = await vpcs.create_node("PC 1", compute_project.id, node_id, console=2222)
|
||||
assert node in compute_project.nodes
|
||||
assert len(compute_project.nodes) == 1
|
||||
await vpcs.create_node("PC 2", compute_project.id, node_id, console=2222)
|
||||
assert len(compute_project.nodes) == 1
|
||||
|
||||
|
||||
def test_create_node_new_topology_without_uuid(loop, project, vpcs):
|
||||
node = loop.run_until_complete(vpcs.create_node("PC 1", project.id, None))
|
||||
assert node in project.nodes
|
||||
async def test_create_node_new_topology_without_uuid(compute_project, vpcs):
|
||||
|
||||
node = await vpcs.create_node("PC 1", compute_project.id, None)
|
||||
assert node in compute_project.nodes
|
||||
assert len(node.id) == 36
|
||||
|
||||
|
||||
def test_create_node_old_topology(loop, project, tmpdir, vpcs):
|
||||
async def test_create_node_old_topology(compute_project, tmpdir, vpcs):
|
||||
|
||||
with patch("gns3server.compute.project.Project.is_local", return_value=True):
|
||||
# Create an old topology directory
|
||||
project_dir = str(tmpdir / "testold")
|
||||
node_dir = os.path.join(project_dir, "testold-files", "vpcs", "pc-1")
|
||||
project.path = project_dir
|
||||
project.name = "testold"
|
||||
compute_project.path = project_dir
|
||||
compute_project.name = "testold"
|
||||
os.makedirs(node_dir, exist_ok=True)
|
||||
with open(os.path.join(node_dir, "startup.vpc"), "w+") as f:
|
||||
f.write("1")
|
||||
|
||||
node_id = 1
|
||||
node = loop.run_until_complete(vpcs.create_node("PC 1", project.id, node_id))
|
||||
node = await vpcs.create_node("PC 1", compute_project.id, node_id)
|
||||
assert len(node.id) == 36
|
||||
|
||||
assert os.path.exists(os.path.join(project_dir, "testold-files")) is False
|
||||
@ -91,6 +95,7 @@ def test_create_node_old_topology(loop, project, tmpdir, vpcs):
|
||||
|
||||
|
||||
def test_get_abs_image_path(qemu, tmpdir, config):
|
||||
|
||||
os.makedirs(str(tmpdir / "QEMU"))
|
||||
path1 = force_unix_path(str(tmpdir / "test1.bin"))
|
||||
open(path1, 'w+').close()
|
||||
@ -107,6 +112,7 @@ def test_get_abs_image_path(qemu, tmpdir, config):
|
||||
|
||||
|
||||
def test_get_abs_image_path_non_local(qemu, tmpdir, config):
|
||||
|
||||
path1 = tmpdir / "images" / "QEMU" / "test1.bin"
|
||||
path1.write("1", ensure=True)
|
||||
path1 = force_unix_path(str(path1))
|
||||
@ -128,6 +134,7 @@ def test_get_abs_image_path_non_local(qemu, tmpdir, config):
|
||||
|
||||
|
||||
def test_get_abs_image_additional_image_paths(qemu, tmpdir, config):
|
||||
|
||||
path1 = tmpdir / "images1" / "QEMU" / "test1.bin"
|
||||
path1.write("1", ensure=True)
|
||||
path1 = force_unix_path(str(path1))
|
||||
@ -151,6 +158,7 @@ def test_get_abs_image_additional_image_paths(qemu, tmpdir, config):
|
||||
|
||||
|
||||
def test_get_abs_image_recursive(qemu, tmpdir, config):
|
||||
|
||||
path1 = tmpdir / "images1" / "QEMU" / "demo" / "test1.bin"
|
||||
path1.write("1", ensure=True)
|
||||
path1 = force_unix_path(str(path1))
|
||||
@ -169,6 +177,7 @@ def test_get_abs_image_recursive(qemu, tmpdir, config):
|
||||
|
||||
|
||||
def test_get_abs_image_recursive_ova(qemu, tmpdir, config):
|
||||
|
||||
path1 = tmpdir / "images1" / "QEMU" / "demo" / "test.ova" / "test1.bin"
|
||||
path1.write("1", ensure=True)
|
||||
path1 = force_unix_path(str(path1))
|
||||
@ -187,6 +196,7 @@ def test_get_abs_image_recursive_ova(qemu, tmpdir, config):
|
||||
|
||||
|
||||
def test_get_relative_image_path(qemu, tmpdir, config):
|
||||
|
||||
os.makedirs(str(tmpdir / "images1" / "QEMU"))
|
||||
os.makedirs(str(tmpdir / "images1" / "VBOX"))
|
||||
path1 = force_unix_path(str(tmpdir / "images1" / "test1.bin"))
|
||||
@ -221,7 +231,7 @@ def test_get_relative_image_path(qemu, tmpdir, config):
|
||||
assert qemu.get_relative_image_path(path5) == path5
|
||||
|
||||
|
||||
def test_list_images(loop, qemu, tmpdir):
|
||||
async def test_list_images(qemu, tmpdir):
|
||||
|
||||
fake_images = ["a.qcow2", "b.qcow2", ".blu.qcow2", "a.qcow2.md5sum"]
|
||||
tmp_images_dir = os.path.join(tmpdir, "images")
|
||||
@ -231,13 +241,13 @@ def test_list_images(loop, qemu, tmpdir):
|
||||
f.write("1")
|
||||
|
||||
with patch("gns3server.utils.images.default_images_directory", return_value=str(tmp_images_dir)):
|
||||
assert sorted(loop.run_until_complete(qemu.list_images()), key=lambda k: k['filename']) == [
|
||||
assert sorted(await qemu.list_images(), key=lambda k: k['filename']) == [
|
||||
{"filename": "a.qcow2", "path": "a.qcow2", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1},
|
||||
{"filename": "b.qcow2", "path": "b.qcow2", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1}
|
||||
]
|
||||
|
||||
|
||||
def test_list_images_recursives(loop, qemu, tmpdir):
|
||||
async def test_list_images_recursives(qemu, tmpdir):
|
||||
|
||||
tmp_images_dir = os.path.join(tmpdir, "images")
|
||||
os.makedirs(tmp_images_dir, exist_ok=True)
|
||||
@ -253,52 +263,57 @@ def test_list_images_recursives(loop, qemu, tmpdir):
|
||||
|
||||
with patch("gns3server.utils.images.default_images_directory", return_value=str(tmp_images_dir)):
|
||||
|
||||
assert sorted(loop.run_until_complete(qemu.list_images()), key=lambda k: k['filename']) == [
|
||||
assert sorted(await qemu.list_images(), key=lambda k: k['filename']) == [
|
||||
{"filename": "a.qcow2", "path": "a.qcow2", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1},
|
||||
{"filename": "b.qcow2", "path": "b.qcow2", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1},
|
||||
{"filename": "c.qcow2", "path": force_unix_path(os.path.sep.join(["c", "c.qcow2"])), "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1}
|
||||
]
|
||||
|
||||
|
||||
def test_list_images_empty(loop, qemu, tmpdir):
|
||||
async def test_list_images_empty(qemu, tmpdir):
|
||||
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
assert loop.run_until_complete(qemu.list_images()) == []
|
||||
assert await qemu.list_images() == []
|
||||
|
||||
|
||||
def test_list_images_directory_not_exist(loop, qemu):
|
||||
async def test_list_images_directory_not_exist(qemu):
|
||||
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value="/bla"):
|
||||
assert loop.run_until_complete(qemu.list_images()) == []
|
||||
assert await qemu.list_images() == []
|
||||
|
||||
|
||||
def test_delete_node(async_run, vpcs, project):
|
||||
project._nodes = set()
|
||||
async def test_delete_node(vpcs, compute_project):
|
||||
|
||||
compute_project._nodes = set()
|
||||
node_id = str(uuid.uuid4())
|
||||
node = async_run(vpcs.create_node("PC 1", project.id, node_id, console=2222))
|
||||
assert node in project.nodes
|
||||
node = await vpcs.create_node("PC 1", compute_project.id, node_id, console=2222)
|
||||
assert node in compute_project.nodes
|
||||
with patch("gns3server.compute.project.Project.emit") as mock_emit:
|
||||
async_run(vpcs.delete_node(node_id))
|
||||
await vpcs.delete_node(node_id)
|
||||
mock_emit.assert_called_with("node.deleted", node)
|
||||
assert node not in project.nodes
|
||||
assert node not in compute_project.nodes
|
||||
|
||||
|
||||
def test_duplicate_vpcs(async_run, vpcs, project):
|
||||
async def test_duplicate_vpcs(vpcs, compute_project):
|
||||
|
||||
source_node_id = str(uuid.uuid4())
|
||||
source_node = async_run(vpcs.create_node("PC-1", project.id, source_node_id, console=2222))
|
||||
source_node = await vpcs.create_node("PC-1", compute_project.id, source_node_id, console=2222)
|
||||
with open(os.path.join(source_node.working_dir, "startup.vpc"), "w+") as f:
|
||||
f.write("set pcname PC-1\nip dhcp\n")
|
||||
destination_node_id = str(uuid.uuid4())
|
||||
destination_node = async_run(vpcs.create_node("PC-2", project.id, destination_node_id, console=2223))
|
||||
async_run(vpcs.duplicate_node(source_node_id, destination_node_id))
|
||||
destination_node = await vpcs.create_node("PC-2", compute_project.id, destination_node_id, console=2223)
|
||||
await vpcs.duplicate_node(source_node_id, destination_node_id)
|
||||
with open(os.path.join(destination_node.working_dir, "startup.vpc")) as f:
|
||||
startup = f.read().strip()
|
||||
assert startup == "set pcname PC-2\nip dhcp\n".strip()
|
||||
|
||||
|
||||
def test_duplicate_ethernet_switch(async_run, project):
|
||||
async def test_duplicate_ethernet_switch(compute_project):
|
||||
|
||||
with asyncio_patch('gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.create'):
|
||||
dynamips_manager = Dynamips.instance()
|
||||
source_node_id = str(uuid.uuid4())
|
||||
source_node = async_run(dynamips_manager.create_node("SW-1", project.id, source_node_id, node_type='ethernet_switch'))
|
||||
await dynamips_manager.create_node("SW-1", compute_project.id, source_node_id, node_type='ethernet_switch')
|
||||
destination_node_id = str(uuid.uuid4())
|
||||
destination_node = async_run(dynamips_manager.create_node("SW-2", project.id, destination_node_id, node_type='ethernet_switch'))
|
||||
async_run(dynamips_manager.duplicate_node(source_node_id, destination_node_id))
|
||||
await dynamips_manager.create_node("SW-2", compute_project.id, destination_node_id, node_type='ethernet_switch')
|
||||
await dynamips_manager.duplicate_node(source_node_id, destination_node_id)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,69 +20,73 @@ import uuid
|
||||
from gns3server.compute.notification_manager import NotificationManager
|
||||
|
||||
|
||||
def test_queue(async_run):
|
||||
async def test_queue():
|
||||
|
||||
NotificationManager.reset()
|
||||
notifications = NotificationManager.instance()
|
||||
with notifications.queue() as queue:
|
||||
assert len(notifications._listeners) == 1
|
||||
|
||||
res = async_run(queue.get(5))
|
||||
res = await queue.get(5)
|
||||
assert res[0] == "ping"
|
||||
|
||||
notifications.emit("test", {"a": 1})
|
||||
res = async_run(queue.get(5))
|
||||
res = await queue.get(5)
|
||||
assert res == ('test', {"a": 1}, {})
|
||||
|
||||
assert len(notifications._listeners) == 0
|
||||
|
||||
|
||||
def test_queue_json(async_run):
|
||||
async def test_queue_json():
|
||||
|
||||
NotificationManager.reset()
|
||||
notifications = NotificationManager.instance()
|
||||
with notifications.queue() as queue:
|
||||
assert len(notifications._listeners) == 1
|
||||
|
||||
res = async_run(queue.get(5))
|
||||
res = await queue.get(5)
|
||||
assert "ping" in res
|
||||
|
||||
notifications.emit("test", {"a": 1})
|
||||
res = async_run(queue.get_json(5))
|
||||
res = await queue.get_json(5)
|
||||
assert res == '{"action": "test", "event": {"a": 1}}'
|
||||
|
||||
assert len(notifications._listeners) == 0
|
||||
|
||||
|
||||
def test_queue_json_meta(async_run):
|
||||
async def test_queue_json_meta():
|
||||
|
||||
NotificationManager.reset()
|
||||
project_id = str(uuid.uuid4())
|
||||
notifications = NotificationManager.instance()
|
||||
with notifications.queue() as queue:
|
||||
assert len(notifications._listeners) == 1
|
||||
|
||||
res = async_run(queue.get(5))
|
||||
res = await queue.get(5)
|
||||
assert "ping" in res
|
||||
|
||||
notifications.emit("test", {"a": 1}, project_id=project_id)
|
||||
res = async_run(queue.get_json(5))
|
||||
res = await queue.get_json(5)
|
||||
assert res == '{"action": "test", "event": {"a": 1}, "project_id": "' + project_id + '"}'
|
||||
|
||||
assert len(notifications._listeners) == 0
|
||||
|
||||
|
||||
def test_queue_ping(async_run):
|
||||
async def test_queue_ping():
|
||||
"""
|
||||
If we don't send a message during a long time (0.5 seconds)
|
||||
a ping is send
|
||||
"""
|
||||
|
||||
NotificationManager.reset()
|
||||
notifications = NotificationManager.instance()
|
||||
with notifications.queue() as queue:
|
||||
assert len(notifications._listeners) == 1
|
||||
|
||||
res = async_run(queue.get(5))
|
||||
res = await queue.get(5)
|
||||
assert res[0] == "ping"
|
||||
|
||||
res = async_run(queue.get(0.5))
|
||||
res = await queue.get(0.5)
|
||||
assert res[0] == "ping"
|
||||
assert res[1]["cpu_usage_percent"] is not None
|
||||
assert len(notifications._listeners) == 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,7 +17,6 @@
|
||||
|
||||
import aiohttp
|
||||
import pytest
|
||||
import sys
|
||||
import uuid
|
||||
from unittest.mock import patch
|
||||
|
||||
@ -26,6 +25,7 @@ from gns3server.compute.project import Project
|
||||
|
||||
|
||||
def test_reserve_tcp_port():
|
||||
|
||||
pm = PortManager()
|
||||
project = Project(project_id=str(uuid.uuid4()))
|
||||
pm.reserve_tcp_port(2001, project)
|
||||
@ -35,6 +35,7 @@ def test_reserve_tcp_port():
|
||||
|
||||
|
||||
def test_reserve_tcp_port_outside_range():
|
||||
|
||||
pm = PortManager()
|
||||
project = Project(project_id=str(uuid.uuid4()))
|
||||
with patch("gns3server.compute.project.Project.emit") as mock_emit:
|
||||
@ -60,7 +61,7 @@ def test_reserve_tcp_port_already_used_by_another_program():
|
||||
|
||||
mock_check.side_effect = execute_mock
|
||||
|
||||
with patch("gns3server.compute.project.Project.emit") as mock_emit:
|
||||
with patch("gns3server.compute.project.Project.emit"):
|
||||
port = pm.reserve_tcp_port(2001, project)
|
||||
assert port != 2001
|
||||
|
||||
@ -68,7 +69,7 @@ def test_reserve_tcp_port_already_used_by_another_program():
|
||||
def test_reserve_tcp_port_already_used():
|
||||
"""
|
||||
This test simulate a scenario where the port is already taken
|
||||
by another programm on the server
|
||||
by another program on the server
|
||||
"""
|
||||
|
||||
pm = PortManager()
|
||||
@ -83,12 +84,13 @@ def test_reserve_tcp_port_already_used():
|
||||
|
||||
mock_check.side_effect = execute_mock
|
||||
|
||||
with patch("gns3server.compute.project.Project.emit") as mock_emit:
|
||||
with patch("gns3server.compute.project.Project.emit"):
|
||||
port = pm.reserve_tcp_port(2001, project)
|
||||
assert port != 2001
|
||||
|
||||
|
||||
def test_reserve_udp_port():
|
||||
|
||||
pm = PortManager()
|
||||
project = Project(project_id=str(uuid.uuid4()))
|
||||
pm.reserve_udp_port(20000, project)
|
||||
@ -97,6 +99,7 @@ def test_reserve_udp_port():
|
||||
|
||||
|
||||
def test_reserve_udp_port_outside_range():
|
||||
|
||||
pm = PortManager()
|
||||
project = Project(project_id=str(uuid.uuid4()))
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
@ -104,6 +107,7 @@ def test_reserve_udp_port_outside_range():
|
||||
|
||||
|
||||
def test_release_udp_port():
|
||||
|
||||
pm = PortManager()
|
||||
project = Project(project_id=str(uuid.uuid4()))
|
||||
pm.reserve_udp_port(20000, project)
|
||||
@ -112,11 +116,13 @@ def test_release_udp_port():
|
||||
|
||||
|
||||
def test_find_unused_port():
|
||||
|
||||
p = PortManager().find_unused_port(1000, 10000)
|
||||
assert p is not None
|
||||
|
||||
|
||||
def test_find_unused_port_invalid_range():
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
p = PortManager().find_unused_port(10000, 1000)
|
||||
|
||||
@ -126,6 +132,7 @@ def test_set_console_host(config):
|
||||
If allow remote connection we need to bind console host
|
||||
to 0.0.0.0
|
||||
"""
|
||||
|
||||
p = PortManager()
|
||||
config.set_section_config("Server", {"allow_remote_console": False})
|
||||
p.console_host = "10.42.1.42"
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -18,11 +18,9 @@
|
||||
|
||||
import os
|
||||
import uuid
|
||||
import json
|
||||
import asyncio
|
||||
import pytest
|
||||
import aiohttp
|
||||
import zipfile
|
||||
from uuid import uuid4
|
||||
from unittest.mock import patch
|
||||
|
||||
@ -34,24 +32,27 @@ from gns3server.config import Config
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = VPCS.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def node(project, manager, loop):
|
||||
node = manager.create_node("test", project.id, "00010203-0405-0607-0809-0a0b0c0d0e0f")
|
||||
return loop.run_until_complete(asyncio.ensure_future(node))
|
||||
async def node(compute_project, manager):
|
||||
|
||||
node = manager.create_node("test", compute_project.id, "00010203-0405-0607-0809-0a0b0c0d0e0f")
|
||||
return await asyncio.ensure_future(node)
|
||||
|
||||
|
||||
def test_affect_uuid():
|
||||
async def test_affect_uuid():
|
||||
|
||||
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f')
|
||||
assert p.id == '00010203-0405-0607-0809-0a0b0c0d0e0f'
|
||||
|
||||
|
||||
def test_clean_tmp_directory(async_run):
|
||||
async def test_clean_tmp_directory():
|
||||
"""
|
||||
The tmp directory should be clean at project open and close
|
||||
"""
|
||||
@ -59,7 +60,7 @@ def test_clean_tmp_directory(async_run):
|
||||
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f')
|
||||
path = p.tmp_working_directory()
|
||||
os.makedirs(path)
|
||||
async_run(p.close())
|
||||
await p.close()
|
||||
assert not os.path.exists(path)
|
||||
|
||||
os.makedirs(path)
|
||||
@ -67,10 +68,9 @@ def test_clean_tmp_directory(async_run):
|
||||
assert not os.path.exists(path)
|
||||
|
||||
|
||||
def test_path(tmpdir):
|
||||
|
||||
directory = Config.instance().get_section_config("Server").get("projects_path")
|
||||
async def test_path(projects_dir):
|
||||
|
||||
directory = projects_dir
|
||||
with patch("gns3server.compute.project.Project.is_local", return_value=True):
|
||||
with patch("gns3server.utils.path.get_default_project_directory", return_value=directory):
|
||||
p = Project(project_id=str(uuid4()))
|
||||
@ -78,27 +78,30 @@ def test_path(tmpdir):
|
||||
assert os.path.exists(os.path.join(directory, p.id))
|
||||
|
||||
|
||||
def test_init_path(tmpdir):
|
||||
async def test_init_path(tmpdir):
|
||||
|
||||
with patch("gns3server.compute.project.Project.is_local", return_value=True):
|
||||
p = Project(path=str(tmpdir), project_id=str(uuid4()))
|
||||
assert p.path == str(tmpdir)
|
||||
|
||||
|
||||
def test_changing_path_not_allowed(tmpdir):
|
||||
async def test_changing_path_not_allowed(tmpdir):
|
||||
|
||||
with patch("gns3server.compute.project.Project.is_local", return_value=False):
|
||||
with pytest.raises(aiohttp.web.HTTPForbidden):
|
||||
p = Project(project_id=str(uuid4()))
|
||||
p.path = str(tmpdir)
|
||||
|
||||
|
||||
def test_variables(tmpdir):
|
||||
async def test_variables():
|
||||
|
||||
variables = [{"name": "VAR1", "value": "VAL1"}]
|
||||
p = Project(project_id=str(uuid4()), variables=variables)
|
||||
assert p.variables == variables
|
||||
|
||||
|
||||
def test_json(tmpdir):
|
||||
async def test_json():
|
||||
|
||||
p = Project(project_id=str(uuid4()))
|
||||
assert p.__json__() == {
|
||||
"name": p.name,
|
||||
@ -107,7 +110,8 @@ def test_json(tmpdir):
|
||||
}
|
||||
|
||||
|
||||
def test_json_with_variables(tmpdir):
|
||||
async def test_json_with_variables():
|
||||
|
||||
variables = [{"name": "VAR1", "value": "VAL1"}]
|
||||
p = Project(project_id=str(uuid4()), variables=variables)
|
||||
assert p.__json__() == {
|
||||
@ -117,18 +121,18 @@ def test_json_with_variables(tmpdir):
|
||||
}
|
||||
|
||||
|
||||
def test_node_working_directory(tmpdir, node):
|
||||
directory = Config.instance().get_section_config("Server").get("projects_path")
|
||||
async def test_node_working_directory(node, projects_dir):
|
||||
|
||||
directory = projects_dir
|
||||
with patch("gns3server.compute.project.Project.is_local", return_value=True):
|
||||
p = Project(project_id=str(uuid4()))
|
||||
assert p.node_working_directory(node) == os.path.join(directory, p.id, 'project-files', node.module_name, node.id)
|
||||
assert os.path.exists(p.node_working_directory(node))
|
||||
|
||||
|
||||
def test_node_working_path(tmpdir, node):
|
||||
directory = Config.instance().get_section_config("Server").get("projects_path")
|
||||
async def test_node_working_path(node, projects_dir):
|
||||
|
||||
directory = projects_dir
|
||||
with patch("gns3server.compute.project.Project.is_local", return_value=True):
|
||||
p = Project(project_id=str(uuid4()))
|
||||
assert p.node_working_path(node) == os.path.join(directory, p.id, 'project-files', node.module_name, node.id)
|
||||
@ -136,40 +140,43 @@ def test_node_working_path(tmpdir, node):
|
||||
assert not os.path.exists(p.node_working_path(node))
|
||||
|
||||
|
||||
def test_project_delete(loop):
|
||||
async def test_project_delete():
|
||||
|
||||
project = Project(project_id=str(uuid4()))
|
||||
directory = project.path
|
||||
assert os.path.exists(directory)
|
||||
loop.run_until_complete(asyncio.ensure_future(project.delete()))
|
||||
await project.delete()
|
||||
assert os.path.exists(directory) is False
|
||||
|
||||
|
||||
def test_project_delete_permission_issue(loop):
|
||||
async def test_project_delete_permission_issue():
|
||||
|
||||
project = Project(project_id=str(uuid4()))
|
||||
directory = project.path
|
||||
assert os.path.exists(directory)
|
||||
os.chmod(directory, 0)
|
||||
with pytest.raises(aiohttp.web.HTTPInternalServerError):
|
||||
loop.run_until_complete(asyncio.ensure_future(project.delete()))
|
||||
await asyncio.ensure_future(project.delete())
|
||||
os.chmod(directory, 700)
|
||||
|
||||
|
||||
def test_project_add_node(manager):
|
||||
async def test_project_add_node(manager):
|
||||
|
||||
project = Project(project_id=str(uuid4()))
|
||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
project.add_node(node)
|
||||
assert len(project.nodes) == 1
|
||||
|
||||
|
||||
def test_project_close(loop, node, project):
|
||||
async def test_project_close(node, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.close") as mock:
|
||||
loop.run_until_complete(asyncio.ensure_future(project.close()))
|
||||
await compute_project.close()
|
||||
assert mock.called
|
||||
assert node.id not in node.manager._nodes
|
||||
|
||||
|
||||
def test_list_files(tmpdir, loop):
|
||||
async def test_list_files(tmpdir):
|
||||
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"projects_path": str(tmpdir)}):
|
||||
project = Project(project_id=str(uuid4()))
|
||||
@ -181,7 +188,7 @@ def test_list_files(tmpdir, loop):
|
||||
with open(os.path.join(path, "test.txt"), "w+") as f:
|
||||
f.write("test2")
|
||||
|
||||
files = loop.run_until_complete(asyncio.ensure_future(project.list_files()))
|
||||
files = await project.list_files()
|
||||
|
||||
assert files == [
|
||||
{
|
||||
@ -195,20 +202,21 @@ def test_list_files(tmpdir, loop):
|
||||
]
|
||||
|
||||
|
||||
def test_emit(async_run):
|
||||
async def test_emit():
|
||||
|
||||
with NotificationManager.instance().queue() as queue:
|
||||
(action, event, context) = async_run(queue.get(0.5)) # Ping
|
||||
await queue.get(0.5) # Ping
|
||||
|
||||
project = Project(project_id=str(uuid4()))
|
||||
project.emit("test", {})
|
||||
(action, event, context) = async_run(queue.get(0.5))
|
||||
(action, event, context) = await queue.get(0.5)
|
||||
assert action == "test"
|
||||
assert context["project_id"] == project.id
|
||||
|
||||
|
||||
def test_update_project(loop):
|
||||
async def test_update_project():
|
||||
|
||||
variables = [{"name": "TEST", "value": "VAL"}]
|
||||
project = Project(project_id=str(uuid.uuid4()))
|
||||
loop.run_until_complete(asyncio.ensure_future(project.update(variables=variables)))
|
||||
await project.update(variables=variables)
|
||||
assert project.variables == variables
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,16 +17,19 @@
|
||||
|
||||
import aiohttp
|
||||
import pytest
|
||||
|
||||
from gns3server.compute.project_manager import ProjectManager
|
||||
|
||||
|
||||
def test_create_project():
|
||||
|
||||
pm = ProjectManager.instance()
|
||||
project = pm.create_project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f')
|
||||
assert project == pm.get_project('00010203-0405-0607-0809-0a0b0c0d0e0f')
|
||||
|
||||
|
||||
def test_project_not_found():
|
||||
|
||||
pm = ProjectManager.instance()
|
||||
with pytest.raises(aiohttp.web.HTTPNotFound):
|
||||
pm.get_project('00010203-0405-0607-0809-000000000000')
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2018 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,10 +17,9 @@
|
||||
|
||||
import pytest
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
from unittest.mock import patch, MagicMock, ANY, PropertyMock
|
||||
from unittest.mock import patch, MagicMock, ANY
|
||||
|
||||
from gns3server.compute.traceng.traceng_vm import TraceNGVM
|
||||
from gns3server.compute.traceng.traceng_error import TraceNGError
|
||||
@ -31,14 +30,16 @@ from gns3server.compute.notification_manager import NotificationManager
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
|
||||
m = TraceNG.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(project, manager, ubridge_path):
|
||||
vm = TraceNGVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
def vm(loop, compute_project, manager, ubridge_path):
|
||||
|
||||
vm = TraceNGVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
vm._start_ubridge = AsyncioMagicMock()
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
vm._ubridge_hypervisor.is_running.return_value = True
|
||||
@ -46,33 +47,36 @@ def vm(project, manager, ubridge_path):
|
||||
|
||||
|
||||
def test_vm(project, manager):
|
||||
|
||||
vm = TraceNGVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
|
||||
|
||||
def test_vm_invalid_traceng_path(vm, manager, loop):
|
||||
async def test_vm_invalid_traceng_path(vm, manager):
|
||||
|
||||
with patch("gns3server.compute.traceng.traceng_vm.TraceNGVM._traceng_path", return_value="/tmp/fake/path/traceng"):
|
||||
with pytest.raises(TraceNGError):
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.port_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.port_add_nio_binding(0, nio)
|
||||
await vm.start()
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0e"
|
||||
|
||||
|
||||
def test_start(loop, vm, async_run):
|
||||
async def test_start(vm):
|
||||
|
||||
process = MagicMock()
|
||||
process.returncode = None
|
||||
|
||||
with NotificationManager.instance().queue() as queue:
|
||||
async_run(queue.get(1)) # Ping
|
||||
await queue.get(1) # Ping
|
||||
|
||||
vm.ip_address = "192.168.1.1"
|
||||
with patch("sys.platform", return_value="win"):
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process) as mock_exec:
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start("192.168.1.2")))
|
||||
await vm.start("192.168.1.2")
|
||||
assert mock_exec.call_args[0] == (vm._traceng_path(),
|
||||
'-u',
|
||||
'-c',
|
||||
@ -88,14 +92,14 @@ def test_start(loop, vm, async_run):
|
||||
'192.168.1.2')
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock_exec.call_args[0])
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
(action, event, kwargs) = await queue.get(1)
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
|
||||
def test_stop(loop, vm, async_run):
|
||||
process = MagicMock()
|
||||
async def test_stop(vm):
|
||||
|
||||
process = MagicMock()
|
||||
# Wait process kill success
|
||||
future = asyncio.Future()
|
||||
future.set_result(True)
|
||||
@ -108,29 +112,29 @@ def test_stop(loop, vm, async_run):
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
nio = TraceNG.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
async_run(vm.port_add_nio_binding(0, nio))
|
||||
await vm.port_add_nio_binding(0, nio)
|
||||
|
||||
vm._ubridge_send = AsyncioMagicMock()
|
||||
async_run(vm.start("192.168.1.2"))
|
||||
await vm.start("192.168.1.2")
|
||||
assert vm.is_running()
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
await vm.stop()
|
||||
assert vm.is_running() is False
|
||||
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
async_run(queue.get(1)) # Ping
|
||||
async_run(queue.get(1)) # Started
|
||||
await queue.get(1) # Ping
|
||||
await queue.get(1) # Started
|
||||
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
(action, event, kwargs) = await queue.get(1)
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
|
||||
def test_reload(loop, vm, async_run):
|
||||
process = MagicMock()
|
||||
async def test_reload(vm):
|
||||
|
||||
process = MagicMock()
|
||||
# Wait process kill success
|
||||
future = asyncio.Future()
|
||||
future.set_result(True)
|
||||
@ -142,14 +146,14 @@ def test_reload(loop, vm, async_run):
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
nio = TraceNG.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
async_run(vm.port_add_nio_binding(0, nio))
|
||||
await vm.port_add_nio_binding(0, nio)
|
||||
|
||||
vm._ubridge_send = AsyncioMagicMock()
|
||||
async_run(vm.start("192.168.1.2"))
|
||||
await vm.start("192.168.1.2")
|
||||
assert vm.is_running()
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
async_run(vm.reload())
|
||||
await vm.reload()
|
||||
assert vm.is_running() is True
|
||||
|
||||
#if sys.platform.startswith("win"):
|
||||
@ -158,24 +162,27 @@ def test_reload(loop, vm, async_run):
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
|
||||
def test_add_nio_binding_udp(vm, async_run):
|
||||
async def test_add_nio_binding_udp(vm):
|
||||
|
||||
nio = TraceNG.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
async_run(vm.port_add_nio_binding(0, nio))
|
||||
await vm.port_add_nio_binding(0, nio)
|
||||
assert nio.lport == 4242
|
||||
|
||||
|
||||
def test_port_remove_nio_binding(loop, vm):
|
||||
async def test_port_remove_nio_binding(vm):
|
||||
|
||||
nio = TraceNG.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.port_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.port_remove_nio_binding(0)))
|
||||
await asyncio.ensure_future(vm.port_add_nio_binding(0, nio))
|
||||
await vm.port_remove_nio_binding(0)
|
||||
assert vm._ethernet_adapter.ports[0] is None
|
||||
|
||||
|
||||
def test_close(vm, port_manager, loop):
|
||||
async def test_close(vm):
|
||||
|
||||
vm.ip_address = "192.168.1.1"
|
||||
with patch("sys.platform", return_value="win"):
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start("192.168.1.2")))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
await vm.start("192.168.1.2")
|
||||
await vm.close()
|
||||
assert vm.is_running() is False
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,8 +20,6 @@ import pytest
|
||||
import tempfile
|
||||
import os
|
||||
import stat
|
||||
import asyncio
|
||||
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
@ -31,19 +29,22 @@ from tests.utils import asyncio_patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = VirtualBox.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
def test_vm_invalid_vboxmanage_path(manager):
|
||||
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"vboxmanage_path": "/bin/test_fake"}):
|
||||
with pytest.raises(VirtualBoxError):
|
||||
manager.find_vboxmanage()
|
||||
|
||||
|
||||
def test_vm_non_executable_vboxmanage_path(manager):
|
||||
|
||||
tmpfile = tempfile.NamedTemporaryFile()
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"vboxmanage_path": tmpfile.name}):
|
||||
with pytest.raises(VirtualBoxError):
|
||||
@ -51,27 +52,28 @@ def test_vm_non_executable_vboxmanage_path(manager):
|
||||
|
||||
|
||||
def test_vm_invalid_executable_name_vboxmanage_path(manager, tmpdir):
|
||||
|
||||
path = str(tmpdir / "vpcs")
|
||||
with open(path, "w+") as f:
|
||||
f.write(path)
|
||||
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
|
||||
tmpfile = tempfile.NamedTemporaryFile()
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"vboxmanage_path": path}):
|
||||
with pytest.raises(VirtualBoxError):
|
||||
manager.find_vboxmanage()
|
||||
|
||||
|
||||
def test_vboxmanage_path(manager, tmpdir):
|
||||
|
||||
path = str(tmpdir / "VBoxManage")
|
||||
with open(path, "w+") as f:
|
||||
f.write(path)
|
||||
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
|
||||
tmpfile = tempfile.NamedTemporaryFile()
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"vboxmanage_path": path}):
|
||||
assert manager.find_vboxmanage() == path
|
||||
|
||||
|
||||
def test_list_vms(manager, loop):
|
||||
async def test_list_vms(manager):
|
||||
|
||||
vm_list = ['"Windows 8.1" {27b4d095-ff5f-4ac4-bb9d-5f2c7861c1f1}',
|
||||
'"Carriage',
|
||||
'Return" {27b4d095-ff5f-4ac4-bb9d-5f2c7861c3f3}',
|
||||
@ -83,7 +85,6 @@ def test_list_vms(manager, loop):
|
||||
if cmd == "list":
|
||||
return vm_list
|
||||
else:
|
||||
print(args)
|
||||
if args[0] == "27b4d095-ff5f-4ac4-bb9d-5f2c7861c1f1":
|
||||
return ["memory=512"]
|
||||
elif args[0] == "ccd8c50b-c172-457d-99fa-dd69371ede0e":
|
||||
@ -92,7 +93,7 @@ def test_list_vms(manager, loop):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.execute") as mock:
|
||||
mock.side_effect = execute_mock
|
||||
vms = loop.run_until_complete(asyncio.ensure_future(manager.list_vms()))
|
||||
vms = await manager.list_vms()
|
||||
assert vms == [
|
||||
{"vmname": "Windows 8.1", "ram": 512},
|
||||
{"vmname": "Linux Microcore 4.7.1", "ram": 256}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -26,30 +26,34 @@ from gns3server.compute.virtualbox import VirtualBox
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
def manager(loop, port_manager):
|
||||
|
||||
m = VirtualBox.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(project, manager):
|
||||
return VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)
|
||||
def vm(compute_project, manager):
|
||||
|
||||
return VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "test", False)
|
||||
|
||||
|
||||
def test_vm(project, manager):
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)
|
||||
def test_vm(compute_project, manager):
|
||||
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "test", False)
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert vm.vmname == "test"
|
||||
|
||||
|
||||
def test_rename_vmname(project, manager, async_run):
|
||||
async def test_rename_vmname(compute_project, manager):
|
||||
"""
|
||||
Rename a VM is not allowed when using a running linked clone
|
||||
or if the vm already exists in Vbox
|
||||
"""
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)
|
||||
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "test", False)
|
||||
vm.manager.list_vms = AsyncioMagicMock(return_value=[{"vmname": "Debian"}])
|
||||
vm._linked_clone = True
|
||||
vm._modify_vm = AsyncioMagicMock()
|
||||
@ -57,42 +61,46 @@ def test_rename_vmname(project, manager, async_run):
|
||||
# Vm is running
|
||||
vm._node_status = "started"
|
||||
with pytest.raises(VirtualBoxError):
|
||||
async_run(vm.set_vmname("Arch"))
|
||||
await vm.set_vmname("Arch")
|
||||
assert not vm._modify_vm.called
|
||||
|
||||
vm._node_status = "stopped"
|
||||
|
||||
# Name already use
|
||||
with pytest.raises(VirtualBoxError):
|
||||
async_run(vm.set_vmname("Debian"))
|
||||
await vm.set_vmname("Debian")
|
||||
assert not vm._modify_vm.called
|
||||
|
||||
# Work
|
||||
async_run(vm.set_vmname("Arch"))
|
||||
await vm.set_vmname("Arch")
|
||||
assert vm._modify_vm.called
|
||||
|
||||
|
||||
def test_vm_valid_virtualbox_api_version(loop, project, manager):
|
||||
async def test_vm_valid_virtualbox_api_version(compute_project, manager):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.execute", return_value=["API version: 4_3"]):
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "test", False)
|
||||
vm._uuid = "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
await vm.create()
|
||||
|
||||
|
||||
def test_vm_invalid_virtualbox_api_version(loop, project, manager):
|
||||
async def test_vm_invalid_virtualbox_api_version(compute_project, manager):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.execute", return_value=["API version: 4_2"]):
|
||||
with pytest.raises(VirtualBoxError):
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "test", False)
|
||||
await vm.create()
|
||||
|
||||
|
||||
def test_vm_adapter_add_nio_binding_adapter_not_exist(loop, vm, manager, free_console_port):
|
||||
async def test_vm_adapter_add_nio_binding_adapter_not_exist(vm, manager, free_console_port):
|
||||
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
with pytest.raises(VirtualBoxError):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(15, nio)))
|
||||
await vm.adapter_add_nio_binding(15, nio)
|
||||
|
||||
|
||||
def test_json(vm, tmpdir, project):
|
||||
|
||||
assert vm.__json__()["node_directory"] is None
|
||||
project._path = str(tmpdir)
|
||||
vm._linked_clone = True
|
||||
@ -100,12 +108,14 @@ def test_json(vm, tmpdir, project):
|
||||
|
||||
|
||||
def test_patch_vm_uuid(vm):
|
||||
|
||||
xml = """<?xml version="1.0"?>
|
||||
<VirtualBox xmlns="http://www.virtualbox.org/" version="1.16-macosx">
|
||||
<Machine uuid="{f8138a63-e361-49ee-a5a4-ba0559bc00e2}" name="Debian-1" OSType="Debian_64" currentSnapshot="{8bd00b14-4c14-4992-a165-cb09e80fe8e4 }" snapshotFolder="Snapshots" lastStateChange="2016-10-28T12:54:26Z">
|
||||
</Machine>
|
||||
</VirtualBox>
|
||||
"""
|
||||
|
||||
os.makedirs(os.path.join(vm.working_dir, vm._vmname), exist_ok=True)
|
||||
with open(vm._linked_vbox_file(), "w+") as f:
|
||||
f.write(xml)
|
||||
@ -117,6 +127,7 @@ def test_patch_vm_uuid(vm):
|
||||
|
||||
|
||||
def test_patch_vm_uuid_with_corrupted_file(vm):
|
||||
|
||||
xml = """<?xml version="1.0"?>
|
||||
<VirtualBox>
|
||||
"""
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,26 +17,20 @@
|
||||
|
||||
|
||||
import pytest
|
||||
import tempfile
|
||||
import os
|
||||
import stat
|
||||
import asyncio
|
||||
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from gns3server.compute.vmware import VMware
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = VMware.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
def test_parse_vmware_file(manager, tmpdir):
|
||||
def test_parse_vmware_file(tmpdir):
|
||||
|
||||
path = str(tmpdir / "test.vmx")
|
||||
with open(path, "w+") as f:
|
||||
f.write('displayname = "GNS3 VM"\nguestOS = "ubuntu-64"')
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,57 +17,58 @@
|
||||
|
||||
import pytest
|
||||
import asyncio
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.compute.vmware.vmware_vm import VMwareVM
|
||||
from gns3server.compute.vmware.vmware_error import VMwareError
|
||||
from gns3server.compute.vmware import VMware
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
|
||||
m = VMware.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(project, manager, tmpdir):
|
||||
async def vm(loop, compute_project, manager, tmpdir):
|
||||
|
||||
fake_vmx = str(tmpdir / "test.vmx")
|
||||
open(fake_vmx, "w+").close()
|
||||
|
||||
return VMwareVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, fake_vmx, False)
|
||||
return VMwareVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, fake_vmx, False)
|
||||
|
||||
|
||||
def test_vm(project, manager, vm):
|
||||
def test_vm(vm):
|
||||
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
|
||||
|
||||
def test_json(vm, tmpdir, project):
|
||||
def test_json(vm, tmpdir, compute_project):
|
||||
|
||||
assert vm.__json__()["node_directory"] is not None
|
||||
project._path = str(tmpdir)
|
||||
compute_project._path = str(tmpdir)
|
||||
vm._linked_clone = True
|
||||
assert vm.__json__()["node_directory"] is not None
|
||||
|
||||
|
||||
def test_start_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
async def test_start_capture(vm, tmpdir, manager, free_console_port):
|
||||
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
vm.adapters = 1
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start_capture(0, output_file)))
|
||||
await vm.adapter_add_nio_binding(0, nio)
|
||||
await vm.start_capture(0, output_file)
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing
|
||||
|
||||
|
||||
def test_stop_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
async def test_stop_capture(vm, tmpdir, manager, free_console_port):
|
||||
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
vm.adapters = 1
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(vm.start_capture(0, output_file))
|
||||
await vm.adapter_add_nio_binding(0, nio)
|
||||
await vm.start_capture(0, output_file)
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop_capture(0)))
|
||||
await asyncio.ensure_future(vm.stop_capture(0))
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing is False
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -25,7 +25,8 @@ from gns3server.compute.vpcs.vpcs_error import VPCSError
|
||||
from gns3server.compute.project_manager import ProjectManager
|
||||
|
||||
|
||||
def test_get_mac_id(loop, project, port_manager):
|
||||
async def test_get_mac_id(compute_project, port_manager):
|
||||
|
||||
# Cleanup the VPCS object
|
||||
VPCS._instance = None
|
||||
vpcs = VPCS.instance()
|
||||
@ -33,17 +34,18 @@ def test_get_mac_id(loop, project, port_manager):
|
||||
vm1_id = str(uuid.uuid4())
|
||||
vm2_id = str(uuid.uuid4())
|
||||
vm3_id = str(uuid.uuid4())
|
||||
loop.run_until_complete(vpcs.create_node("PC 1", project.id, vm1_id))
|
||||
loop.run_until_complete(vpcs.create_node("PC 2", project.id, vm2_id))
|
||||
await vpcs.create_node("PC 1", compute_project.id, vm1_id)
|
||||
await vpcs.create_node("PC 2", compute_project.id, vm2_id)
|
||||
assert vpcs.get_mac_id(vm1_id) == 0
|
||||
assert vpcs.get_mac_id(vm1_id) == 0
|
||||
assert vpcs.get_mac_id(vm2_id) == 1
|
||||
loop.run_until_complete(vpcs.delete_node(vm1_id))
|
||||
loop.run_until_complete(vpcs.create_node("PC 3", project.id, vm3_id))
|
||||
await vpcs.delete_node(vm1_id)
|
||||
await vpcs.create_node("PC 3", compute_project.id, vm3_id)
|
||||
assert vpcs.get_mac_id(vm3_id) == 0
|
||||
|
||||
|
||||
def test_get_mac_id_multiple_project(loop, port_manager):
|
||||
async def test_get_mac_id_multiple_project(port_manager):
|
||||
|
||||
# Cleanup the VPCS object
|
||||
VPCS._instance = None
|
||||
vpcs = VPCS.instance()
|
||||
@ -53,15 +55,16 @@ def test_get_mac_id_multiple_project(loop, port_manager):
|
||||
vm3_id = str(uuid.uuid4())
|
||||
project1 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4()))
|
||||
project2 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4()))
|
||||
loop.run_until_complete(vpcs.create_node("PC 1", project1.id, vm1_id))
|
||||
loop.run_until_complete(vpcs.create_node("PC 2", project1.id, vm2_id))
|
||||
loop.run_until_complete(vpcs.create_node("PC 2", project2.id, vm3_id))
|
||||
await vpcs.create_node("PC 1", project1.id, vm1_id)
|
||||
await vpcs.create_node("PC 2", project1.id, vm2_id)
|
||||
await vpcs.create_node("PC 2", project2.id, vm3_id)
|
||||
assert vpcs.get_mac_id(vm1_id) == 0
|
||||
assert vpcs.get_mac_id(vm2_id) == 1
|
||||
assert vpcs.get_mac_id(vm3_id) == 0
|
||||
|
||||
|
||||
def test_get_mac_id_no_id_available(loop, project, port_manager):
|
||||
async def test_get_mac_id_no_id_available(compute_project, port_manager):
|
||||
|
||||
# Cleanup the VPCS object
|
||||
VPCS._instance = None
|
||||
vpcs = VPCS.instance()
|
||||
@ -69,5 +72,5 @@ def test_get_mac_id_no_id_available(loop, project, port_manager):
|
||||
with pytest.raises(VPCSError):
|
||||
for i in range(0, 256):
|
||||
node_id = str(uuid.uuid4())
|
||||
loop.run_until_complete(vpcs.create_node("PC {}".format(i), project.id, node_id))
|
||||
await vpcs.create_node("PC {}".format(i), compute_project.id, node_id)
|
||||
assert vpcs.get_mac_id(node_id) == i
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,7 +16,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
@ -32,15 +31,17 @@ from gns3server.compute.notification_manager import NotificationManager
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manager(port_manager):
|
||||
async def manager(loop, port_manager):
|
||||
|
||||
m = VPCS.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(project, manager, ubridge_path):
|
||||
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
async def vm(loop, compute_project, manager, ubridge_path):
|
||||
|
||||
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
vm._vpcs_version = parse_version("0.9")
|
||||
vm._start_ubridge = AsyncioMagicMock()
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
@ -48,55 +49,61 @@ def vm(project, manager, ubridge_path):
|
||||
return vm
|
||||
|
||||
|
||||
def test_vm(project, manager):
|
||||
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
async def test_vm(compute_project, manager):
|
||||
|
||||
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager)
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
|
||||
|
||||
def test_vm_check_vpcs_version(loop, vm, manager):
|
||||
async def test_vm_check_vpcs_version(vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.subprocess_check_output", return_value="Welcome to Virtual PC Simulator, version 0.9"):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_vpcs_version()))
|
||||
await asyncio.ensure_future(vm._check_vpcs_version())
|
||||
assert vm._vpcs_version == parse_version("0.9")
|
||||
|
||||
|
||||
def test_vm_check_vpcs_version_0_6_1(loop, vm, manager):
|
||||
async def test_vm_check_vpcs_version_0_6_1(vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.subprocess_check_output", return_value="Welcome to Virtual PC Simulator, version 0.6.1"):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_vpcs_version()))
|
||||
await vm._check_vpcs_version()
|
||||
assert vm._vpcs_version == parse_version("0.6.1")
|
||||
|
||||
|
||||
def test_vm_invalid_vpcs_version(loop, manager, vm):
|
||||
async def test_vm_invalid_vpcs_version(vm, manager):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.subprocess_check_output", return_value="Welcome to Virtual PC Simulator, version 0.1"):
|
||||
with pytest.raises(VPCSError):
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.port_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_vpcs_version()))
|
||||
await asyncio.ensure_future(vm.port_add_nio_binding(0, nio))
|
||||
await asyncio.ensure_future(vm._check_vpcs_version())
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
|
||||
|
||||
def test_vm_invalid_vpcs_path(vm, manager, loop):
|
||||
async def test_vm_invalid_vpcs_path(vm, manager):
|
||||
|
||||
with patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM._vpcs_path", return_value="/tmp/fake/path/vpcs"):
|
||||
with pytest.raises(VPCSError):
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.port_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await asyncio.ensure_future(vm.port_add_nio_binding(0, nio))
|
||||
await asyncio.ensure_future(vm.start())
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0e"
|
||||
|
||||
|
||||
def test_start(loop, vm, async_run):
|
||||
async def test_start(vm):
|
||||
|
||||
process = MagicMock()
|
||||
process.returncode = None
|
||||
|
||||
with NotificationManager.instance().queue() as queue:
|
||||
async_run(queue.get(1)) # Ping
|
||||
await queue.get(1) # Ping
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process) as mock_exec:
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_wrap_console"):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
await vm.start()
|
||||
assert mock_exec.call_args[0] == (vm._vpcs_path(),
|
||||
'-p',
|
||||
str(vm._internal_console_port),
|
||||
@ -113,16 +120,17 @@ def test_start(loop, vm, async_run):
|
||||
'127.0.0.1')
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock_exec.call_args[0])
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
(action, event, kwargs) = await queue.get(1)
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
|
||||
def test_start_0_6_1(loop, vm, async_run):
|
||||
async def test_start_0_6_1(vm):
|
||||
"""
|
||||
Version 0.6.1 doesn't have the -R options. It's not require
|
||||
because GNS3 provide a patch for this.
|
||||
"""
|
||||
|
||||
process = MagicMock()
|
||||
process.returncode = None
|
||||
vm._vpcs_version = parse_version("0.6.1")
|
||||
@ -131,8 +139,8 @@ def test_start_0_6_1(loop, vm, async_run):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process) as mock_exec:
|
||||
nio = VPCS.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
async_run(vm.port_add_nio_binding(0, nio))
|
||||
async_run(vm.start())
|
||||
await vm.port_add_nio_binding(0, nio)
|
||||
await vm.start()
|
||||
assert mock_exec.call_args[0] == (vm._vpcs_path(),
|
||||
'-p',
|
||||
str(vm._internal_console_port),
|
||||
@ -149,9 +157,9 @@ def test_start_0_6_1(loop, vm, async_run):
|
||||
assert vm.is_running()
|
||||
|
||||
|
||||
def test_stop(loop, vm, async_run):
|
||||
process = MagicMock()
|
||||
async def test_stop(vm):
|
||||
|
||||
process = MagicMock()
|
||||
# Wait process kill success
|
||||
future = asyncio.Future()
|
||||
future.set_result(True)
|
||||
@ -163,13 +171,13 @@ def test_stop(loop, vm, async_run):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
nio = VPCS.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
async_run(vm.port_add_nio_binding(0, nio))
|
||||
await vm.port_add_nio_binding(0, nio)
|
||||
|
||||
async_run(vm.start())
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
await asyncio.ensure_future(vm.stop())
|
||||
assert vm.is_running() is False
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
@ -177,17 +185,17 @@ def test_stop(loop, vm, async_run):
|
||||
else:
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
async_run(queue.get(1)) # Ping
|
||||
async_run(queue.get(1)) # Started
|
||||
await queue.get(1) # Ping
|
||||
await queue.get(1) # Started
|
||||
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
(action, event, kwargs) = await queue.get(1)
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
|
||||
def test_reload(loop, vm, async_run):
|
||||
process = MagicMock()
|
||||
async def test_reload(vm):
|
||||
|
||||
process = MagicMock()
|
||||
# Wait process kill success
|
||||
future = asyncio.Future()
|
||||
future.set_result(True)
|
||||
@ -198,13 +206,13 @@ def test_reload(loop, vm, async_run):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
nio = VPCS.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
async_run(vm.port_add_nio_binding(0, nio))
|
||||
async_run(vm.start())
|
||||
await vm.port_add_nio_binding(0, nio)
|
||||
await vm.start()
|
||||
assert vm.is_running()
|
||||
|
||||
vm._ubridge_send = AsyncioMagicMock()
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
async_run(vm.reload())
|
||||
await vm.reload()
|
||||
assert vm.is_running() is True
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
@ -213,28 +221,32 @@ def test_reload(loop, vm, async_run):
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
|
||||
def test_add_nio_binding_udp(vm, async_run):
|
||||
async def test_add_nio_binding_udp(vm):
|
||||
|
||||
nio = VPCS.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
async_run(vm.port_add_nio_binding(0, nio))
|
||||
await vm.port_add_nio_binding(0, nio)
|
||||
assert nio.lport == 4242
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_add_nio_binding_tap(vm, ethernet_device, loop):
|
||||
async def test_add_nio_binding_tap(vm, ethernet_device):
|
||||
|
||||
with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True):
|
||||
nio = VPCS.instance().create_nio({"type": "nio_tap", "tap_device": ethernet_device})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.port_add_nio_binding(0, nio)))
|
||||
await asyncio.ensure_future(vm.port_add_nio_binding(0, nio))
|
||||
assert nio.tap_device == ethernet_device
|
||||
|
||||
|
||||
def test_port_remove_nio_binding(vm, loop):
|
||||
async def test_port_remove_nio_binding(vm):
|
||||
|
||||
nio = VPCS.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.port_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.port_remove_nio_binding(0)))
|
||||
await asyncio.ensure_future(vm.port_add_nio_binding(0, nio))
|
||||
await vm.port_remove_nio_binding(0)
|
||||
assert vm._ethernet_adapter.ports[0] is None
|
||||
|
||||
|
||||
def test_update_startup_script(vm):
|
||||
|
||||
content = "echo GNS3 VPCS\nip 192.168.1.2\n"
|
||||
vm.startup_script = content
|
||||
filepath = os.path.join(vm.working_dir, 'startup.vpc')
|
||||
@ -244,6 +256,7 @@ def test_update_startup_script(vm):
|
||||
|
||||
|
||||
def test_update_startup_script_h(vm):
|
||||
|
||||
content = "set pcname %h\n"
|
||||
vm.name = "pc1"
|
||||
vm.startup_script = content
|
||||
@ -253,12 +266,14 @@ def test_update_startup_script_h(vm):
|
||||
|
||||
|
||||
def test_update_startup_script_with_escaping_characters_in_name(vm):
|
||||
|
||||
vm.startup_script = "set pcname initial-name\n"
|
||||
vm.name = "test\\"
|
||||
assert vm.startup_script == "set pcname test{}".format(os.linesep)
|
||||
|
||||
|
||||
def test_get_startup_script(vm):
|
||||
|
||||
content = "echo GNS3 VPCS\nip 192.168.1.2"
|
||||
vm.startup_script = content
|
||||
assert vm.startup_script == os.linesep.join(["echo GNS3 VPCS", "ip 192.168.1.2"])
|
||||
@ -278,7 +293,8 @@ def test_get_startup_script_using_default_script(vm):
|
||||
assert vm.script_file == filepath
|
||||
|
||||
|
||||
def test_change_name(vm, tmpdir):
|
||||
def test_change_name(vm):
|
||||
|
||||
path = os.path.join(vm.working_dir, 'startup.vpc')
|
||||
vm.name = "world"
|
||||
with open(path, 'w+') as f:
|
||||
@ -296,11 +312,11 @@ def test_change_name(vm, tmpdir):
|
||||
assert f.read() == "set pcname beta"
|
||||
|
||||
|
||||
def test_close(vm, port_manager, loop):
|
||||
async def test_close(vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_wrap_console"):
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
await asyncio.ensure_future(vm.start())
|
||||
await asyncio.ensure_future(vm.close())
|
||||
assert vm.is_running() is False
|
||||
|
@ -1,204 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import gc
|
||||
import pytest
|
||||
import socket
|
||||
import asyncio
|
||||
import tempfile
|
||||
import weakref
|
||||
import shutil
|
||||
import os
|
||||
import sys
|
||||
import aiohttp
|
||||
import weakref
|
||||
|
||||
from aiohttp import web
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
from pathlib import Path
|
||||
|
||||
from gns3server.web.route import Route
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.config import Config
|
||||
from gns3server.compute import MODULES
|
||||
from gns3server.compute.port_manager import PortManager
|
||||
from gns3server.compute.project_manager import ProjectManager
|
||||
# this import will register all handlers
|
||||
from gns3server.handlers import *
|
||||
|
||||
from .handlers.api.base import Query
|
||||
|
||||
sys._called_from_test = True
|
||||
sys.original_platform = sys.platform
|
||||
|
||||
# Prevent execution of external binaries
|
||||
os.environ["PATH"] = tempfile.mkdtemp()
|
||||
|
||||
from gns3server.config import Config
|
||||
from gns3server.web.route import Route
|
||||
# TODO: get rid of *
|
||||
from gns3server.handlers import *
|
||||
from gns3server.compute import MODULES
|
||||
from gns3server.compute.port_manager import PortManager
|
||||
from gns3server.compute.project_manager import ProjectManager
|
||||
from gns3server.controller import Controller
|
||||
from tests.handlers.api.base import Query
|
||||
@pytest.fixture(scope='function')
|
||||
async def http_client(aiohttp_client):
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def restore_original_path():
|
||||
"""
|
||||
Temporary restore a standard path environnement. This allow
|
||||
to run external binaries.
|
||||
"""
|
||||
os.environ["PATH"] = "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
||||
yield
|
||||
os.environ["PATH"] = tempfile.mkdtemp()
|
||||
|
||||
|
||||
@pytest.yield_fixture(scope="session")
|
||||
def loop(request):
|
||||
"""Return an event loop and destroy it at the end of test"""
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop) # Replace main loop to avoid conflict between tests
|
||||
yield loop
|
||||
#loop.close()
|
||||
asyncio.set_event_loop(None)
|
||||
|
||||
|
||||
def _get_unused_port():
|
||||
""" Return an unused port on localhost. In rare occasion it can return
|
||||
an already used port (race condition)"""
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind(('localhost', 0))
|
||||
addr, port = s.getsockname()
|
||||
s.close()
|
||||
return port
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def client(aiohttp_client):
|
||||
"""
|
||||
Return an helper allowing you to call the server without any prefix
|
||||
"""
|
||||
app = web.Application()
|
||||
app['websockets'] = weakref.WeakSet()
|
||||
for method, route, handler in Route.get_routes():
|
||||
app.router.add_route(method, route, handler)
|
||||
return await aiohttp_client(app)
|
||||
|
||||
@pytest.yield_fixture
|
||||
def http_server(request, loop, port_manager, monkeypatch, controller):
|
||||
"""A GNS3 server"""
|
||||
|
||||
app = web.Application()
|
||||
for method, route, handler in Route.get_routes():
|
||||
app.router.add_route(method, route, handler)
|
||||
|
||||
# Keep a list of active websocket connections
|
||||
app['websockets'] = weakref.WeakSet()
|
||||
|
||||
host = "127.0.0.1"
|
||||
|
||||
# We try multiple time. Because on Travis test can fail when because the port is taken by someone else
|
||||
for i in range(0, 5):
|
||||
port = _get_unused_port()
|
||||
try:
|
||||
|
||||
runner = web.AppRunner(app)
|
||||
loop.run_until_complete(runner.setup())
|
||||
site = web.TCPSite(runner, host, port)
|
||||
loop.run_until_complete(site.start())
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
break
|
||||
|
||||
yield (host, port)
|
||||
|
||||
# close websocket connections
|
||||
for ws in set(app['websockets']):
|
||||
loop.run_until_complete(ws.close(code=aiohttp.WSCloseCode.GOING_AWAY, message='Server shutdown'))
|
||||
|
||||
loop.run_until_complete(controller.stop())
|
||||
for module in MODULES:
|
||||
instance = module.instance()
|
||||
monkeypatch.setattr('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.close', lambda self: True)
|
||||
loop.run_until_complete(instance.unload())
|
||||
|
||||
loop.run_until_complete(runner.cleanup())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def http_root(loop, http_server):
|
||||
"""
|
||||
Return an helper allowing you to call the server without any prefix
|
||||
"""
|
||||
host, port = http_server
|
||||
return Query(loop, host=host, port=port)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def http_controller(loop, http_server):
|
||||
"""
|
||||
Return an helper allowing you to call the server API without any prefix
|
||||
"""
|
||||
host, port = http_server
|
||||
return Query(loop, host=host, port=port, api_version=2)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def http_compute(loop, http_server):
|
||||
"""
|
||||
Return an helper allowing you to call the hypervisor API via HTTP
|
||||
"""
|
||||
host, port = http_server
|
||||
return Query(loop, host=host, port=port, prefix="/compute", api_version=2)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def project(tmpdir):
|
||||
"""A GNS3 lab"""
|
||||
|
||||
p = ProjectManager.instance().create_project(project_id="a1e920ca-338a-4e9f-b363-aa607b09dd80")
|
||||
return p
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def port_manager():
|
||||
"""An instance of port manager"""
|
||||
PortManager._instance = None
|
||||
p = PortManager.instance()
|
||||
p.console_host = "127.0.0.1"
|
||||
return p
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def free_console_port(request, port_manager, project):
|
||||
"""Get a free TCP port"""
|
||||
|
||||
# In case of already use ports we will raise an exception
|
||||
port = port_manager.get_free_tcp_port(project)
|
||||
# We release the port immediately in order to allow
|
||||
# the test do whatever the test want
|
||||
port_manager.release_tcp_port(port, project)
|
||||
return port
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ethernet_device():
|
||||
import psutil
|
||||
return sorted(psutil.net_if_addrs().keys())[0]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def controller_config_path(tmpdir):
|
||||
|
||||
return str(tmpdir / "config" / "gns3_controller.conf")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def controller(tmpdir, controller_config_path):
|
||||
|
||||
Controller._instance = None
|
||||
controller = Controller.instance()
|
||||
os.makedirs(os.path.dirname(controller_config_path), exist_ok=True)
|
||||
@ -208,17 +50,184 @@ def controller(tmpdir, controller_config_path):
|
||||
return controller
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute(controller):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "example.com"
|
||||
controller._computes = {"example.com": compute}
|
||||
return compute
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def project(loop, tmpdir, controller):
|
||||
|
||||
return await controller.add_project(name="Test")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute_project(tmpdir):
|
||||
|
||||
return ProjectManager.instance().create_project(project_id="a1e920ca-338a-4e9f-b363-aa607b09dd80")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute_api(http_client):
|
||||
"""
|
||||
Return an helper allowing you to call the hypervisor API via HTTP
|
||||
"""
|
||||
|
||||
return Query(http_client, prefix="/compute", api_version=2)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def controller_api(http_client, controller):
|
||||
"""
|
||||
Return an helper allowing you to call the server API without any prefix
|
||||
"""
|
||||
|
||||
return Query(http_client, api_version=2)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config():
|
||||
|
||||
config = Config.instance()
|
||||
config.clear()
|
||||
return config
|
||||
|
||||
|
||||
@pytest.yield_fixture(autouse=True)
|
||||
def run_around_tests(monkeypatch, port_manager, controller, config):
|
||||
@pytest.fixture
|
||||
def images_dir(config):
|
||||
"""
|
||||
This setup a temporay project file environnement around tests
|
||||
Get the location of images
|
||||
"""
|
||||
|
||||
path = config.get_section_config("Server").get("images_path")
|
||||
os.makedirs(path, exist_ok=True)
|
||||
os.makedirs(os.path.join(path, "QEMU"))
|
||||
os.makedirs(os.path.join(path, "IOU"))
|
||||
return path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def symbols_dir(config):
|
||||
"""
|
||||
Get the location of symbols
|
||||
"""
|
||||
|
||||
path = config.get_section_config("Server").get("symbols_path")
|
||||
os.makedirs(path, exist_ok=True)
|
||||
print(path)
|
||||
return path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def projects_dir(config):
|
||||
"""
|
||||
Get the location of images
|
||||
"""
|
||||
|
||||
path = config.get_section_config("Server").get("projects_path")
|
||||
os.makedirs(path, exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def port_manager():
|
||||
"""An instance of port manager"""
|
||||
|
||||
PortManager._instance = None
|
||||
p = PortManager.instance()
|
||||
p.console_host = "127.0.0.1"
|
||||
return p
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def free_console_port(port_manager, compute_project):
|
||||
"""Get a free TCP port"""
|
||||
|
||||
# In case of already use ports we will raise an exception
|
||||
port = port_manager.get_free_tcp_port(compute_project)
|
||||
# We release the port immediately in order to allow
|
||||
# the test do whatever the test want
|
||||
port_manager.release_tcp_port(port, compute_project)
|
||||
return port
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def darwin_platform():
|
||||
"""
|
||||
Change sys.plaform to Darwin
|
||||
"""
|
||||
|
||||
old_platform = sys.platform
|
||||
sys.platform = "darwin10.10"
|
||||
yield
|
||||
sys.plaform = old_platform
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def windows_platform():
|
||||
"""
|
||||
Change sys.platform to Windows
|
||||
"""
|
||||
|
||||
old_platform = sys.platform
|
||||
sys.platform = "win10"
|
||||
yield
|
||||
sys.plaform = old_platform
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def linux_platform():
|
||||
"""
|
||||
Change sys.platform to Linux
|
||||
"""
|
||||
|
||||
old_platform = sys.platform
|
||||
sys.platform = "linuxdebian"
|
||||
yield
|
||||
sys.plaform = old_platform
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def on_gns3vm(linux_platform):
|
||||
"""
|
||||
Mock the hostname to emulate the GNS3 VM
|
||||
"""
|
||||
|
||||
with patch("gns3server.utils.interfaces.interfaces", return_value=[
|
||||
{"name": "eth0", "special": False, "type": "ethernet"},
|
||||
{"name": "eth1", "special": False, "type": "ethernet"},
|
||||
{"name": "virbr0", "special": True, "type": "ethernet"}]):
|
||||
with patch("socket.gethostname", return_value="gns3vm"):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ethernet_device():
|
||||
|
||||
import psutil
|
||||
return sorted(psutil.net_if_addrs().keys())[0]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ubridge_path(config):
|
||||
"""
|
||||
Get the location of a fake ubridge
|
||||
"""
|
||||
|
||||
path = config.get_section_config("Server").get("ubridge_path")
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
open(path, 'w+').close()
|
||||
return path
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def run_around_tests(monkeypatch, config, port_manager):#port_manager, controller, config):
|
||||
"""
|
||||
This setup a temporary project file environment around tests
|
||||
"""
|
||||
|
||||
tmppath = tempfile.mkdtemp()
|
||||
@ -255,101 +264,3 @@ def run_around_tests(monkeypatch, port_manager, controller, config):
|
||||
shutil.rmtree(tmppath)
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def images_dir(config):
|
||||
"""
|
||||
Get the location of images
|
||||
"""
|
||||
path = config.get_section_config("Server").get("images_path")
|
||||
os.makedirs(path, exist_ok=True)
|
||||
os.makedirs(os.path.join(path, "QEMU"))
|
||||
os.makedirs(os.path.join(path, "IOU"))
|
||||
return path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def symbols_dir(config):
|
||||
"""
|
||||
Get the location of symbols
|
||||
"""
|
||||
path = config.get_section_config("Server").get("symbols_path")
|
||||
os.makedirs(path, exist_ok=True)
|
||||
print(path)
|
||||
return path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def projects_dir(config):
|
||||
"""
|
||||
Get the location of images
|
||||
"""
|
||||
path = config.get_section_config("Server").get("projects_path")
|
||||
os.makedirs(path, exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ubridge_path(config):
|
||||
"""
|
||||
Get the location of a fake ubridge
|
||||
"""
|
||||
path = config.get_section_config("Server").get("ubridge_path")
|
||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||
open(path, 'w+').close()
|
||||
return path
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def darwin_platform():
|
||||
"""
|
||||
Change sys.plaform to Darwin
|
||||
"""
|
||||
old_platform = sys.platform
|
||||
sys.platform = "darwin10.10"
|
||||
yield
|
||||
sys.plaform = old_platform
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def windows_platform():
|
||||
"""
|
||||
Change sys.platform to Windows
|
||||
"""
|
||||
old_platform = sys.platform
|
||||
sys.platform = "win10"
|
||||
yield
|
||||
sys.plaform = old_platform
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def linux_platform():
|
||||
"""
|
||||
Change sys.platform to Linux
|
||||
"""
|
||||
old_platform = sys.platform
|
||||
sys.platform = "linuxdebian"
|
||||
yield
|
||||
sys.plaform = old_platform
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def async_run(loop):
|
||||
"""
|
||||
Shortcut for running in asyncio loop
|
||||
"""
|
||||
return lambda x: loop.run_until_complete(asyncio.ensure_future(x))
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def on_gns3vm(linux_platform):
|
||||
"""
|
||||
Mock the hostname to emulate the GNS3 VM
|
||||
"""
|
||||
with patch("gns3server.utils.interfaces.interfaces", return_value=[
|
||||
{"name": "eth0", "special": False, "type": "ethernet"},
|
||||
{"name": "eth1", "special": False, "type": "ethernet"},
|
||||
{"name": "virbr0", "special": True, "type": "ethernet"}]):
|
||||
with patch("socket.gethostname", return_value="gns3vm"):
|
||||
yield
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -23,25 +23,30 @@ from gns3server.controller.gns3vm.gns3_vm_error import GNS3VMError
|
||||
|
||||
@pytest.fixture
|
||||
def gns3vm(controller):
|
||||
|
||||
return RemoteGNS3VM(controller)
|
||||
|
||||
|
||||
def test_list(async_run, gns3vm, controller):
|
||||
async_run(controller.add_compute("r1", name="R1", host="r1.local", connect=False))
|
||||
res = async_run(gns3vm.list())
|
||||
async def test_list(gns3vm, controller):
|
||||
|
||||
await controller.add_compute("r1", name="R1", host="r1.local", connect=False)
|
||||
res = await gns3vm.list()
|
||||
assert res == [{"vmname": "R1"}]
|
||||
|
||||
|
||||
def test_start(async_run, gns3vm, controller):
|
||||
async_run(controller.add_compute("r1", name="R1",
|
||||
protocol="https",
|
||||
host="r1.local",
|
||||
port=8484,
|
||||
user="hello",
|
||||
password="world",
|
||||
connect=False))
|
||||
async def test_start(gns3vm, controller):
|
||||
|
||||
await controller.add_compute("r1",
|
||||
name="R1",
|
||||
protocol="https",
|
||||
host="r1.local",
|
||||
port=8484,
|
||||
user="hello",
|
||||
password="world",
|
||||
connect=False)
|
||||
|
||||
gns3vm.vmname = "R1"
|
||||
res = async_run(gns3vm.start())
|
||||
await gns3vm.start()
|
||||
assert gns3vm.running
|
||||
assert gns3vm.protocol == "https"
|
||||
assert gns3vm.ip_address == "r1.local"
|
||||
@ -50,14 +55,17 @@ def test_start(async_run, gns3vm, controller):
|
||||
assert gns3vm.password == "world"
|
||||
|
||||
|
||||
def test_start_invalid_vm(async_run, gns3vm, controller):
|
||||
async_run(controller.add_compute("r1", name="R1",
|
||||
protocol="https",
|
||||
host="r1.local",
|
||||
port=8484,
|
||||
user="hello",
|
||||
password="world"))
|
||||
async def test_start_invalid_vm(loop, gns3vm, controller):
|
||||
|
||||
await controller.add_compute("r1",
|
||||
name="R1",
|
||||
protocol="https",
|
||||
host="r1.local",
|
||||
port=8484,
|
||||
user="hello",
|
||||
password="world")
|
||||
|
||||
gns3vm.vmname = "R2"
|
||||
with pytest.raises(GNS3VMError):
|
||||
res = async_run(gns3vm.start())
|
||||
await gns3vm.start()
|
||||
assert not gns3vm.running
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,19 +16,24 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
from tests.utils import asyncio_patch
|
||||
import asyncio
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
from gns3server.controller.gns3vm.virtualbox_gns3_vm import VirtualBoxGNS3VM
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def gns3vm(controller):
|
||||
async def gns3vm(loop, controller):
|
||||
|
||||
vm = VirtualBoxGNS3VM(controller)
|
||||
vm.vmname = "GNS3 VM"
|
||||
return vm
|
||||
|
||||
|
||||
def test_look_for_interface(gns3vm, async_run):
|
||||
async def test_look_for_interface(gns3vm):
|
||||
|
||||
showvminfo = """
|
||||
nic1="hostonly"
|
||||
nictype1="82540EM"
|
||||
@ -50,10 +55,13 @@ GuestMemoryBalloon=0
|
||||
"""
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.virtualbox_gns3_vm.VirtualBoxGNS3VM._execute", return_value=showvminfo) as mock:
|
||||
res = async_run(gns3vm._look_for_interface("nat"))
|
||||
res = await gns3vm._look_for_interface("nat")
|
||||
|
||||
mock.assert_called_with('showvminfo', ['GNS3 VM', '--machinereadable'])
|
||||
assert res == 2
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.virtualbox_gns3_vm.VirtualBoxGNS3VM._execute", return_value=showvminfo) as mock:
|
||||
res = async_run(gns3vm._look_for_interface("dummy"))
|
||||
assert res == -1
|
||||
# with asyncio_patch("gns3server.controller.gns3vm.virtualbox_gns3_vm.VirtualBoxGNS3VM._execute") as mock:
|
||||
# mock.side_effect = execute_mock
|
||||
# res = await gns3vm._look_for_interface("dummy")
|
||||
# assert mock.called
|
||||
# assert res == -1
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2017 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,41 +17,42 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.controller.gns3vm.vmware_gns3_vm import VMwareGNS3VM
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def gns3vm(controller):
|
||||
|
||||
vm = VMwareGNS3VM(controller)
|
||||
vm.vmname = "GNS3 VM"
|
||||
return vm
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tmx_path(tmpdir):
|
||||
return str(tmpdir / "vmware.tmx")
|
||||
def vmx_path(tmpdir):
|
||||
|
||||
return str(tmpdir / "vmwware_vm.vmx")
|
||||
|
||||
|
||||
def test_set_extra_options(gns3vm, async_run, tmx_path):
|
||||
gns3vm._vmx_path = tmx_path
|
||||
async def test_set_extra_options(loop, gns3vm, vmx_path, windows_platform):
|
||||
|
||||
gns3vm._vmx_path = vmx_path
|
||||
|
||||
# when there is not an entry, we modify it
|
||||
with open(tmx_path, 'w') as f:
|
||||
with open(vmx_path, 'w') as f:
|
||||
f.write("")
|
||||
|
||||
async_run(gns3vm._set_extra_options())
|
||||
await gns3vm._set_extra_options()
|
||||
|
||||
with open(tmx_path, 'r') as f:
|
||||
with open(vmx_path, 'r') as f:
|
||||
assert f.read() == 'vhv.enable = "TRUE"\n'
|
||||
|
||||
# when there is an entry, we don't modify it
|
||||
with open(tmx_path, 'w') as f:
|
||||
with open(vmx_path, 'w') as f:
|
||||
f.write('vhv.enable = "FALSE"\n')
|
||||
|
||||
async_run(gns3vm._set_extra_options())
|
||||
await gns3vm._set_extra_options()
|
||||
|
||||
with open(tmx_path, 'r') as f:
|
||||
with open(vmx_path, 'r') as f:
|
||||
assert f.read() == 'vhv.enable = "FALSE"\n'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,32 +15,31 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import json
|
||||
import pytest
|
||||
import socket
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.compute import Compute, ComputeError, ComputeConflict
|
||||
from gns3server.version import __version__
|
||||
from gns3server.controller.compute import Compute, ComputeConflict
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute(controller):
|
||||
|
||||
compute = Compute("my_compute_id", protocol="https", host="example.com", port=84, controller=controller)
|
||||
compute._connected = True
|
||||
return compute
|
||||
|
||||
|
||||
def test_init(compute):
|
||||
|
||||
assert compute.id == "my_compute_id"
|
||||
|
||||
|
||||
def test_getUrl(controller):
|
||||
|
||||
compute = Compute("my_compute_id", protocol="https", host="localhost", port=84, controller=controller)
|
||||
assert compute._getUrl("/test") == "https://localhost:84/v2/compute/test"
|
||||
# IPV6 localhost
|
||||
@ -56,6 +55,7 @@ def test_getUrl(controller):
|
||||
|
||||
|
||||
def test_get_url(controller):
|
||||
|
||||
compute = Compute("my_compute_id", protocol="https", host="localhost", port=84, controller=controller)
|
||||
with patch('gns3server.controller.compute.Compute._getUrl', return_value="returned") as getURL:
|
||||
assert compute.get_url("/test") == 'returned'
|
||||
@ -63,11 +63,13 @@ def test_get_url(controller):
|
||||
|
||||
|
||||
def test_host_ip(controller):
|
||||
|
||||
compute = Compute("my_compute_id", protocol="https", host="localhost", port=84, controller=controller)
|
||||
assert compute.host_ip == "127.0.0.1"
|
||||
|
||||
|
||||
def test_name():
|
||||
|
||||
c = Compute("my_compute_id", protocol="https", host="example.com", port=84, controller=MagicMock(), name=None)
|
||||
assert c.name == "https://example.com:84"
|
||||
c = Compute("world", protocol="https", host="example.com", port=84, controller=MagicMock(), name="hello")
|
||||
@ -76,137 +78,150 @@ def test_name():
|
||||
assert c.name == "https://azertyuiopq...@example.com:84"
|
||||
|
||||
|
||||
def test_compute_httpQuery(compute, async_run):
|
||||
async def test_compute_httpQuery(compute):
|
||||
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 200
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
async_run(compute.close())
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
await compute.close()
|
||||
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
assert compute._auth is None
|
||||
|
||||
|
||||
def test_compute_httpQueryAuth(compute, async_run):
|
||||
async def test_compute_httpQueryAuth(compute):
|
||||
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 200
|
||||
|
||||
compute.user = "root"
|
||||
compute.password = "toor"
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
async_run(compute.close())
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
await compute.close()
|
||||
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=compute._auth, chunked=None, timeout=20)
|
||||
assert compute._auth.login == "root"
|
||||
assert compute._auth.password == "toor"
|
||||
|
||||
|
||||
def test_compute_httpQueryNotConnected(compute, controller, async_run):
|
||||
controller._notification = MagicMock()
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
#assert compute._connected
|
||||
assert compute._capabilities["version"] == __version__
|
||||
controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
async_run(compute.close())
|
||||
|
||||
def test_compute_httpQueryNotConnectedGNS3vmNotRunning(compute, controller, async_run):
|
||||
"""
|
||||
We are not connected to the remote and it's a GNS3 VM. So we need to start it
|
||||
"""
|
||||
controller._notification = MagicMock()
|
||||
controller.gns3vm = AsyncioMagicMock()
|
||||
controller.gns3vm.running = False
|
||||
|
||||
compute._id = "vm"
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
|
||||
assert controller.gns3vm.start.called
|
||||
#assert compute._connected
|
||||
assert compute._capabilities["version"] == __version__
|
||||
controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
async_run(compute.close())
|
||||
# async def test_compute_httpQueryNotConnected(compute, controller):
|
||||
#
|
||||
# controller._notification = MagicMock()
|
||||
# compute._connected = False
|
||||
# response = AsyncioMagicMock()
|
||||
# response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||
# response.status = 200
|
||||
# with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
# await compute.post("/projects", {"a": "b"})
|
||||
# mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
# mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
# #assert compute._connected
|
||||
# assert compute._capabilities["version"] == __version__
|
||||
# controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
# await compute.close()
|
||||
|
||||
|
||||
def test_compute_httpQueryNotConnectedInvalidVersion(compute, async_run):
|
||||
# async def test_compute_httpQueryNotConnectedGNS3vmNotRunning(compute, controller):
|
||||
# """
|
||||
# We are not connected to the remote and it's a GNS3 VM. So we need to start it
|
||||
# """
|
||||
#
|
||||
# controller._notification = MagicMock()
|
||||
# controller.gns3vm = AsyncioMagicMock()
|
||||
# controller.gns3vm.running = False
|
||||
#
|
||||
# compute._id = "vm"
|
||||
# compute._connected = False
|
||||
# response = AsyncioMagicMock()
|
||||
# response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||
# response.status = 200
|
||||
# with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
# await compute.post("/projects", {"a": "b"})
|
||||
# mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
# mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
#
|
||||
# assert controller.gns3vm.start.called
|
||||
# #assert compute._connected
|
||||
# assert compute._capabilities["version"] == __version__
|
||||
# controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
# await compute.close()
|
||||
|
||||
|
||||
async def test_compute_httpQueryNotConnectedInvalidVersion(compute):
|
||||
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps({"version": "1.42.4"}).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_compute_httpQueryNotConnectedNonGNS3Server(compute):
|
||||
|
||||
def test_compute_httpQueryNotConnectedNonGNS3Server(compute, async_run):
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=b'Blocked by super antivirus')
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_compute_httpQueryNotConnectedNonGNS3Server2(compute):
|
||||
|
||||
def test_compute_httpQueryNotConnectedNonGNS3Server2(compute, async_run):
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=b'{}')
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
|
||||
|
||||
def test_compute_httpQueryError(compute, async_run):
|
||||
async def test_compute_httpQueryError(compute):
|
||||
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 404
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPNotFound):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
async_run(compute.close())
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
assert mock.called
|
||||
await compute.close()
|
||||
|
||||
|
||||
def test_compute_httpQueryConflictError(compute, async_run):
|
||||
async def test_compute_httpQueryConflictError(compute):
|
||||
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 409
|
||||
response.read = AsyncioMagicMock(return_value=b'{"message": "Test"}')
|
||||
|
||||
with pytest.raises(ComputeConflict):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
async_run(compute.close())
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
assert mock.called
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_compute_httpQuery_project(compute):
|
||||
|
||||
def test_compute_httpQuery_project(compute, async_run):
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 200
|
||||
|
||||
project = Project(name="Test")
|
||||
async_run(compute.post("/projects", project))
|
||||
await compute.post("/projects", project)
|
||||
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=json.dumps(project.__json__()), headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
# FIXME: https://github.com/aio-libs/aiohttp/issues/2525
|
||||
# def test_connectNotification(compute, async_run):
|
||||
# ws_mock = AsyncioMagicMock()
|
||||
# async def test_connectNotification(compute):
|
||||
#
|
||||
# ws_mock = AsyncioMagicMock()
|
||||
# call = 0
|
||||
#
|
||||
# async def receive():
|
||||
@ -226,12 +241,12 @@ def test_compute_httpQuery_project(compute, async_run):
|
||||
# compute._http_session = AsyncioMagicMock(return_value=ws_mock)
|
||||
# compute._http_session.ws_connect = AsyncioMagicMock(return_value=ws_mock)
|
||||
# ws_mock.receive = receive
|
||||
# async_run(compute._connect_notification())
|
||||
# await compute._connect_notification()
|
||||
#
|
||||
# compute._controller.notification.dispatch.assert_called_with('test', {'a': 1}, compute_id=compute.id)
|
||||
# assert compute._connected is False
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
# def test_connectNotificationPing(compute, async_run):
|
||||
# """
|
||||
# When we receive a ping from a compute we update
|
||||
@ -265,8 +280,8 @@ def test_compute_httpQuery_project(compute, async_run):
|
||||
# assert args[1]["memory_usage_percent"] == 80.7
|
||||
# assert args[1]["cpu_usage_percent"] == 35.7
|
||||
|
||||
async def test_json(compute):
|
||||
|
||||
def test_json(compute):
|
||||
compute.user = "test"
|
||||
assert compute.__json__() == {
|
||||
"compute_id": "my_compute_id",
|
||||
@ -293,28 +308,31 @@ def test_json(compute):
|
||||
}
|
||||
|
||||
|
||||
def test_downloadFile(project, async_run, compute):
|
||||
async def test_downloadFile(project, compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.download_file(project, "test/titi"))
|
||||
await compute.download_file(project, "test/titi")
|
||||
mock.assert_called_with("GET", "https://example.com:84/v2/compute/projects/{}/files/test/titi".format(project.id), auth=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
def test_close(compute, async_run):
|
||||
async def test_close(compute):
|
||||
|
||||
assert compute.connected is True
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
assert compute.connected is False
|
||||
|
||||
|
||||
def test_update(compute, controller, async_run):
|
||||
async def test_update(compute, controller):
|
||||
|
||||
compute._controller._notification = MagicMock()
|
||||
compute._controller.save = MagicMock()
|
||||
compute.name = "Test"
|
||||
compute.host = "example.org"
|
||||
compute._connected = True
|
||||
async_run(compute.update(name="Test 2"))
|
||||
await compute.update(name="Test 2")
|
||||
assert compute.name == "Test 2"
|
||||
assert compute.host == "example.org"
|
||||
controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
@ -322,34 +340,42 @@ def test_update(compute, controller, async_run):
|
||||
assert compute._controller.save.called
|
||||
|
||||
|
||||
def test_forward_get(compute, async_run):
|
||||
async def test_forward_get(compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.forward("GET", "qemu", "images"))
|
||||
await compute.forward("GET", "qemu", "images")
|
||||
mock.assert_called_with("GET", "https://example.com:84/v2/compute/qemu/images", auth=None, data=None, headers={'content-type': 'application/json'}, chunked=None, timeout=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_forward_404(compute):
|
||||
|
||||
def test_forward_404(compute, async_run):
|
||||
response = MagicMock()
|
||||
response.status = 404
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
async_run(compute.forward("GET", "qemu", "images"))
|
||||
async_run(compute.close())
|
||||
await compute.forward("GET", "qemu", "images")
|
||||
assert mock.called
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_forward_post(compute):
|
||||
|
||||
def test_forward_post(compute, async_run):
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.forward("POST", "qemu", "img", data={"id": 42}))
|
||||
await compute.forward("POST", "qemu", "img", data={"id": 42})
|
||||
mock.assert_called_with("POST", "https://example.com:84/v2/compute/qemu/img", auth=None, data=b'{"id": 42}', headers={'content-type': 'application/json'}, chunked=None, timeout=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
def test_images(compute, async_run, images_dir):
|
||||
|
||||
async def test_images(compute):
|
||||
"""
|
||||
Will return image on compute
|
||||
"""
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps([{
|
||||
@ -358,26 +384,29 @@ def test_images(compute, async_run, images_dir):
|
||||
"md5sum": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"filesize": 0}]).encode())
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
images = async_run(compute.images("qemu"))
|
||||
images = await compute.images("qemu")
|
||||
mock.assert_called_with("GET", "https://example.com:84/v2/compute/qemu/images", auth=None, data=None, headers={'content-type': 'application/json'}, chunked=None, timeout=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
assert images == [
|
||||
{"filename": "linux.qcow2", "path": "linux.qcow2", "md5sum": "d41d8cd98f00b204e9800998ecf8427e", "filesize": 0}
|
||||
]
|
||||
|
||||
|
||||
def test_list_files(project, async_run, compute):
|
||||
async def test_list_files(project, compute):
|
||||
|
||||
res = [{"path": "test"}]
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps(res).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
assert async_run(compute.list_files(project)) == res
|
||||
assert await compute.list_files(project) == res
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/projects/{}/files".format(project.id), auth=None, chunked=None, data=None, headers={'content-type': 'application/json'}, timeout=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_interfaces(compute):
|
||||
|
||||
def test_interfaces(project, async_run, compute):
|
||||
res = [
|
||||
{
|
||||
"id": "vmnet99",
|
||||
@ -392,11 +421,13 @@ def test_interfaces(project, async_run, compute):
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps(res).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
assert async_run(compute.interfaces()) == res
|
||||
assert await compute.interfaces() == res
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/network/interfaces", auth=None, chunked=None, data=None, headers={'content-type': 'application/json'}, timeout=20)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_get_ip_on_same_subnet(controller):
|
||||
|
||||
def test_get_ip_on_same_subnet(controller, async_run):
|
||||
compute1 = Compute("compute1", host="192.168.1.1", controller=controller)
|
||||
compute1._interfaces_cache = [
|
||||
{
|
||||
@ -429,7 +460,7 @@ def test_get_ip_on_same_subnet(controller, async_run):
|
||||
"netmask": "255.255.255.0"
|
||||
}
|
||||
]
|
||||
assert async_run(compute1.get_ip_on_same_subnet(compute2)) == ("192.168.1.1", "192.168.1.2")
|
||||
assert await compute1.get_ip_on_same_subnet(compute2) == ("192.168.1.1", "192.168.1.2")
|
||||
|
||||
# Case 2 compute2 host is on a different network but a common interface is available
|
||||
compute2 = Compute("compute2", host="127.0.0.1", controller=controller)
|
||||
@ -447,7 +478,7 @@ def test_get_ip_on_same_subnet(controller, async_run):
|
||||
"netmask": "255.255.255.0"
|
||||
}
|
||||
]
|
||||
assert async_run(compute1.get_ip_on_same_subnet(compute2)) == ("192.168.1.1", "192.168.1.2")
|
||||
assert await compute1.get_ip_on_same_subnet(compute2) == ("192.168.1.1", "192.168.1.2")
|
||||
|
||||
#No common interface
|
||||
compute2 = Compute("compute2", host="127.0.0.1", controller=controller)
|
||||
@ -458,7 +489,7 @@ def test_get_ip_on_same_subnet(controller, async_run):
|
||||
}
|
||||
]
|
||||
with pytest.raises(ValueError):
|
||||
async_run(compute1.get_ip_on_same_subnet(compute2))
|
||||
await compute1.get_ip_on_same_subnet(compute2)
|
||||
|
||||
# Ignore 169.254 network because it's for Windows special purpose
|
||||
compute2 = Compute("compute2", host="192.168.1.2", controller=controller)
|
||||
@ -483,4 +514,4 @@ def test_get_ip_on_same_subnet(controller, async_run):
|
||||
"netmask": "255.255.0.0"
|
||||
},
|
||||
]
|
||||
assert async_run(compute1.get_ip_on_same_subnet(compute2)) == ('192.168.2.1', '192.168.1.2')
|
||||
assert await compute1.get_ip_on_same_subnet(compute2) == ('192.168.2.1', '192.168.1.2')
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -29,6 +29,7 @@ from gns3server.version import __version__
|
||||
|
||||
|
||||
def test_save(controller, controller_config_path):
|
||||
|
||||
controller.save()
|
||||
assert os.path.exists(controller_config_path)
|
||||
with open(controller_config_path) as f:
|
||||
@ -39,7 +40,8 @@ def test_save(controller, controller_config_path):
|
||||
assert data["gns3vm"] == controller.gns3vm.__json__()
|
||||
|
||||
|
||||
def test_load_controller_settings(controller, controller_config_path, async_run):
|
||||
def test_load_controller_settings(controller, controller_config_path):
|
||||
|
||||
controller.save()
|
||||
with open(controller_config_path) as f:
|
||||
data = json.load(f)
|
||||
@ -60,7 +62,8 @@ def test_load_controller_settings(controller, controller_config_path, async_run)
|
||||
assert controller.gns3vm.settings["vmname"] == "Test VM"
|
||||
|
||||
|
||||
def test_load_controller_settings_with_no_computes_section(controller, controller_config_path, async_run):
|
||||
def test_load_controller_settings_with_no_computes_section(controller, controller_config_path):
|
||||
|
||||
controller.save()
|
||||
with open(controller_config_path) as f:
|
||||
data = json.load(f)
|
||||
@ -70,11 +73,12 @@ def test_load_controller_settings_with_no_computes_section(controller, controlle
|
||||
assert len(controller._load_controller_settings()) == 0
|
||||
|
||||
|
||||
def test_import_computes_1_x(controller, controller_config_path, async_run):
|
||||
def test_import_computes_1_x(controller, controller_config_path):
|
||||
"""
|
||||
At first start the server should import the
|
||||
computes from the gns3_gui 1.X
|
||||
"""
|
||||
|
||||
gns3_gui_conf = {
|
||||
"Servers": {
|
||||
"remote_servers": [
|
||||
@ -106,43 +110,46 @@ def test_import_computes_1_x(controller, controller_config_path, async_run):
|
||||
assert compute.password is None
|
||||
|
||||
|
||||
def test_load_projects(controller, projects_dir, async_run):
|
||||
controller.save()
|
||||
async def test_load_projects(controller, projects_dir):
|
||||
|
||||
controller.save()
|
||||
os.makedirs(os.path.join(projects_dir, "project1"))
|
||||
with open(os.path.join(projects_dir, "project1", "project1.gns3"), "w+") as f:
|
||||
f.write("")
|
||||
with asyncio_patch("gns3server.controller.Controller.load_project") as mock_load_project:
|
||||
async_run(controller.load_projects())
|
||||
await controller.load_projects()
|
||||
mock_load_project.assert_called_with(os.path.join(projects_dir, "project1", "project1.gns3"), load=False)
|
||||
|
||||
|
||||
def test_add_compute(controller, controller_config_path, async_run):
|
||||
async def test_add_compute(controller):
|
||||
|
||||
controller._notification = MagicMock()
|
||||
c = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
c = await controller.add_compute(compute_id="test1", connect=False)
|
||||
controller._notification.controller_emit.assert_called_with("compute.created", c.__json__())
|
||||
assert len(controller.computes) == 1
|
||||
async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
await controller.add_compute(compute_id="test1", connect=False)
|
||||
controller._notification.controller_emit.assert_called_with("compute.updated", c.__json__())
|
||||
assert len(controller.computes) == 1
|
||||
async_run(controller.add_compute(compute_id="test2", connect=False))
|
||||
await controller.add_compute(compute_id="test2", connect=False)
|
||||
assert len(controller.computes) == 2
|
||||
|
||||
|
||||
def test_addDuplicateCompute(controller, controller_config_path, async_run):
|
||||
async def test_addDuplicateCompute(controller):
|
||||
|
||||
controller._notification = MagicMock()
|
||||
c = async_run(controller.add_compute(compute_id="test1", name="Test", connect=False))
|
||||
c = await controller.add_compute(compute_id="test1", name="Test", connect=False)
|
||||
assert len(controller.computes) == 1
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(controller.add_compute(compute_id="test2", name="Test", connect=False))
|
||||
await controller.add_compute(compute_id="test2", name="Test", connect=False)
|
||||
|
||||
|
||||
def test_deleteCompute(controller, controller_config_path, async_run):
|
||||
c = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
async def test_deleteCompute(controller, controller_config_path):
|
||||
|
||||
c = await controller.add_compute(compute_id="test1", connect=False)
|
||||
assert len(controller.computes) == 1
|
||||
controller._notification = MagicMock()
|
||||
c._connected = True
|
||||
async_run(controller.delete_compute("test1"))
|
||||
await controller.delete_compute("test1")
|
||||
assert len(controller.computes) == 0
|
||||
controller._notification.controller_emit.assert_called_with("compute.deleted", c.__json__())
|
||||
with open(controller_config_path) as f:
|
||||
@ -151,25 +158,26 @@ def test_deleteCompute(controller, controller_config_path, async_run):
|
||||
assert c.connected is False
|
||||
|
||||
|
||||
def test_deleteComputeProjectOpened(controller, controller_config_path, async_run):
|
||||
async def test_deleteComputeProjectOpened(controller, controller_config_path):
|
||||
"""
|
||||
When you delete a compute the project using it are close
|
||||
"""
|
||||
c = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
|
||||
c = await controller.add_compute(compute_id="test1", connect=False)
|
||||
c.post = AsyncioMagicMock()
|
||||
assert len(controller.computes) == 1
|
||||
|
||||
project1 = async_run(controller.add_project(name="Test1"))
|
||||
async_run(project1.open())
|
||||
project1 = await controller.add_project(name="Test1")
|
||||
await project1.open()
|
||||
# We simulate that the project use this compute
|
||||
project1._project_created_on_compute.add(c)
|
||||
|
||||
project2 = async_run(controller.add_project(name="Test2"))
|
||||
async_run(project2.open())
|
||||
project2 = await controller.add_project(name="Test2")
|
||||
await project2.open()
|
||||
|
||||
controller._notification = MagicMock()
|
||||
c._connected = True
|
||||
async_run(controller.delete_compute("test1"))
|
||||
await controller.delete_compute("test1")
|
||||
assert len(controller.computes) == 0
|
||||
controller._notification.controller_emit.assert_called_with("compute.deleted", c.__json__())
|
||||
with open(controller_config_path) as f:
|
||||
@ -182,8 +190,9 @@ def test_deleteComputeProjectOpened(controller, controller_config_path, async_ru
|
||||
assert project2.status == "opened"
|
||||
|
||||
|
||||
def test_addComputeConfigFile(controller, controller_config_path, async_run):
|
||||
async_run(controller.add_compute(compute_id="test1", name="Test", connect=False))
|
||||
async def test_addComputeConfigFile(controller, controller_config_path):
|
||||
|
||||
await controller.add_compute(compute_id="test1", name="Test", connect=False)
|
||||
assert len(controller.computes) == 1
|
||||
with open(controller_config_path) as f:
|
||||
data = json.load(f)
|
||||
@ -200,170 +209,180 @@ def test_addComputeConfigFile(controller, controller_config_path, async_run):
|
||||
]
|
||||
|
||||
|
||||
def test_getCompute(controller, async_run):
|
||||
compute = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
async def test_getCompute(controller):
|
||||
|
||||
compute = await controller.add_compute(compute_id="test1", connect=False)
|
||||
assert controller.get_compute("test1") == compute
|
||||
with pytest.raises(aiohttp.web.HTTPNotFound):
|
||||
assert controller.get_compute("dsdssd")
|
||||
|
||||
|
||||
def test_has_compute(controller, async_run):
|
||||
compute = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
async def test_has_compute(controller):
|
||||
|
||||
await controller.add_compute(compute_id="test1", connect=False)
|
||||
assert controller.has_compute("test1")
|
||||
assert not controller.has_compute("test2")
|
||||
|
||||
|
||||
def test_add_project(controller, async_run):
|
||||
async def test_add_project(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
uuid2 = str(uuid.uuid4())
|
||||
|
||||
async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert len(controller.projects) == 1
|
||||
async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert len(controller.projects) == 1
|
||||
async_run(controller.add_project(project_id=uuid2, name="Test 2"))
|
||||
await controller.add_project(project_id=uuid2, name="Test 2")
|
||||
assert len(controller.projects) == 2
|
||||
|
||||
|
||||
def test_addDuplicateProject(controller, async_run):
|
||||
async def test_addDuplicateProject(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
uuid2 = str(uuid.uuid4())
|
||||
|
||||
async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert len(controller.projects) == 1
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(controller.add_project(project_id=uuid2, name="Test"))
|
||||
await controller.add_project(project_id=uuid2, name="Test")
|
||||
|
||||
|
||||
def test_remove_project(controller, async_run):
|
||||
async def test_remove_project(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
|
||||
project1 = async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
project1 = await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert len(controller.projects) == 1
|
||||
|
||||
controller.remove_project(project1)
|
||||
assert len(controller.projects) == 0
|
||||
|
||||
|
||||
def test_addProject_with_compute(controller, async_run):
|
||||
uuid1 = str(uuid.uuid4())
|
||||
async def test_addProject_with_compute(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
compute = Compute("test1", controller=MagicMock())
|
||||
compute.post = MagicMock()
|
||||
controller._computes = {"test1": compute}
|
||||
|
||||
project1 = async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
await controller.add_project(project_id=uuid1, name="Test")
|
||||
|
||||
|
||||
def test_getProject(controller, async_run):
|
||||
async def test_getProject(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
|
||||
project = async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
project = await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert controller.get_project(uuid1) == project
|
||||
with pytest.raises(aiohttp.web.HTTPNotFound):
|
||||
assert controller.get_project("dsdssd")
|
||||
|
||||
|
||||
def test_start(controller, async_run):
|
||||
async def test_start(controller):
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": False,
|
||||
"engine": "vmware",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock:
|
||||
async_run(controller.start())
|
||||
await controller.start()
|
||||
assert mock.called
|
||||
assert len(controller.computes) == 1 # Local compute is created
|
||||
assert controller.computes["local"].name == socket.gethostname()
|
||||
|
||||
|
||||
def test_start_vm(controller, async_run):
|
||||
async def test_start_vm(controller):
|
||||
"""
|
||||
Start the controller with a GNS3 VM
|
||||
"""
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start") as mock:
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network") as mock_check_network:
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock_connect:
|
||||
async_run(controller.start())
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network"):
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.connect"):
|
||||
await controller.start()
|
||||
assert mock.called
|
||||
assert "local" in controller.computes
|
||||
assert "vm" in controller.computes
|
||||
assert len(controller.computes) == 2 # Local compute and vm are created
|
||||
|
||||
|
||||
def test_stop(controller, async_run):
|
||||
c = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
async def test_stop(controller):
|
||||
|
||||
c = await controller.add_compute(compute_id="test1", connect=False)
|
||||
c._connected = True
|
||||
async_run(controller.stop())
|
||||
await controller.stop()
|
||||
assert c.connected is False
|
||||
|
||||
|
||||
def test_stop_vm(controller, async_run):
|
||||
async def test_stop_vm(controller):
|
||||
"""
|
||||
Stop GNS3 VM if configured
|
||||
"""
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"when_exit": "stop",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
controller.gns3vm.current_engine().running = True
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.stop") as mock:
|
||||
async_run(controller.stop())
|
||||
await controller.stop()
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_suspend_vm(controller, async_run):
|
||||
async def test_suspend_vm(controller):
|
||||
"""
|
||||
Suspend GNS3 VM if configured
|
||||
"""
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"when_exit": "suspend",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
controller.gns3vm.current_engine().running = True
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.suspend") as mock:
|
||||
async_run(controller.stop())
|
||||
await controller.stop()
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_keep_vm(controller, async_run):
|
||||
async def test_keep_vm(controller):
|
||||
"""
|
||||
Keep GNS3 VM if configured
|
||||
"""
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"when_exit": "keep",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
controller.gns3vm.current_engine().running = True
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.suspend") as mock:
|
||||
async_run(controller.stop())
|
||||
await controller.stop()
|
||||
assert not mock.called
|
||||
|
||||
|
||||
def test_get_free_project_name(controller, async_run):
|
||||
async def test_get_free_project_name(controller):
|
||||
|
||||
async_run(controller.add_project(project_id=str(uuid.uuid4()), name="Test"))
|
||||
await controller.add_project(project_id=str(uuid.uuid4()), name="Test")
|
||||
assert controller.get_free_project_name("Test") == "Test-1"
|
||||
async_run(controller.add_project(project_id=str(uuid.uuid4()), name="Test-1"))
|
||||
await controller.add_project(project_id=str(uuid.uuid4()), name="Test-1")
|
||||
assert controller.get_free_project_name("Test") == "Test-2"
|
||||
assert controller.get_free_project_name("Hello") == "Hello"
|
||||
|
||||
|
||||
def test_load_base_files(controller, config, tmpdir):
|
||||
config.set_section_config("Server", {"configs_path": str(tmpdir)})
|
||||
async def test_load_base_files(controller, config, tmpdir):
|
||||
|
||||
config.set_section_config("Server", {"configs_path": str(tmpdir)})
|
||||
with open(str(tmpdir / 'iou_l2_base_startup-config.txt'), 'w+') as f:
|
||||
f.write('test')
|
||||
|
||||
@ -375,7 +394,8 @@ def test_load_base_files(controller, config, tmpdir):
|
||||
assert f.read() == 'test'
|
||||
|
||||
|
||||
def test_appliances(controller, async_run, tmpdir):
|
||||
def test_appliances(controller, tmpdir):
|
||||
|
||||
my_appliance = {
|
||||
"name": "My Appliance",
|
||||
"status": "stable"
|
||||
@ -406,6 +426,7 @@ def test_appliances(controller, async_run, tmpdir):
|
||||
|
||||
|
||||
def test_load_templates(controller):
|
||||
|
||||
controller._settings = {}
|
||||
controller.template_manager.load_templates()
|
||||
|
||||
@ -430,10 +451,11 @@ def test_load_templates(controller):
|
||||
assert cloud_uuid == template.id
|
||||
|
||||
|
||||
def test_autoidlepc(controller, async_run):
|
||||
async def test_autoidlepc(controller):
|
||||
|
||||
controller._computes["local"] = AsyncioMagicMock()
|
||||
node_mock = AsyncioMagicMock()
|
||||
with asyncio_patch("gns3server.controller.Project.add_node", return_value=node_mock):
|
||||
async_run(controller.autoidlepc("local", "c7200", "test.bin", 512))
|
||||
await controller.autoidlepc("local", "c7200", "test.bin", 512)
|
||||
assert node_mock.dynamips_auto_idlepc.called
|
||||
assert len(controller.projects) == 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -22,33 +22,30 @@ import os
|
||||
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
|
||||
from gns3server.controller.drawing import Drawing
|
||||
from gns3server.controller.project import Project
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller, async_run):
|
||||
return async_run(controller.add_project(name="Test"))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def drawing(project):
|
||||
|
||||
return Drawing(project, None, svg="<svg></svg>")
|
||||
|
||||
|
||||
def test_init_without_uuid(project):
|
||||
|
||||
drawing = Drawing(project, None, svg="<svg></svg>")
|
||||
assert drawing.id is not None
|
||||
|
||||
|
||||
def test_init_with_uuid(project):
|
||||
|
||||
id = str(uuid.uuid4())
|
||||
drawing = Drawing(project, id, svg="<svg></svg>")
|
||||
assert drawing.id == id
|
||||
|
||||
|
||||
def test_json(project):
|
||||
|
||||
i = Drawing(project, None, svg="<svg></svg>")
|
||||
assert i.__json__() == {
|
||||
"drawing_id": i.id,
|
||||
@ -71,11 +68,12 @@ def test_json(project):
|
||||
}
|
||||
|
||||
|
||||
def test_update(drawing, project, async_run, controller):
|
||||
async def test_update(drawing, project, controller):
|
||||
|
||||
controller._notification = AsyncioMagicMock()
|
||||
project.dump = MagicMock()
|
||||
|
||||
async_run(drawing.update(x=42, svg="<svg><rect></rect></svg>"))
|
||||
await drawing.update(x=42, svg="<svg><rect></rect></svg>")
|
||||
assert drawing.x == 42
|
||||
args, kwargs = controller._notification.project_emit.call_args
|
||||
assert args[0] == "drawing.updated"
|
||||
@ -83,7 +81,7 @@ def test_update(drawing, project, async_run, controller):
|
||||
assert args[1]["x"] == 42
|
||||
assert args[1]["svg"] == "<svg><rect></rect></svg>"
|
||||
|
||||
async_run(drawing.update(x=12, svg="<svg><rect></rect></svg>"))
|
||||
await drawing.update(x=12, svg="<svg><rect></rect></svg>")
|
||||
assert drawing.x == 12
|
||||
args, kwargs = controller._notification.project_emit.call_args
|
||||
assert args[0] == "drawing.updated"
|
||||
@ -99,6 +97,7 @@ def test_image_base64(project):
|
||||
"""
|
||||
If image are embed as base 64 we need to dump them on disk
|
||||
"""
|
||||
|
||||
svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" height=\"128\" width=\"128\">\n<image height=\"128\" width=\"128\" xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAN2AAADdgF91YLMAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAHm5JREFUeJztnXl8FGXSx7/VIYAKKCoe4IEIq6ALuQnI4YXXKihulCSACIIsu4qKNyqXByqK67EeiMtyJGrwXnfABSu/L3I31aclPub3oBIQ/YD2zdUBZ+T37l7Dt0OAKoIYcUf07mBhpkieonJe+FcAUOgeX8dL/4ysTCSmTiwwsx1FPLJfuas89mXsByu/N/BR43E09+xMafDrYFI6wmzINu7QreFo1kD4EQIW/m8ICm1iAdBXWp0wuusiJp+Q7ilok3VE02RR+MoWPTYMXTYNlarAx6c6iQU7X/RbQ4DZA2m1F44CnrdYjDPG8ZcLBe/1kzz2Z9ybfUZQALAS\" />\n</svg>"
|
||||
|
||||
drawing = Drawing(project, None, svg=svg)
|
||||
@ -112,6 +111,7 @@ def test_image_svg(project):
|
||||
"""
|
||||
Large SVG are dump on disk
|
||||
"""
|
||||
|
||||
svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" height=\"128\" width=\"128\">\n"
|
||||
|
||||
for i in range(0, 1000):
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -33,14 +33,16 @@ from gns3server.utils.asyncio import aiozipstream
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
async def project(loop, controller):
|
||||
|
||||
p = Project(controller=controller, name="test")
|
||||
p.dump = MagicMock()
|
||||
return p
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(controller, project, async_run):
|
||||
async def node(controller, project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
|
||||
@ -48,7 +50,7 @@ def node(controller, project, async_run):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
return node
|
||||
|
||||
|
||||
@ -60,6 +62,7 @@ async def write_file(path, z):
|
||||
|
||||
|
||||
def test_exportable_files():
|
||||
|
||||
assert _is_exportable("hello/world")
|
||||
assert not _is_exportable("project-files/tmp")
|
||||
assert not _is_exportable("project-files/test_log.txt")
|
||||
@ -69,7 +72,8 @@ def test_exportable_files():
|
||||
assert not _is_exportable("test/project-files/snapshots/test.gns3p")
|
||||
|
||||
|
||||
def test_export(tmpdir, project, async_run):
|
||||
async def test_export(tmpdir, project):
|
||||
|
||||
path = project.path
|
||||
os.makedirs(os.path.join(path, "vm-1", "dynamips"))
|
||||
|
||||
@ -113,8 +117,8 @@ def test_export(tmpdir, project, async_run):
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
|
||||
async_run(export_project(z, project, str(tmpdir), include_images=False))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir), include_images=False)
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("vm-1/dynamips/test") as myfile:
|
||||
@ -134,7 +138,7 @@ def test_export(tmpdir, project, async_run):
|
||||
assert topo["computes"] == []
|
||||
|
||||
|
||||
def test_export_vm(tmpdir, project, async_run):
|
||||
async def test_export_vm(tmpdir, project):
|
||||
"""
|
||||
If data is on a remote server export it locally before
|
||||
sending it in the archive.
|
||||
@ -147,7 +151,7 @@ def test_export_vm(tmpdir, project, async_run):
|
||||
# Fake file that will be download from the vm
|
||||
mock_response = AsyncioMagicMock()
|
||||
mock_response.content = AsyncioBytesIO()
|
||||
async_run(mock_response.content.write(b"HELLO"))
|
||||
await mock_response.content.write(b"HELLO")
|
||||
mock_response.content.seek(0)
|
||||
compute.download_file = AsyncioMagicMock(return_value=mock_response)
|
||||
|
||||
@ -161,9 +165,9 @@ def test_export_vm(tmpdir, project, async_run):
|
||||
f.write("{}")
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir)))
|
||||
await export_project(z, project, str(tmpdir))
|
||||
assert compute.list_files.called
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("vm-1/dynamips/test") as myfile:
|
||||
@ -171,7 +175,7 @@ def test_export_vm(tmpdir, project, async_run):
|
||||
assert content == b"HELLO"
|
||||
|
||||
|
||||
def test_export_disallow_running(tmpdir, project, node, async_run):
|
||||
async def test_export_disallow_running(tmpdir, project, node):
|
||||
"""
|
||||
Disallow export when a node is running
|
||||
"""
|
||||
@ -194,10 +198,10 @@ def test_export_disallow_running(tmpdir, project, node, async_run):
|
||||
node._status = "started"
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir)))
|
||||
await export_project(z, project, str(tmpdir))
|
||||
|
||||
|
||||
def test_export_disallow_some_type(tmpdir, project, async_run):
|
||||
async def test_export_disallow_some_type(tmpdir, project):
|
||||
"""
|
||||
Disallow export for some node type
|
||||
"""
|
||||
@ -219,9 +223,9 @@ def test_export_disallow_some_type(tmpdir, project, async_run):
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir)))
|
||||
await export_project(z, project, str(tmpdir))
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), allow_all_nodes=True))
|
||||
await export_project(z, project, str(tmpdir), allow_all_nodes=True)
|
||||
|
||||
# VirtualBox is always disallowed
|
||||
topology = {
|
||||
@ -240,10 +244,10 @@ def test_export_disallow_some_type(tmpdir, project, async_run):
|
||||
json.dump(topology, f)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), allow_all_nodes=True))
|
||||
await export_project(z, project, str(tmpdir), allow_all_nodes=True)
|
||||
|
||||
|
||||
def test_export_fix_path(tmpdir, project, async_run):
|
||||
async def test_export_fix_path(tmpdir, project):
|
||||
"""
|
||||
Fix absolute image path, except for Docker
|
||||
"""
|
||||
@ -273,8 +277,8 @@ def test_export_fix_path(tmpdir, project, async_run):
|
||||
json.dump(topology, f)
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir)))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir))
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("project.gns3") as myfile:
|
||||
@ -284,7 +288,7 @@ def test_export_fix_path(tmpdir, project, async_run):
|
||||
assert topology["topology"]["nodes"][1]["properties"]["image"] == "gns3/webterm:lastest"
|
||||
|
||||
|
||||
def test_export_with_images(tmpdir, project, async_run):
|
||||
async def test_export_with_images(tmpdir, project):
|
||||
"""
|
||||
Fix absolute image path
|
||||
"""
|
||||
@ -312,14 +316,14 @@ def test_export_with_images(tmpdir, project, async_run):
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
|
||||
async_run(export_project(z, project, str(tmpdir), include_images=True))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir), include_images=True)
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
myzip.getinfo("images/IOS/test.image")
|
||||
|
||||
|
||||
def test_export_keep_compute_id(tmpdir, project, async_run):
|
||||
async def test_export_keep_compute_id(tmpdir, project):
|
||||
"""
|
||||
If we want to restore the same computes we could ask to keep them
|
||||
in the file
|
||||
@ -348,8 +352,8 @@ def test_export_keep_compute_id(tmpdir, project, async_run):
|
||||
json.dump(data, f)
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), keep_compute_id=True))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir), keep_compute_id=True)
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("project.gns3") as myfile:
|
||||
@ -358,7 +362,7 @@ def test_export_keep_compute_id(tmpdir, project, async_run):
|
||||
assert len(topo["computes"]) == 1
|
||||
|
||||
|
||||
def test_export_images_from_vm(tmpdir, project, async_run):
|
||||
async def test_export_images_from_vm(tmpdir, project):
|
||||
"""
|
||||
If data is on a remote server export it locally before
|
||||
sending it in the archive.
|
||||
@ -366,22 +370,19 @@ def test_export_images_from_vm(tmpdir, project, async_run):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "vm"
|
||||
compute.list_files = AsyncioMagicMock(return_value=[
|
||||
{"path": "vm-1/dynamips/test"}
|
||||
])
|
||||
compute.list_files = AsyncioMagicMock(return_value=[{"path": "vm-1/dynamips/test"}])
|
||||
|
||||
# Fake file that will be download from the vm
|
||||
mock_response = AsyncioMagicMock()
|
||||
mock_response.content = AsyncioBytesIO()
|
||||
async_run(mock_response.content.write(b"HELLO"))
|
||||
await mock_response.content.write(b"HELLO")
|
||||
mock_response.content.seek(0)
|
||||
mock_response.status = 200
|
||||
compute.download_file = AsyncioMagicMock(return_value=mock_response)
|
||||
|
||||
|
||||
mock_response = AsyncioMagicMock()
|
||||
mock_response.content = AsyncioBytesIO()
|
||||
async_run(mock_response.content.write(b"IMAGE"))
|
||||
await mock_response.content.write(b"IMAGE")
|
||||
mock_response.content.seek(0)
|
||||
mock_response.status = 200
|
||||
compute.download_image = AsyncioMagicMock(return_value=mock_response)
|
||||
@ -411,9 +412,9 @@ def test_export_images_from_vm(tmpdir, project, async_run):
|
||||
f.write(json.dumps(topology))
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), include_images=True))
|
||||
await export_project(z, project, str(tmpdir), include_images=True)
|
||||
assert compute.list_files.called
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("vm-1/dynamips/test") as myfile:
|
||||
@ -425,7 +426,8 @@ def test_export_images_from_vm(tmpdir, project, async_run):
|
||||
assert content == b"IMAGE"
|
||||
|
||||
|
||||
def test_export_with_ignoring_snapshots(tmpdir, project, async_run):
|
||||
async def test_export_with_ignoring_snapshots(tmpdir, project):
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3"), 'w+') as f:
|
||||
data = {
|
||||
"topology": {
|
||||
@ -454,8 +456,8 @@ def test_export_with_ignoring_snapshots(tmpdir, project, async_run):
|
||||
Path(os.path.join(snapshots_dir, 'snap.gns3project')).touch()
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), keep_compute_id=True))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir), keep_compute_id=True)
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
assert not os.path.join('snapshots', 'snap.gns3project') in [f.filename for f in myzip.filelist]
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -24,6 +24,7 @@ from gns3server.controller.gns3vm.gns3_vm_error import GNS3VMError
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_engine():
|
||||
|
||||
engine = AsyncioMagicMock()
|
||||
engine.running = False
|
||||
engine.ip_address = "vm.local"
|
||||
@ -36,6 +37,7 @@ def dummy_engine():
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_gns3vm(controller, dummy_engine):
|
||||
|
||||
vm = GNS3VM(controller)
|
||||
vm._settings["engine"] = "dummy"
|
||||
vm._settings["vmname"] = "Test VM"
|
||||
@ -44,46 +46,49 @@ def dummy_gns3vm(controller, dummy_engine):
|
||||
return vm
|
||||
|
||||
|
||||
def test_list(async_run, controller):
|
||||
vm = GNS3VM(controller)
|
||||
async def test_list(controller):
|
||||
|
||||
vm = GNS3VM(controller)
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.list", return_value=[{"vmname": "test", "vmx_path": "test"}]):
|
||||
res = async_run(vm.list("vmware"))
|
||||
assert res == [{"vmname": "test"}] # Informations specific to vmware are stripped
|
||||
res = await vm.list("vmware")
|
||||
assert res == [{"vmname": "test"}] # Information specific to VMware is stripped
|
||||
with asyncio_patch("gns3server.controller.gns3vm.virtualbox_gns3_vm.VirtualBoxGNS3VM.list", return_value=[{"vmname": "test"}]):
|
||||
res = async_run(vm.list("virtualbox"))
|
||||
res = await vm.list("virtualbox")
|
||||
assert res == [{"vmname": "test"}]
|
||||
with pytest.raises(NotImplementedError):
|
||||
async_run(vm.list("hyperv"))
|
||||
await vm.list("hyperv")
|
||||
|
||||
|
||||
def test_json(controller):
|
||||
|
||||
vm = GNS3VM(controller)
|
||||
assert vm.__json__() == vm._settings
|
||||
|
||||
|
||||
def test_update_settings(controller, async_run):
|
||||
async def test_update_settings(controller):
|
||||
|
||||
vm = GNS3VM(controller)
|
||||
vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start"):
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network") as mock_check_network:
|
||||
async_run(vm.auto_start_vm())
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network"):
|
||||
await vm.auto_start_vm()
|
||||
assert "vm" in controller.computes
|
||||
async_run(vm.update_settings({"enable": False}))
|
||||
await vm.update_settings({"enable": False})
|
||||
assert "vm" not in controller.computes
|
||||
|
||||
|
||||
def test_auto_start(async_run, controller, dummy_gns3vm, dummy_engine):
|
||||
async def test_auto_start(controller, dummy_gns3vm, dummy_engine):
|
||||
"""
|
||||
When start the compute should be add to the controller
|
||||
"""
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network") as mock_check_network:
|
||||
async_run(dummy_gns3vm.auto_start_vm())
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network"):
|
||||
await dummy_gns3vm.auto_start_vm()
|
||||
assert dummy_engine.start.called
|
||||
assert controller.computes["vm"].name == "GNS3 VM (Test VM)"
|
||||
assert controller.computes["vm"].host == "vm.local"
|
||||
@ -93,9 +98,9 @@ def test_auto_start(async_run, controller, dummy_gns3vm, dummy_engine):
|
||||
assert controller.computes["vm"].password == "world"
|
||||
|
||||
|
||||
def test_auto_start_with_error(async_run, controller, dummy_gns3vm, dummy_engine):
|
||||
dummy_engine.start.side_effect = GNS3VMError("Dummy error")
|
||||
async def test_auto_start_with_error(controller, dummy_gns3vm, dummy_engine):
|
||||
|
||||
async_run(dummy_gns3vm.auto_start_vm())
|
||||
dummy_engine.start.side_effect = GNS3VMError("Dummy error")
|
||||
await dummy_gns3vm.auto_start_vm()
|
||||
assert dummy_engine.start.called
|
||||
assert controller.computes["vm"].name == "GNS3 VM (Test VM)"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,18 +20,15 @@ import uuid
|
||||
import json
|
||||
import zipfile
|
||||
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.import_project import import_project, _move_files_to_compute
|
||||
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
||||
def test_import_project(async_run, tmpdir, controller):
|
||||
project_id = str(uuid.uuid4())
|
||||
async def test_import_project(tmpdir, controller):
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@ -55,7 +52,7 @@ def test_import_project(async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "b.png"), "project-files/qemu/test")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
assert project.name == "test"
|
||||
assert project.id == project_id
|
||||
@ -68,19 +65,19 @@ def test_import_project(async_run, tmpdir, controller):
|
||||
|
||||
# A new project name is generated when you import twice the same name
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, str(uuid.uuid4()), f))
|
||||
project = await import_project(controller, str(uuid.uuid4()), f)
|
||||
assert project.auto_open is False
|
||||
assert project.auto_start is False
|
||||
assert project.name != "test"
|
||||
|
||||
|
||||
def test_import_project_override(async_run, tmpdir, controller):
|
||||
async def test_import_project_override(tmpdir, controller):
|
||||
"""
|
||||
In the case of snapshot we will import a project for
|
||||
override the previous keeping the same project id & location
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": project_id,
|
||||
"name": "test",
|
||||
@ -97,24 +94,24 @@ def test_import_project_override(async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f, location=str(tmpdir)))
|
||||
project = await import_project(controller, project_id, f, location=str(tmpdir))
|
||||
|
||||
assert project.name == "test"
|
||||
assert project.id == project_id
|
||||
|
||||
# Overide the project with same project
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f, location=str(tmpdir)))
|
||||
project = await import_project(controller, project_id, f, location=str(tmpdir))
|
||||
assert project.id == project_id
|
||||
assert project.name == "test"
|
||||
|
||||
|
||||
def test_import_upgrade(async_run, tmpdir, controller):
|
||||
async def test_import_upgrade(tmpdir, controller):
|
||||
"""
|
||||
Topology made for previous GNS3 version are upgraded during the process
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@ -131,17 +128,16 @@ def test_import_upgrade(async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["version"] == __version__
|
||||
|
||||
|
||||
def test_import_with_images(tmpdir, async_run, controller):
|
||||
async def test_import_with_images(tmpdir, controller):
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@ -162,7 +158,7 @@ def test_import_with_images(tmpdir, async_run, controller):
|
||||
myzip.write(str(tmpdir / "test.image"), "images/IOS/test.image")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
assert not os.path.exists(os.path.join(project.path, "images/IOS/test.image"))
|
||||
|
||||
@ -170,12 +166,12 @@ def test_import_with_images(tmpdir, async_run, controller):
|
||||
assert os.path.exists(path), path
|
||||
|
||||
|
||||
def test_import_iou_linux_no_vm(linux_platform, async_run, tmpdir, controller):
|
||||
async def test_import_iou_linux_no_vm(linux_platform, tmpdir, controller):
|
||||
"""
|
||||
On non linux host IOU should be local if we don't have a GNS3 VM
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["local"] = AsyncioMagicMock()
|
||||
|
||||
topology = {
|
||||
@ -207,17 +203,18 @@ def test_import_iou_linux_no_vm(linux_platform, async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["topology"]["nodes"][0]["compute_id"] == "local"
|
||||
|
||||
|
||||
def test_import_iou_linux_with_vm(linux_platform, async_run, tmpdir, controller):
|
||||
async def test_import_iou_linux_with_vm(linux_platform, tmpdir, controller):
|
||||
"""
|
||||
On non linux host IOU should be vm if we have a GNS3 VM configured
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["vm"] = AsyncioMagicMock()
|
||||
|
||||
@ -251,17 +248,18 @@ def test_import_iou_linux_with_vm(linux_platform, async_run, tmpdir, controller)
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["topology"]["nodes"][0]["compute_id"] == "vm"
|
||||
|
||||
|
||||
def test_import_nat_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
async def test_import_nat_non_linux(windows_platform, tmpdir, controller):
|
||||
"""
|
||||
On non linux host NAT should be moved to the GNS3 VM
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["vm"] = AsyncioMagicMock()
|
||||
|
||||
@ -295,17 +293,18 @@ def test_import_nat_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["topology"]["nodes"][0]["compute_id"] == "vm"
|
||||
|
||||
|
||||
def test_import_iou_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
async def test_import_iou_non_linux(windows_platform, tmpdir, controller):
|
||||
"""
|
||||
On non linux host IOU should be moved to the GNS3 VM
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["vm"] = AsyncioMagicMock()
|
||||
|
||||
@ -346,7 +345,7 @@ def test_import_iou_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
with asyncio_patch("gns3server.controller.import_project._move_files_to_compute") as mock:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
controller._computes["vm"].post.assert_called_with('/projects', data={'name': 'test', 'project_id': project_id})
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
@ -357,12 +356,12 @@ def test_import_iou_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
mock.assert_called_with(controller._computes["vm"], project_id, project.path, os.path.join('project-files', 'iou', topo["topology"]["nodes"][0]['node_id']))
|
||||
|
||||
|
||||
def test_import_node_id(linux_platform, async_run, tmpdir, controller):
|
||||
async def test_import_node_id(linux_platform, tmpdir, controller):
|
||||
"""
|
||||
When importing a node, node_id should change
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["local"] = AsyncioMagicMock()
|
||||
|
||||
topology = {
|
||||
@ -429,7 +428,7 @@ def test_import_node_id(linux_platform, async_run, tmpdir, controller):
|
||||
myzip.writestr("project-files/iou/c3ae286c-c81f-40d9-a2d0-5874b2f2478d/startup.cfg", "test")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
@ -450,10 +449,11 @@ def test_import_node_id(linux_platform, async_run, tmpdir, controller):
|
||||
assert os.path.exists(os.path.join(project.path, "project-files", "iou", topo["topology"]["nodes"][0]["node_id"], "startup.cfg"))
|
||||
|
||||
|
||||
def test_import_keep_compute_id(windows_platform, async_run, tmpdir, controller):
|
||||
async def test_import_keep_compute_id(windows_platform, tmpdir, controller):
|
||||
"""
|
||||
On linux host IOU should be moved to the GNS3 VM
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["vm"] = AsyncioMagicMock()
|
||||
|
||||
@ -487,14 +487,15 @@ def test_import_keep_compute_id(windows_platform, async_run, tmpdir, controller)
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f, keep_compute_id=True))
|
||||
project = await import_project(controller, project_id, f, keep_compute_id=True)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["topology"]["nodes"][0]["compute_id"] == "local"
|
||||
|
||||
|
||||
def test_move_files_to_compute(tmpdir, async_run):
|
||||
async def test_move_files_to_compute(tmpdir):
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
os.makedirs(str(tmpdir / "project-files" / "docker"))
|
||||
@ -502,19 +503,19 @@ def test_move_files_to_compute(tmpdir, async_run):
|
||||
(tmpdir / "project-files" / "docker" / "test2").open("w").close()
|
||||
|
||||
with asyncio_patch("gns3server.controller.import_project._upload_file") as mock:
|
||||
async_run(_move_files_to_compute(None, project_id, str(tmpdir), os.path.join("project-files", "docker")))
|
||||
await _move_files_to_compute(None, project_id, str(tmpdir), os.path.join("project-files", "docker"))
|
||||
|
||||
mock.assert_any_call(None, project_id, str(tmpdir / "project-files" / "docker" / "test"), os.path.join("project-files", "docker", "test"))
|
||||
mock.assert_any_call(None, project_id, str(tmpdir / "project-files" / "docker" / "test2"), os.path.join("project-files", "docker", "test2"))
|
||||
assert not os.path.exists(str(tmpdir / "project-files" / "docker"))
|
||||
|
||||
|
||||
def test_import_project_name_and_location(async_run, tmpdir, controller):
|
||||
async def test_import_project_name_and_location(tmpdir, controller):
|
||||
"""
|
||||
Import a project with a different location and name
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@ -531,7 +532,7 @@ def test_import_project_name_and_location(async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f, name="hello", location=str(tmpdir / "hello")))
|
||||
project = await import_project(controller, project_id, f, name="hello", location=str(tmpdir / "hello"))
|
||||
|
||||
assert project.name == "hello"
|
||||
|
||||
@ -539,5 +540,5 @@ def test_import_project_name_and_location(async_run, tmpdir, controller):
|
||||
|
||||
# A new project name is generated when you import twice the same name
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, str(uuid.uuid4()), f, name="hello", location=str(tmpdir / "test")))
|
||||
project = await import_project(controller, str(uuid.uuid4()), f, name="hello", location=str(tmpdir / "test"))
|
||||
assert project.name == "hello-1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,35 +15,20 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
||||
from gns3server.controller.link import Link
|
||||
from gns3server.controller.node import Node
|
||||
from gns3server.controller.ports.ethernet_port import EthernetPort
|
||||
from gns3server.controller.ports.serial_port import SerialPort
|
||||
from gns3server.controller.compute import Compute
|
||||
from gns3server.controller.project import Project
|
||||
|
||||
from tests.utils import AsyncioBytesIO, AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(controller=controller, name="Test")
|
||||
async def link(project, compute):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute():
|
||||
return Compute("example.com", controller=MagicMock())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def link(async_run, project, compute):
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
@ -51,26 +36,27 @@ def link(async_run, project, compute):
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 1, 3))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 1, 3)
|
||||
return link
|
||||
|
||||
|
||||
def test_eq(project, link, controller):
|
||||
def test_eq(project, link):
|
||||
|
||||
assert link == Link(project, link_id=link.id)
|
||||
assert link != "a"
|
||||
assert link != Link(project)
|
||||
|
||||
|
||||
def test_add_node(async_run, project, compute):
|
||||
async def test_add_node(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
project.dump = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
assert link._nodes == [
|
||||
{
|
||||
"node": node1,
|
||||
@ -85,23 +71,23 @@ def test_add_node(async_run, project, compute):
|
||||
]
|
||||
assert project.dump.called
|
||||
assert not link._project.emit_notification.called
|
||||
|
||||
assert not link.create.called
|
||||
|
||||
# We call link.created only when both side are created
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
assert link.create.called
|
||||
link._project.emit_notification.assert_called_with("link.created", link.__json__())
|
||||
assert link in node2.links
|
||||
|
||||
|
||||
def test_add_node_already_connected(async_run, project, compute):
|
||||
async def test_add_node_already_connected(project, compute):
|
||||
"""
|
||||
Raise an error if we try to use an already connected port
|
||||
"""
|
||||
|
||||
project.dump = AsyncioMagicMock()
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
@ -110,19 +96,20 @@ def test_add_node_already_connected(async_run, project, compute):
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
assert link.create.called
|
||||
link2 = Link(project)
|
||||
link2.create = AsyncioMagicMock()
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link2.add_node(node1, 0, 4))
|
||||
await link2.add_node(node1, 0, 4)
|
||||
|
||||
|
||||
def test_add_node_cloud(async_run, project, compute):
|
||||
async def test_add_node_cloud(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="cloud")
|
||||
@ -132,14 +119,15 @@ def test_add_node_cloud(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
|
||||
def test_add_node_cloud_to_cloud(async_run, project, compute):
|
||||
async def test_add_node_cloud_to_cloud(project, compute):
|
||||
"""
|
||||
Cloud to cloud connection is not allowed
|
||||
"""
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="cloud")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="cloud")
|
||||
@ -149,15 +137,16 @@ def test_add_node_cloud_to_cloud(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
|
||||
def test_add_node_same_node(async_run, project, compute):
|
||||
async def test_add_node_same_node(project, compute):
|
||||
"""
|
||||
Connection to the same node is not allowed
|
||||
"""
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4), EthernetPort("E1", 0, 0, 5)]
|
||||
|
||||
@ -165,15 +154,16 @@ def test_add_node_same_node(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link.add_node(node1, 0, 5))
|
||||
await link.add_node(node1, 0, 5)
|
||||
|
||||
|
||||
def test_add_node_serial_to_ethernet(async_run, project, compute):
|
||||
async def test_add_node_serial_to_ethernet(project, compute):
|
||||
"""
|
||||
Serial to ethernet connection is not allowed
|
||||
"""
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
@ -183,12 +173,13 @@ def test_add_node_serial_to_ethernet(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
|
||||
def test_json(async_run, project, compute, link):
|
||||
async def test_json(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
@ -196,8 +187,8 @@ def test_json(async_run, project, compute, link):
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 1, 3))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 1, 3)
|
||||
assert link.__json__() == {
|
||||
"link_id": link.id,
|
||||
"project_id": project.id,
|
||||
@ -256,7 +247,8 @@ def test_json(async_run, project, compute, link):
|
||||
}
|
||||
|
||||
|
||||
def test_json_serial_link(async_run, project, compute, link):
|
||||
async def test_json_serial_link(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [SerialPort("S0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
@ -264,11 +256,13 @@ def test_json_serial_link(async_run, project, compute, link):
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 1, 3))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 1, 3)
|
||||
assert link.__json__()["link_type"] == "serial"
|
||||
|
||||
def test_default_capture_file_name(project, compute, async_run):
|
||||
|
||||
async def test_default_capture_file_name(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "Hello@", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "w0.rld", node_type="qemu")
|
||||
@ -276,33 +270,35 @@ def test_default_capture_file_name(project, compute, async_run):
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 1, 3))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 1, 3)
|
||||
assert link.default_capture_file_name() == "Hello_0-4_to_w0rld_1-3.pcap"
|
||||
|
||||
|
||||
def test_start_capture(link, async_run, tmpdir):
|
||||
async def test_start_capture(link):
|
||||
|
||||
async def fake_reader():
|
||||
return AsyncioBytesIO()
|
||||
|
||||
link.read_pcap_from_source = fake_reader
|
||||
link._project.emit_notification = MagicMock()
|
||||
async_run(link.start_capture(capture_file_name="test.pcap"))
|
||||
await link.start_capture(capture_file_name="test.pcap")
|
||||
assert link._capturing
|
||||
assert link._capture_file_name == "test.pcap"
|
||||
link._project.emit_notification.assert_called_with("link.updated", link.__json__())
|
||||
|
||||
|
||||
def test_stop_capture(link, async_run, tmpdir):
|
||||
async def test_stop_capture(link):
|
||||
|
||||
link._capturing = True
|
||||
link._project.emit_notification = MagicMock()
|
||||
async_run(link.stop_capture())
|
||||
await link.stop_capture()
|
||||
assert link._capturing is False
|
||||
link._project.emit_notification.assert_called_with("link.updated", link.__json__())
|
||||
|
||||
|
||||
def test_delete(async_run, project, compute):
|
||||
async def test_delete(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
@ -310,19 +306,18 @@ def test_delete(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
project.dump = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
|
||||
await link.add_node(node2, 0, 4)
|
||||
assert link in node2.links
|
||||
|
||||
async_run(link.delete())
|
||||
await link.delete()
|
||||
assert link not in node2.links
|
||||
|
||||
|
||||
def test_update_filters(async_run, project, compute):
|
||||
async def test_update_filters(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
@ -330,20 +325,20 @@ def test_update_filters(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
project.dump = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
link.update = AsyncioMagicMock()
|
||||
assert link._created
|
||||
async_run(link.update_filters({
|
||||
await link.update_filters({
|
||||
"packet_loss": [10],
|
||||
"delay": [50, 10],
|
||||
"frequency_drop": [0],
|
||||
"bpf": [" \n "]
|
||||
}))
|
||||
})
|
||||
assert link.filters == {
|
||||
"packet_loss": [10],
|
||||
"delay": [50, 10]
|
||||
@ -351,7 +346,8 @@ def test_update_filters(async_run, project, compute):
|
||||
assert link.update.called
|
||||
|
||||
|
||||
def test_available_filters(async_run, project, compute):
|
||||
async def test_available_filters(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="ethernet_switch")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
@ -360,10 +356,10 @@ def test_available_filters(async_run, project, compute):
|
||||
assert link.available_filters() == []
|
||||
|
||||
# Ethernet switch is not supported should return 0 filters
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
assert link.available_filters() == []
|
||||
|
||||
node2 = Node(project, compute, "node2", node_type="vpcs")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
assert len(link.available_filters()) > 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,15 +16,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import shutil
|
||||
import aiohttp
|
||||
import pytest
|
||||
import uuid
|
||||
import asyncio
|
||||
import copy
|
||||
import os
|
||||
|
||||
from unittest.mock import MagicMock, ANY
|
||||
|
||||
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
from gns3server.controller.node import Node
|
||||
@ -33,18 +29,15 @@ from gns3server.controller.project import Project
|
||||
|
||||
@pytest.fixture
|
||||
def compute():
|
||||
|
||||
s = AsyncioMagicMock()
|
||||
s.id = "http://test.com:42"
|
||||
return s
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(str(uuid.uuid4()), controller=controller)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(compute, project):
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="vpcs",
|
||||
@ -57,6 +50,7 @@ def test_name(compute, project):
|
||||
"""
|
||||
If node use a name template generate names
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "PC",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="vpcs",
|
||||
@ -76,16 +70,13 @@ def test_name(compute, project):
|
||||
properties={"startup_script": "echo test"})
|
||||
assert node.name == "PC2"
|
||||
|
||||
# If we change the name to a name already used we patch the name to a free
|
||||
node.name == "PC1"
|
||||
assert node.name == "PC2"
|
||||
|
||||
|
||||
def test_vmname(compute, project):
|
||||
"""
|
||||
Additionnal properties should be add to the properties
|
||||
field
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "PC",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="virtualbox",
|
||||
@ -111,6 +102,7 @@ def test_empty_properties(compute, project):
|
||||
|
||||
|
||||
def test_eq(compute, project, node, controller):
|
||||
|
||||
assert node == Node(project, compute, "demo1", node_id=node.id, node_type="qemu")
|
||||
assert node != "a"
|
||||
assert node != Node(project, compute, "demo2", node_id=str(uuid.uuid4()), node_type="qemu")
|
||||
@ -118,6 +110,7 @@ def test_eq(compute, project, node, controller):
|
||||
|
||||
|
||||
def test_json(node, compute):
|
||||
|
||||
assert node.__json__() == {
|
||||
"compute_id": str(compute.id),
|
||||
"project_id": node.project.id,
|
||||
@ -156,6 +149,7 @@ def test_json(node, compute):
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
assert node.__json__(topology_dump=True) == {
|
||||
"compute_id": str(compute.id),
|
||||
"node_id": node.id,
|
||||
@ -188,14 +182,14 @@ def test_init_without_uuid(project, compute):
|
||||
assert node.id is not None
|
||||
|
||||
|
||||
def test_create(node, compute, project, async_run):
|
||||
node._console = 2048
|
||||
async def test_create(node, compute):
|
||||
|
||||
node._console = 2048
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
assert async_run(node.create()) is True
|
||||
assert await node.create() is True
|
||||
data = {
|
||||
"console": 2048,
|
||||
"console_type": "vnc",
|
||||
@ -208,9 +202,9 @@ def test_create(node, compute, project, async_run):
|
||||
assert node._properties == {"startup_script": "echo test"}
|
||||
|
||||
|
||||
def test_create_image_missing(node, compute, project, async_run):
|
||||
node._console = 2048
|
||||
async def test_create_image_missing(node, compute):
|
||||
|
||||
node._console = 2048
|
||||
node.__calls = 0
|
||||
|
||||
async def resp(*args, **kwargs):
|
||||
@ -226,13 +220,13 @@ def test_create_image_missing(node, compute, project, async_run):
|
||||
compute.post = AsyncioMagicMock(side_effect=resp)
|
||||
node._upload_missing_image = AsyncioMagicMock(return_value=True)
|
||||
|
||||
assert async_run(node.create()) is True
|
||||
node._upload_missing_image.called is True
|
||||
assert await node.create() is True
|
||||
#assert node._upload_missing_image.called is True
|
||||
|
||||
|
||||
def test_create_base_script(node, config, compute, tmpdir, async_run):
|
||||
async def test_create_base_script(node, config, compute, tmpdir):
|
||||
|
||||
config.set_section_config("Server", {"configs_path": str(tmpdir)})
|
||||
|
||||
with open(str(tmpdir / 'test.txt'), 'w+') as f:
|
||||
f.write('hostname test')
|
||||
|
||||
@ -243,7 +237,7 @@ def test_create_base_script(node, config, compute, tmpdir, async_run):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
assert async_run(node.create()) is True
|
||||
assert await node.create() is True
|
||||
data = {
|
||||
"console": 2048,
|
||||
"console_type": "vnc",
|
||||
@ -251,10 +245,11 @@ def test_create_base_script(node, config, compute, tmpdir, async_run):
|
||||
"startup_script": "hostname test",
|
||||
"name": "demo"
|
||||
}
|
||||
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes".format(node.project.id), data=data, timeout=1200)
|
||||
|
||||
|
||||
def test_symbol(node, symbols_dir, controller):
|
||||
def test_symbol(node, symbols_dir):
|
||||
"""
|
||||
Change symbol should change the node size
|
||||
"""
|
||||
@ -304,14 +299,15 @@ def test_label_with_default_label_font(node):
|
||||
assert node.label["style"] == None #"font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #ff0000;fill-opacity: 1.0;"
|
||||
|
||||
|
||||
def test_update(node, compute, project, async_run, controller):
|
||||
async def test_update(node, compute, project, controller):
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.put = AsyncioMagicMock(return_value=response)
|
||||
controller._notification = AsyncioMagicMock()
|
||||
project.dump = MagicMock()
|
||||
|
||||
async_run(node.update(x=42, console=2048, console_type="vnc", properties={"startup_script": "echo test"}, name="demo"))
|
||||
await node.update(x=42, console=2048, console_type="vnc", properties={"startup_script": "echo test"}, name="demo")
|
||||
data = {
|
||||
"console": 2048,
|
||||
"console_type": "vnc",
|
||||
@ -326,7 +322,7 @@ def test_update(node, compute, project, async_run, controller):
|
||||
assert project.dump.called
|
||||
|
||||
|
||||
def test_update_properties(node, compute, project, async_run, controller):
|
||||
async def test_update_properties(node, compute, controller):
|
||||
"""
|
||||
properties will be updated by the answer from compute
|
||||
"""
|
||||
@ -335,7 +331,7 @@ def test_update_properties(node, compute, project, async_run, controller):
|
||||
compute.put = AsyncioMagicMock(return_value=response)
|
||||
controller._notification = AsyncioMagicMock()
|
||||
|
||||
async_run(node.update(x=42, console=2048, console_type="vnc", properties={"startup_script": "hello world"}, name="demo"))
|
||||
await node.update(x=42, console=2048, console_type="vnc", properties={"startup_script": "hello world"}, name="demo")
|
||||
data = {
|
||||
"console": 2048,
|
||||
"console_type": "vnc",
|
||||
@ -354,26 +350,27 @@ def test_update_properties(node, compute, project, async_run, controller):
|
||||
#controller._notification.emit.assert_called_with("node.updated", node_notif)
|
||||
|
||||
|
||||
def test_update_only_controller(node, controller, compute, async_run):
|
||||
async def test_update_only_controller(node, compute):
|
||||
"""
|
||||
When updating property used only on controller we don't need to
|
||||
call the compute
|
||||
"""
|
||||
|
||||
compute.put = AsyncioMagicMock()
|
||||
node._project.emit_notification = AsyncioMagicMock()
|
||||
|
||||
async_run(node.update(x=42))
|
||||
await node.update(x=42)
|
||||
assert not compute.put.called
|
||||
assert node.x == 42
|
||||
node._project.emit_notification.assert_called_with("node.updated", node.__json__())
|
||||
|
||||
# If nothing change a second notif should not be send
|
||||
# If nothing change a second notif should not be sent
|
||||
node._project.emit_notification = AsyncioMagicMock()
|
||||
async_run(node.update(x=42))
|
||||
await node.update(x=42)
|
||||
assert not node._project.emit_notification.called
|
||||
|
||||
|
||||
def test_update_no_changes(node, compute, project, async_run):
|
||||
async def test_update_no_changes(node, compute):
|
||||
"""
|
||||
We don't call the compute node if all compute properties has not changed
|
||||
"""
|
||||
@ -381,24 +378,25 @@ def test_update_no_changes(node, compute, project, async_run):
|
||||
response.json = {"console": 2048}
|
||||
compute.put = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(node.update(console=2048, x=42))
|
||||
await node.update(console=2048, x=42)
|
||||
assert compute.put.called
|
||||
|
||||
compute.put = AsyncioMagicMock()
|
||||
async_run(node.update(console=2048, x=43))
|
||||
await node.update(console=2048, x=43)
|
||||
assert not compute.put.called
|
||||
assert node.x == 43
|
||||
|
||||
|
||||
def test_start(node, compute, project, async_run):
|
||||
async def test_start(node, compute):
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
|
||||
async_run(node.start())
|
||||
await node.start()
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/start".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_start_iou(compute, project, async_run, controller):
|
||||
async def test_start_iou(compute, project, controller):
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="iou")
|
||||
@ -409,44 +407,42 @@ def test_start_iou(compute, project, async_run, controller):
|
||||
# async_run(node.start())
|
||||
|
||||
controller._iou_license_settings = {"license_check": True, "iourc_content": "aa"}
|
||||
async_run(node.start())
|
||||
await node.start()
|
||||
compute.post.assert_called_with("/projects/{}/iou/nodes/{}/start".format(node.project.id, node.id), timeout=240, data={"license_check": True, "iourc_content": "aa"})
|
||||
|
||||
|
||||
def test_stop(node, compute, project, async_run):
|
||||
async def test_stop(node, compute):
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
|
||||
async_run(node.stop())
|
||||
await node.stop()
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/stop".format(node.project.id, node.id), timeout=240, dont_connect=True)
|
||||
|
||||
|
||||
def test_suspend(node, compute, project, async_run):
|
||||
async def test_suspend(node, compute):
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
|
||||
async_run(node.suspend())
|
||||
await node.suspend()
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/suspend".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_reload(node, compute, project, async_run):
|
||||
async def test_reload(node, compute):
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
|
||||
async_run(node.reload())
|
||||
await node.reload()
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/reload".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_create_without_console(node, compute, project, async_run):
|
||||
async def test_create_without_console(node, compute):
|
||||
"""
|
||||
None properties should be send. Because it can mean the emulator doesn"t support it
|
||||
None properties should be send. Because it can mean the emulator doesn't support it
|
||||
"""
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048, "test_value": "success"}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(node.create())
|
||||
await node.create()
|
||||
data = {
|
||||
"console_type": "vnc",
|
||||
"node_id": node.id,
|
||||
@ -458,49 +454,53 @@ def test_create_without_console(node, compute, project, async_run):
|
||||
assert node._properties == {"test_value": "success", "startup_script": "echo test"}
|
||||
|
||||
|
||||
def test_delete(node, compute, async_run):
|
||||
async_run(node.destroy())
|
||||
async def test_delete(node, compute):
|
||||
|
||||
await node.destroy()
|
||||
compute.delete.assert_called_with("/projects/{}/vpcs/nodes/{}".format(node.project.id, node.id))
|
||||
|
||||
|
||||
def test_post(node, compute, async_run):
|
||||
async_run(node.post("/test", {"a": "b"}))
|
||||
async def test_post(node, compute):
|
||||
|
||||
await node.post("/test", {"a": "b"})
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/test".format(node.project.id, node.id), data={"a": "b"})
|
||||
|
||||
|
||||
def test_delete(node, compute, async_run):
|
||||
async_run(node.delete("/test"))
|
||||
async def test_delete(node, compute):
|
||||
|
||||
await node.delete("/test")
|
||||
compute.delete.assert_called_with("/projects/{}/vpcs/nodes/{}/test".format(node.project.id, node.id))
|
||||
|
||||
|
||||
def test_dynamips_idle_pc(node, async_run, compute):
|
||||
async def test_dynamips_idle_pc(node, compute):
|
||||
|
||||
node._node_type = "dynamips"
|
||||
response = MagicMock()
|
||||
response.json = {"idlepc": "0x60606f54"}
|
||||
compute.get = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(node.dynamips_auto_idlepc())
|
||||
await node.dynamips_auto_idlepc()
|
||||
compute.get.assert_called_with("/projects/{}/dynamips/nodes/{}/auto_idlepc".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_dynamips_idlepc_proposals(node, async_run, compute):
|
||||
async def test_dynamips_idlepc_proposals(node, compute):
|
||||
|
||||
node._node_type = "dynamips"
|
||||
response = MagicMock()
|
||||
response.json = ["0x60606f54", "0x30ff6f37"]
|
||||
compute.get = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(node.dynamips_idlepc_proposals())
|
||||
await node.dynamips_idlepc_proposals()
|
||||
compute.get.assert_called_with("/projects/{}/dynamips/nodes/{}/idlepc_proposals".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_upload_missing_image(compute, controller, async_run, images_dir):
|
||||
async def test_upload_missing_image(compute, controller, images_dir):
|
||||
|
||||
project = Project(str(uuid.uuid4()), controller=controller)
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="qemu",
|
||||
properties={"hda_disk_image": "linux.img"})
|
||||
open(os.path.join(images_dir, "linux.img"), 'w+').close()
|
||||
assert async_run(node._upload_missing_image("qemu", "linux.img")) is True
|
||||
assert await node._upload_missing_image("qemu", "linux.img") is True
|
||||
compute.post.assert_called_with("/qemu/images/linux.img", data=ANY, timeout=None)
|
||||
|
||||
|
||||
@ -509,6 +509,7 @@ def test_update_label(node):
|
||||
The text in label need to be always the
|
||||
node name
|
||||
"""
|
||||
|
||||
node.name = "Test"
|
||||
assert node.label["text"] == "Test"
|
||||
node.label = {"text": "Wrong", "x": 12}
|
||||
@ -517,6 +518,7 @@ def test_update_label(node):
|
||||
|
||||
|
||||
def test_get_port(node):
|
||||
|
||||
node._node_type = "qemu"
|
||||
node._properties["adapters"] = 2
|
||||
node._list_ports()
|
||||
@ -529,12 +531,13 @@ def test_get_port(node):
|
||||
assert port is None
|
||||
|
||||
|
||||
def test_parse_node_response(node, async_run):
|
||||
async def test_parse_node_response(node):
|
||||
"""
|
||||
When a node is updated we notify the links connected to it
|
||||
"""
|
||||
|
||||
link = MagicMock()
|
||||
link.node_updated = AsyncioMagicMock()
|
||||
node.add_link(link)
|
||||
async_run(node.parse_node_response({"status": "started"}))
|
||||
await node.parse_node_response({"status": "started"})
|
||||
assert link.node_updated.called
|
||||
|
@ -21,7 +21,6 @@ import uuid
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
from gns3server.controller.node import Node
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.ports.ethernet_port import EthernetPort
|
||||
|
||||
|
||||
@ -31,12 +30,6 @@ def compute():
|
||||
s.id = "http://test.com:42"
|
||||
return s
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(str(uuid.uuid4()), controller=controller)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(compute, project):
|
||||
node = Node(project, compute, "demo",
|
||||
@ -51,6 +44,7 @@ def test_list_ports(node):
|
||||
"""
|
||||
List port by default
|
||||
"""
|
||||
|
||||
assert node.__json__()["ports"] == [
|
||||
{
|
||||
"name": "Ethernet0",
|
||||
@ -67,6 +61,7 @@ def test_list_ports_vpcs(node):
|
||||
"""
|
||||
List port by default
|
||||
"""
|
||||
|
||||
node._node_type = "vpcs"
|
||||
assert node.__json__()["ports"] == [
|
||||
{
|
||||
@ -84,6 +79,7 @@ def test_list_ports_docker(node):
|
||||
"""
|
||||
List port by default
|
||||
"""
|
||||
|
||||
node._node_type = "docker"
|
||||
node._properties["adapters"] = 2
|
||||
assert node.__json__()["ports"] == [
|
||||
@ -110,6 +106,7 @@ def test_list_ports_port_name_format(node):
|
||||
"""
|
||||
Support port name format
|
||||
"""
|
||||
|
||||
node._first_port_name = None
|
||||
node._port_name_format = "eth{}"
|
||||
node._list_ports()
|
||||
@ -139,6 +136,7 @@ def test_list_ports_adapters(node):
|
||||
"""
|
||||
List port using adapters properties
|
||||
"""
|
||||
|
||||
node.properties["adapters"] = 2
|
||||
assert node.__json__()["ports"] == [
|
||||
{
|
||||
@ -164,6 +162,7 @@ def test_list_ports_adapters_cloud(project, compute):
|
||||
"""
|
||||
List port using adapters properties
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="cloud")
|
||||
@ -192,6 +191,7 @@ def test_list_ports_ethernet_hub(project, compute):
|
||||
"""
|
||||
List port for atm switch
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="ethernet_hub")
|
||||
@ -230,6 +230,7 @@ def test_list_ports_atm_switch(project, compute):
|
||||
"""
|
||||
List port for atm switch
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="atm_switch")
|
||||
@ -261,6 +262,7 @@ def test_list_ports_frame_relay_switch(project, compute):
|
||||
"""
|
||||
List port for frame relay switch
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="frame_relay_switch")
|
||||
@ -309,6 +311,7 @@ def test_list_ports_iou(compute, project):
|
||||
"""
|
||||
IOU has a special behavior 4 port by adapters
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="iou")
|
||||
@ -514,6 +517,7 @@ def test_list_ports_dynamips(project, compute):
|
||||
"""
|
||||
List port for dynamips
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="dynamips")
|
||||
@ -595,6 +599,7 @@ def test_list_ports_dynamips(project, compute):
|
||||
|
||||
|
||||
def test_short_name():
|
||||
|
||||
# If no customization of port name format return the default short name
|
||||
assert EthernetPort("Ethernet0", 0, 0, 0).short_name == "e0"
|
||||
assert EthernetPort("Ethernet0", 0, 0, 0, short_name="mgmt").short_name == "mgmt"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -18,81 +18,78 @@
|
||||
import pytest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from gns3server.controller.notification import Notification
|
||||
from gns3server.controller import Controller
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(async_run):
|
||||
return async_run(Controller.instance().add_project(name="Test"))
|
||||
async def node(project):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(project, async_run):
|
||||
compute = MagicMock()
|
||||
compute.id = "remote1"
|
||||
compute.host = "example.org"
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
return async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
return await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
|
||||
def test_emit_to_all(async_run, controller, project):
|
||||
async def test_emit_to_all(controller, project):
|
||||
"""
|
||||
Send an event to all if we don't have a project id in the event
|
||||
"""
|
||||
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
await queue.get(0.1) # ping
|
||||
notif.project_emit('test', {})
|
||||
msg = async_run(queue.get(5))
|
||||
msg = await queue.get(5)
|
||||
assert msg == ('test', {}, {})
|
||||
|
||||
assert len(notif._project_listeners[project.id]) == 0
|
||||
|
||||
|
||||
def test_emit_to_project(async_run, controller, project):
|
||||
async def test_emit_to_project(controller, project):
|
||||
"""
|
||||
Send an event to a project listeners
|
||||
"""
|
||||
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
await queue.get(0.1) # ping
|
||||
# This event has not listener
|
||||
notif.project_emit('ignore', {"project_id": 42})
|
||||
notif.project_emit('test', {"project_id": project.id})
|
||||
msg = async_run(queue.get(5))
|
||||
msg = await queue.get(5)
|
||||
assert msg == ('test', {"project_id": project.id}, {})
|
||||
|
||||
assert len(notif._project_listeners[project.id]) == 0
|
||||
|
||||
|
||||
def test_dispatch(async_run, controller, project):
|
||||
async def test_dispatch(controller, project):
|
||||
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
async_run(notif.dispatch("test", {}, project_id=project.id, compute_id=1))
|
||||
msg = async_run(queue.get(5))
|
||||
await queue.get(0.1) # ping
|
||||
await notif.dispatch("test", {}, project_id=project.id, compute_id=1)
|
||||
msg = await queue.get(5)
|
||||
assert msg == ('test', {}, {})
|
||||
|
||||
|
||||
def test_dispatch_ping(async_run, controller, project):
|
||||
async def test_dispatch_ping(controller, project):
|
||||
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
async_run(notif.dispatch("ping", {}, project_id=project.id, compute_id=12))
|
||||
msg = async_run(queue.get(5))
|
||||
await queue.get(0.1) # ping
|
||||
await notif.dispatch("ping", {}, project_id=project.id, compute_id=12)
|
||||
msg = await queue.get(5)
|
||||
assert msg == ('ping', {'compute_id': 12}, {})
|
||||
|
||||
|
||||
def test_dispatch_node_updated(async_run, controller, node, project):
|
||||
async def test_dispatch_node_updated(controller, node, project):
|
||||
"""
|
||||
When we receive a node.updated notification from compute
|
||||
we need to update the client
|
||||
@ -101,25 +98,26 @@ def test_dispatch_node_updated(async_run, controller, node, project):
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
async_run(notif.dispatch("node.updated", {
|
||||
await queue.get(0.1) # ping
|
||||
await notif.dispatch("node.updated", {
|
||||
"node_id": node.id,
|
||||
"project_id": project.id,
|
||||
"name": "hello",
|
||||
"startup_config": "ip 192"
|
||||
},
|
||||
project_id=project.id,
|
||||
compute_id=1))
|
||||
compute_id=1)
|
||||
assert node.name == "hello"
|
||||
action, event, _ = async_run(queue.get(5))
|
||||
action, event, _ = await queue.get(5)
|
||||
assert action == "node.updated"
|
||||
assert event["name"] == "hello"
|
||||
assert event["properties"]["startup_config"] == "ip 192"
|
||||
|
||||
|
||||
def test_various_notification(controller, node):
|
||||
|
||||
notif = controller.notification
|
||||
notif.project_emit("log.info", {"message": "Image uploaded"})
|
||||
notif.project_emit("log.warning", {"message": "Warning ASA 8 is not officialy supported by GNS3"})
|
||||
notif.project_emit("log.warning", {"message": "Warning ASA 8 is not officially supported by GNS3"})
|
||||
notif.project_emit("log.error", {"message": "Permission denied on /tmp"})
|
||||
notif.project_emit("node.updated", node.__json__())
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -34,33 +34,29 @@ from gns3server.config import Config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(controller=controller, name="Test")
|
||||
async def node(controller, project):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(controller, project, async_run):
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
return node
|
||||
|
||||
|
||||
def test_affect_uuid():
|
||||
async def test_affect_uuid():
|
||||
|
||||
p = Project(name="Test")
|
||||
assert len(p.id) == 36
|
||||
|
||||
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test 2")
|
||||
assert p.id == '00010203-0405-0607-0809-0a0b0c0d0e0f'
|
||||
|
||||
|
||||
def test_json(tmpdir):
|
||||
async def test_json():
|
||||
|
||||
p = Project(name="Test")
|
||||
|
||||
assert p.__json__() == {
|
||||
"name": "Test",
|
||||
"project_id": p.id,
|
||||
@ -84,34 +80,31 @@ def test_json(tmpdir):
|
||||
}
|
||||
|
||||
|
||||
def test_update(controller, async_run):
|
||||
async def test_update(controller):
|
||||
|
||||
project = Project(controller=controller, name="Hello")
|
||||
project.emit_notification = MagicMock()
|
||||
assert project.name == "Hello"
|
||||
async_run(project.update(name="World"))
|
||||
await project.update(name="World")
|
||||
assert project.name == "World"
|
||||
project.emit_notification.assert_any_call("project.updated", project.__json__())
|
||||
|
||||
|
||||
def test_update_on_compute(controller, async_run):
|
||||
async def test_update_on_compute(controller):
|
||||
|
||||
variables = [{"name": "TEST", "value": "VAL1"}]
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = Project(controller=controller, name="Test")
|
||||
project._project_created_on_compute = [compute]
|
||||
project.emit_notification = MagicMock()
|
||||
|
||||
async_run(project.update(variables=variables))
|
||||
|
||||
compute.put.assert_any_call('/projects/{}'.format(project.id), {
|
||||
"variables": variables
|
||||
})
|
||||
await project.update(variables=variables)
|
||||
compute.put.assert_any_call('/projects/{}'.format(project.id), {"variables": variables})
|
||||
|
||||
|
||||
def test_path(tmpdir):
|
||||
|
||||
directory = Config.instance().get_section_config("Server").get("projects_path")
|
||||
async def test_path(projects_dir):
|
||||
|
||||
directory = projects_dir
|
||||
with patch("gns3server.utils.path.get_default_project_directory", return_value=directory):
|
||||
p = Project(project_id=str(uuid4()), name="Test")
|
||||
assert p.path == os.path.join(directory, p.id)
|
||||
@ -120,37 +113,41 @@ def test_path(tmpdir):
|
||||
|
||||
def test_path_exist(tmpdir):
|
||||
"""
|
||||
Should raise an error when you try to owerwrite
|
||||
Should raise an error when you try to overwrite
|
||||
an existing project
|
||||
"""
|
||||
|
||||
os.makedirs(str(tmpdir / "demo"))
|
||||
with pytest.raises(aiohttp.web.HTTPForbidden):
|
||||
p = Project(name="Test", path=str(tmpdir / "demo"))
|
||||
Project(name="Test", path=str(tmpdir / "demo"))
|
||||
|
||||
|
||||
def test_init_path(tmpdir):
|
||||
async def test_init_path(tmpdir):
|
||||
|
||||
p = Project(path=str(tmpdir), project_id=str(uuid4()), name="Test")
|
||||
assert p.path == str(tmpdir)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_changing_path_with_quote_not_allowed(tmpdir):
|
||||
async def test_changing_path_with_quote_not_allowed(tmpdir):
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPForbidden):
|
||||
p = Project(project_id=str(uuid4()), name="Test")
|
||||
p.path = str(tmpdir / "project\"53")
|
||||
|
||||
|
||||
def test_captures_directory(tmpdir):
|
||||
async def test_captures_directory(tmpdir):
|
||||
|
||||
p = Project(path=str(tmpdir / "capturestest"), name="Test")
|
||||
assert p.captures_directory == str(tmpdir / "capturestest" / "project-files" / "captures")
|
||||
assert os.path.exists(p.captures_directory)
|
||||
|
||||
|
||||
def test_add_node_local(async_run, controller):
|
||||
async def test_add_node_local(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = Project(controller=controller, name="Test")
|
||||
@ -160,7 +157,7 @@ def test_add_node_local(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"})
|
||||
assert node.id in project._nodes
|
||||
|
||||
compute.post.assert_any_call('/projects', data={
|
||||
@ -177,10 +174,11 @@ def test_add_node_local(async_run, controller):
|
||||
project.emit_notification.assert_any_call("node.created", node.__json__())
|
||||
|
||||
|
||||
def test_add_node_non_local(async_run, controller):
|
||||
async def test_add_node_non_local(controller):
|
||||
"""
|
||||
For a non local server we do not send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "remote"
|
||||
project = Project(controller=controller, name="Test")
|
||||
@ -190,67 +188,66 @@ def test_add_node_non_local(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"})
|
||||
|
||||
compute.post.assert_any_call('/projects', data={
|
||||
"name": project._name,
|
||||
"project_id": project._id
|
||||
})
|
||||
compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id),
|
||||
data={'node_id': node.id,
|
||||
'startup_script': 'test.cfg',
|
||||
'name': 'test'},
|
||||
timeout=1200)
|
||||
compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id,
|
||||
'startup_script': 'test.cfg',
|
||||
'name': 'test'}, timeout=1200)
|
||||
assert compute in project._project_created_on_compute
|
||||
project.emit_notification.assert_any_call("node.created", node.__json__())
|
||||
|
||||
|
||||
def test_add_node_iou(async_run, controller):
|
||||
async def test_add_node_iou(controller):
|
||||
"""
|
||||
Test if an application ID is allocated for IOU nodes
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test1"))
|
||||
project = await controller.add_project(project_id=str(uuid.uuid4()), name="test1")
|
||||
project.emit_notification = MagicMock()
|
||||
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project.add_node(compute, "test1", None, node_type="iou"))
|
||||
node2 = async_run(project.add_node(compute, "test2", None, node_type="iou"))
|
||||
node3 = async_run(project.add_node(compute, "test3", None, node_type="iou"))
|
||||
node1 = await project.add_node(compute, "test1", None, node_type="iou")
|
||||
node2 = await project.add_node(compute, "test2", None, node_type="iou")
|
||||
node3 = await project.add_node(compute, "test3", None, node_type="iou")
|
||||
assert node1.properties["application_id"] == 1
|
||||
assert node2.properties["application_id"] == 2
|
||||
assert node3.properties["application_id"] == 3
|
||||
|
||||
|
||||
def test_add_node_iou_with_multiple_projects(async_run, controller):
|
||||
async def test_add_node_iou_with_multiple_projects(controller):
|
||||
"""
|
||||
Test if an application ID is allocated for IOU nodes with different projects already opened
|
||||
"""
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project1 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test1"))
|
||||
project1 = await controller.add_project(project_id=str(uuid.uuid4()), name="test1")
|
||||
project1.emit_notification = MagicMock()
|
||||
project2 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test2"))
|
||||
project2 = await controller.add_project(project_id=str(uuid.uuid4()), name="test2")
|
||||
project2.emit_notification = MagicMock()
|
||||
project3 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test3"))
|
||||
project3 = await controller.add_project(project_id=str(uuid.uuid4()), name="test3")
|
||||
project3.emit_notification = MagicMock()
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project1.add_node(compute, "test1", None, node_type="iou"))
|
||||
node2 = async_run(project1.add_node(compute, "test2", None, node_type="iou"))
|
||||
node3 = async_run(project1.add_node(compute, "test3", None, node_type="iou"))
|
||||
node1 = await project1.add_node(compute, "test1", None, node_type="iou")
|
||||
node2 = await project1.add_node(compute, "test2", None, node_type="iou")
|
||||
node3 = await project1.add_node(compute, "test3", None, node_type="iou")
|
||||
|
||||
node4 = async_run(project2.add_node(compute, "test4", None, node_type="iou"))
|
||||
node5 = async_run(project2.add_node(compute, "test5", None, node_type="iou"))
|
||||
node6 = async_run(project2.add_node(compute, "test6", None, node_type="iou"))
|
||||
node4 = await project2.add_node(compute, "test4", None, node_type="iou")
|
||||
node5 = await project2.add_node(compute, "test5", None, node_type="iou")
|
||||
node6 = await project2.add_node(compute, "test6", None, node_type="iou")
|
||||
|
||||
node7 = async_run(project3.add_node(compute, "test7", None, node_type="iou"))
|
||||
node8 = async_run(project3.add_node(compute, "test8", None, node_type="iou"))
|
||||
node9 = async_run(project3.add_node(compute, "test9", None, node_type="iou"))
|
||||
node7 = await project3.add_node(compute, "test7", None, node_type="iou")
|
||||
node8 = await project3.add_node(compute, "test8", None, node_type="iou")
|
||||
node9 = await project3.add_node(compute, "test9", None, node_type="iou")
|
||||
|
||||
assert node1.properties["application_id"] == 1
|
||||
assert node2.properties["application_id"] == 2
|
||||
@ -265,19 +262,19 @@ def test_add_node_iou_with_multiple_projects(async_run, controller):
|
||||
assert node9.properties["application_id"] == 9
|
||||
|
||||
controller.remove_project(project1)
|
||||
project4 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test4"))
|
||||
project4 = await controller.add_project(project_id=str(uuid.uuid4()), name="test4")
|
||||
project4.emit_notification = MagicMock()
|
||||
|
||||
node10 = async_run(project3.add_node(compute, "test10", None, node_type="iou"))
|
||||
node11 = async_run(project3.add_node(compute, "test11", None, node_type="iou"))
|
||||
node12 = async_run(project3.add_node(compute, "test12", None, node_type="iou"))
|
||||
node10 = await project3.add_node(compute, "test10", None, node_type="iou")
|
||||
node11 = await project3.add_node(compute, "test11", None, node_type="iou")
|
||||
node12 = await project3.add_node(compute, "test12", None, node_type="iou")
|
||||
|
||||
assert node10.properties["application_id"] == 1
|
||||
assert node11.properties["application_id"] == 2
|
||||
assert node12.properties["application_id"] == 3
|
||||
|
||||
|
||||
def test_add_node_iou_with_multiple_projects_different_computes(async_run, controller):
|
||||
async def test_add_node_iou_with_multiple_projects_different_computes(controller):
|
||||
"""
|
||||
Test if an application ID is allocated for IOU nodes with different projects already opened
|
||||
"""
|
||||
@ -285,19 +282,19 @@ def test_add_node_iou_with_multiple_projects_different_computes(async_run, contr
|
||||
compute1.id = "remote1"
|
||||
compute2 = MagicMock()
|
||||
compute2.id = "remote2"
|
||||
project1 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test1"))
|
||||
project1 = await controller.add_project(project_id=str(uuid.uuid4()), name="test1")
|
||||
project1.emit_notification = MagicMock()
|
||||
project2 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test2"))
|
||||
project2 = await controller.add_project(project_id=str(uuid.uuid4()), name="test2")
|
||||
project2.emit_notification = MagicMock()
|
||||
response = MagicMock()
|
||||
compute1.post = AsyncioMagicMock(return_value=response)
|
||||
compute2.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project1.add_node(compute1, "test1", None, node_type="iou"))
|
||||
node2 = async_run(project1.add_node(compute1, "test2", None, node_type="iou"))
|
||||
node1 = await project1.add_node(compute1, "test1", None, node_type="iou")
|
||||
node2 = await project1.add_node(compute1, "test2", None, node_type="iou")
|
||||
|
||||
node3 = async_run(project2.add_node(compute2, "test3", None, node_type="iou"))
|
||||
node4 = async_run(project2.add_node(compute2, "test4", None, node_type="iou"))
|
||||
node3 = await project2.add_node(compute2, "test3", None, node_type="iou")
|
||||
node4 = await project2.add_node(compute2, "test4", None, node_type="iou")
|
||||
|
||||
assert node1.properties["application_id"] == 1
|
||||
assert node2.properties["application_id"] == 2
|
||||
@ -305,20 +302,21 @@ def test_add_node_iou_with_multiple_projects_different_computes(async_run, contr
|
||||
assert node3.properties["application_id"] == 1
|
||||
assert node4.properties["application_id"] == 2
|
||||
|
||||
node5 = async_run(project1.add_node(compute2, "test5", None, node_type="iou"))
|
||||
node6 = async_run(project2.add_node(compute1, "test6", None, node_type="iou"))
|
||||
node5 = await project1.add_node(compute2, "test5", None, node_type="iou")
|
||||
node6 = await project2.add_node(compute1, "test6", None, node_type="iou")
|
||||
|
||||
assert node5.properties["application_id"] == 3
|
||||
assert node6.properties["application_id"] == 4
|
||||
|
||||
|
||||
def test_add_node_iou_no_id_available(async_run, controller):
|
||||
async def test_add_node_iou_no_id_available(controller):
|
||||
"""
|
||||
Test if an application ID is allocated for IOU nodes
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test"))
|
||||
project = await controller.add_project(project_id=str(uuid.uuid4()), name="test")
|
||||
project.emit_notification = MagicMock()
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
@ -327,13 +325,14 @@ def test_add_node_iou_no_id_available(async_run, controller):
|
||||
for i in range(1, 513):
|
||||
prop = {"properties": {"application_id": i}}
|
||||
project._nodes[i] = Node(project, compute, "Node{}".format(i), node_id=i, node_type="iou", **prop)
|
||||
async_run(project.add_node(compute, "test1", None, node_type="iou"))
|
||||
await project.add_node(compute, "test1", None, node_type="iou")
|
||||
|
||||
|
||||
def test_add_node_from_template(async_run, controller):
|
||||
async def test_add_node_from_template(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = Project(controller=controller, name="Test")
|
||||
@ -351,7 +350,7 @@ def test_add_node_from_template(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node_from_template(template.id, x=23, y=12))
|
||||
node = await project.add_node_from_template(template.id, x=23, y=12)
|
||||
compute.post.assert_any_call('/projects', data={
|
||||
"name": project._name,
|
||||
"project_id": project._id,
|
||||
@ -362,10 +361,11 @@ def test_add_node_from_template(async_run, controller):
|
||||
project.emit_notification.assert_any_call("node.created", node.__json__())
|
||||
|
||||
|
||||
def test_add_builtin_node_from_template(async_run, controller):
|
||||
async def test_add_builtin_node_from_template(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = Project(controller=controller, name="Test")
|
||||
@ -374,6 +374,7 @@ def test_add_builtin_node_from_template(async_run, controller):
|
||||
"name": "Builtin-switch",
|
||||
"template_type": "ethernet_switch",
|
||||
}, builtin=True)
|
||||
|
||||
controller.template_manager.templates[template.id] = template
|
||||
template.__json__()
|
||||
controller._computes["local"] = compute
|
||||
@ -382,7 +383,7 @@ def test_add_builtin_node_from_template(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node_from_template(template.id, x=23, y=12, compute_id="local"))
|
||||
node = await project.add_node_from_template(template.id, x=23, y=12, compute_id="local")
|
||||
compute.post.assert_any_call('/projects', data={
|
||||
"name": project._name,
|
||||
"project_id": project._id,
|
||||
@ -393,7 +394,7 @@ def test_add_builtin_node_from_template(async_run, controller):
|
||||
project.emit_notification.assert_any_call("node.created", node.__json__())
|
||||
|
||||
|
||||
def test_delete_node(async_run, controller):
|
||||
async def test_delete_node(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
@ -405,19 +406,20 @@ def test_delete_node(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.id in project._nodes
|
||||
async_run(project.delete_node(node.id))
|
||||
await project.delete_node(node.id)
|
||||
assert node.id not in project._nodes
|
||||
|
||||
compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id))
|
||||
project.emit_notification.assert_any_call("node.deleted", node.__json__())
|
||||
|
||||
|
||||
def test_delete_locked_node(async_run, controller):
|
||||
async def test_delete_locked_node(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
project = Project(controller=controller, name="Test")
|
||||
project.emit_notification = MagicMock()
|
||||
@ -426,14 +428,14 @@ def test_delete_locked_node(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.id in project._nodes
|
||||
node.locked = True
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPConflict):
|
||||
async_run(project.delete_node(node.id))
|
||||
await project.delete_node(node.id)
|
||||
|
||||
|
||||
def test_delete_node_delete_link(async_run, controller):
|
||||
async def test_delete_node_delete_link(controller):
|
||||
"""
|
||||
Delete a node delete all the node connected
|
||||
"""
|
||||
@ -445,12 +447,12 @@ def test_delete_node_delete_link(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
link = async_run(project.add_link())
|
||||
async_run(link.add_node(node, 0, 0))
|
||||
link = await project.add_link()
|
||||
await link.add_node(node, 0, 0)
|
||||
|
||||
async_run(project.delete_node(node.id))
|
||||
await project.delete_node(node.id)
|
||||
assert node.id not in project._nodes
|
||||
assert link.id not in project._links
|
||||
|
||||
@ -459,7 +461,8 @@ def test_delete_node_delete_link(async_run, controller):
|
||||
project.emit_notification.assert_any_call("link.deleted", link.__json__())
|
||||
|
||||
|
||||
def test_get_node(async_run, controller):
|
||||
async def test_get_node(controller):
|
||||
|
||||
compute = MagicMock()
|
||||
project = Project(controller=controller, name="Test")
|
||||
|
||||
@ -467,18 +470,20 @@ def test_get_node(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
vm = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
vm = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert project.get_node(vm.id) == vm
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project.get_node("test")
|
||||
|
||||
# Raise an error if the project is not opened
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
with pytest.raises(aiohttp.web.HTTPForbidden):
|
||||
project.get_node(vm.id)
|
||||
|
||||
def test_list_nodes(async_run, controller):
|
||||
|
||||
async def test_list_nodes(controller):
|
||||
|
||||
compute = MagicMock()
|
||||
project = Project(controller=controller, name="Test")
|
||||
|
||||
@ -486,157 +491,163 @@ def test_list_nodes(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
vm = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
vm = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert len(project.nodes) == 1
|
||||
assert isinstance(project.nodes, dict)
|
||||
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert len(project.nodes) == 1
|
||||
assert isinstance(project.nodes, dict)
|
||||
|
||||
|
||||
def test_add_link(async_run, project, controller):
|
||||
async def test_add_link(project):
|
||||
|
||||
compute = MagicMock()
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
vm1 = async_run(project.add_node(compute, "test1", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
vm1 = await project.add_node(compute, "test1", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
vm1._ports = [EthernetPort("E0", 0, 3, 1)]
|
||||
vm2 = async_run(project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
vm2 = await project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
vm2._ports = [EthernetPort("E0", 0, 4, 2)]
|
||||
project.emit_notification = MagicMock()
|
||||
link = async_run(project.add_link())
|
||||
async_run(link.add_node(vm1, 3, 1))
|
||||
link = await project.add_link()
|
||||
await link.add_node(vm1, 3, 1)
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock_udp_create:
|
||||
async_run(link.add_node(vm2, 4, 2))
|
||||
await link.add_node(vm2, 4, 2)
|
||||
assert mock_udp_create.called
|
||||
assert len(link._nodes) == 2
|
||||
project.emit_notification.assert_any_call("link.created", link.__json__())
|
||||
|
||||
|
||||
def test_list_links(async_run, project):
|
||||
compute = MagicMock()
|
||||
async def test_list_links(project):
|
||||
|
||||
compute = MagicMock()
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
link = async_run(project.add_link())
|
||||
await project.add_link()
|
||||
assert len(project.links) == 1
|
||||
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert len(project.links) == 1
|
||||
|
||||
|
||||
def test_get_link(async_run, project):
|
||||
async def test_get_link(project):
|
||||
|
||||
compute = MagicMock()
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
link = async_run(project.add_link())
|
||||
link = await project.add_link()
|
||||
assert project.get_link(link.id) == link
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project.get_link("test")
|
||||
|
||||
|
||||
def test_delete_link(async_run, project, controller):
|
||||
compute = MagicMock()
|
||||
async def test_delete_link(project):
|
||||
|
||||
compute = MagicMock()
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
assert len(project._links) == 0
|
||||
link = async_run(project.add_link())
|
||||
link = await project.add_link()
|
||||
assert len(project._links) == 1
|
||||
project.emit_notification = MagicMock()
|
||||
async_run(project.delete_link(link.id))
|
||||
await project.delete_link(link.id)
|
||||
project.emit_notification.assert_any_call("link.deleted", link.__json__())
|
||||
assert len(project._links) == 0
|
||||
|
||||
|
||||
def test_add_drawing(async_run, project, controller):
|
||||
project.emit_notification = MagicMock()
|
||||
async def test_add_drawing(project):
|
||||
|
||||
drawing = async_run(project.add_drawing(None, svg="<svg></svg>"))
|
||||
project.emit_notification = MagicMock()
|
||||
drawing = await project.add_drawing(None, svg="<svg></svg>")
|
||||
assert len(project._drawings) == 1
|
||||
project.emit_notification.assert_any_call("drawing.created", drawing.__json__())
|
||||
|
||||
|
||||
def test_get_drawing(async_run, project):
|
||||
drawing = async_run(project.add_drawing(None))
|
||||
async def test_get_drawing(project):
|
||||
|
||||
drawing = await project.add_drawing(None)
|
||||
assert project.get_drawing(drawing.id) == drawing
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project.get_drawing("test")
|
||||
|
||||
|
||||
def test_list_drawing(async_run, project):
|
||||
drawing = async_run(project.add_drawing(None))
|
||||
async def test_list_drawing(project):
|
||||
|
||||
await project.add_drawing(None)
|
||||
assert len(project.drawings) == 1
|
||||
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert len(project.drawings) == 1
|
||||
|
||||
|
||||
def test_delete_drawing(async_run, project, controller):
|
||||
async def test_delete_drawing(project):
|
||||
|
||||
assert len(project._drawings) == 0
|
||||
drawing = async_run(project.add_drawing())
|
||||
drawing = await project.add_drawing()
|
||||
assert len(project._drawings) == 1
|
||||
project.emit_notification = MagicMock()
|
||||
async_run(project.delete_drawing(drawing.id))
|
||||
await project.delete_drawing(drawing.id)
|
||||
project.emit_notification.assert_any_call("drawing.deleted", drawing.__json__())
|
||||
assert len(project._drawings) == 0
|
||||
|
||||
|
||||
def test_clean_pictures(async_run, project, controller):
|
||||
async def test_clean_pictures(project):
|
||||
"""
|
||||
When a project is close old pictures should be removed
|
||||
"""
|
||||
|
||||
drawing = async_run(project.add_drawing())
|
||||
drawing = await project.add_drawing()
|
||||
drawing._svg = "test.png"
|
||||
open(os.path.join(project.pictures_directory, "test.png"), "w+").close()
|
||||
open(os.path.join(project.pictures_directory, "test2.png"), "w+").close()
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert os.path.exists(os.path.join(project.pictures_directory, "test.png"))
|
||||
assert not os.path.exists(os.path.join(project.pictures_directory, "test2.png"))
|
||||
|
||||
|
||||
def test_clean_pictures_and_keep_supplier_logo(async_run, project, controller):
|
||||
async def test_clean_pictures_and_keep_supplier_logo(project):
|
||||
"""
|
||||
When a project is close old pictures should be removed
|
||||
"""
|
||||
|
||||
project.supplier = {
|
||||
'logo': 'logo.png'
|
||||
}
|
||||
|
||||
drawing = async_run(project.add_drawing())
|
||||
drawing = await project.add_drawing()
|
||||
drawing._svg = "test.png"
|
||||
open(os.path.join(project.pictures_directory, "test.png"), "w+").close()
|
||||
open(os.path.join(project.pictures_directory, "test2.png"), "w+").close()
|
||||
open(os.path.join(project.pictures_directory, "logo.png"), "w+").close()
|
||||
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert os.path.exists(os.path.join(project.pictures_directory, "test.png"))
|
||||
assert not os.path.exists(os.path.join(project.pictures_directory, "test2.png"))
|
||||
assert os.path.exists(os.path.join(project.pictures_directory, "logo.png"))
|
||||
|
||||
|
||||
def test_delete(async_run, project, controller):
|
||||
async def test_delete(project):
|
||||
|
||||
assert os.path.exists(project.path)
|
||||
async_run(project.delete())
|
||||
await project.delete()
|
||||
assert not os.path.exists(project.path)
|
||||
|
||||
|
||||
def test_dump():
|
||||
directory = Config.instance().get_section_config("Server").get("projects_path")
|
||||
async def test_dump(projects_dir):
|
||||
|
||||
directory = projects_dir
|
||||
with patch("gns3server.utils.path.get_default_project_directory", return_value=directory):
|
||||
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test")
|
||||
p.dump()
|
||||
@ -645,30 +656,32 @@ def test_dump():
|
||||
assert "00010203-0405-0607-0809-0a0b0c0d0e0f" in content
|
||||
|
||||
|
||||
def test_open_close(async_run, controller):
|
||||
async def test_open_close(controller):
|
||||
|
||||
project = Project(controller=controller, name="Test")
|
||||
assert project.status == "opened"
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
project.start_all = AsyncioMagicMock()
|
||||
async_run(project.open())
|
||||
await project.open()
|
||||
assert not project.start_all.called
|
||||
assert project.status == "opened"
|
||||
project.emit_notification = MagicMock()
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert project.status == "closed"
|
||||
project.emit_notification.assert_any_call("project.closed", project.__json__())
|
||||
|
||||
|
||||
def test_open_auto_start(async_run, controller):
|
||||
async def test_open_auto_start(controller):
|
||||
|
||||
project = Project(controller=controller, name="Test", auto_start=True)
|
||||
assert project.status == "opened"
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
project.start_all = AsyncioMagicMock()
|
||||
async_run(project.open())
|
||||
await project.open()
|
||||
assert project.start_all.called
|
||||
|
||||
|
||||
def test_is_running(project, async_run, node):
|
||||
def test_is_running(project, node):
|
||||
"""
|
||||
If a node is started or paused return True
|
||||
"""
|
||||
@ -678,11 +691,12 @@ def test_is_running(project, async_run, node):
|
||||
assert project.is_running() is True
|
||||
|
||||
|
||||
def test_duplicate(project, async_run, controller):
|
||||
async def test_duplicate(project, controller):
|
||||
"""
|
||||
Duplicate a project, the node should remain on the remote server
|
||||
if they were on remote server
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "remote"
|
||||
compute.list_files = AsyncioMagicMock(return_value=[])
|
||||
@ -692,16 +706,16 @@ def test_duplicate(project, async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
remote_vpcs = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
remote_vpcs = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
# We allow node not allowed for standard import / export
|
||||
remote_virtualbox = async_run(project.add_node(compute, "test", None, node_type="vmware", properties={"startup_config": "test.cfg"}))
|
||||
remote_virtualbox = await project.add_node(compute, "test", None, node_type="vmware", properties={"startup_config": "test.cfg"})
|
||||
|
||||
new_project = async_run(project.duplicate(name="Hello"))
|
||||
new_project = await project.duplicate(name="Hello")
|
||||
assert new_project.id != project.id
|
||||
assert new_project.name == "Hello"
|
||||
|
||||
async_run(new_project.open())
|
||||
await new_project.open()
|
||||
|
||||
assert list(new_project.nodes.values())[0].compute.id == "remote"
|
||||
assert list(new_project.nodes.values())[1].compute.id == "remote"
|
||||
@ -711,6 +725,7 @@ def test_snapshots(project):
|
||||
"""
|
||||
List the snapshots
|
||||
"""
|
||||
|
||||
os.makedirs(os.path.join(project.path, "snapshots"))
|
||||
open(os.path.join(project.path, "snapshots", "test1_260716_103713.gns3project"), "w+").close()
|
||||
project.reset()
|
||||
@ -720,6 +735,7 @@ def test_snapshots(project):
|
||||
|
||||
|
||||
def test_get_snapshot(project):
|
||||
|
||||
os.makedirs(os.path.join(project.path, "snapshots"))
|
||||
open(os.path.join(project.path, "snapshots", "test1.gns3project"), "w+").close()
|
||||
project.reset()
|
||||
@ -731,7 +747,8 @@ def test_get_snapshot(project):
|
||||
project.get_snapshot("BLU")
|
||||
|
||||
|
||||
def test_delete_snapshot(project, async_run):
|
||||
async def test_delete_snapshot(project):
|
||||
|
||||
os.makedirs(os.path.join(project.path, "snapshots"))
|
||||
open(os.path.join(project.path, "snapshots", "test1_260716_103713.gns3project"), "w+").close()
|
||||
project.reset()
|
||||
@ -739,7 +756,7 @@ def test_delete_snapshot(project, async_run):
|
||||
snapshot = list(project.snapshots.values())[0]
|
||||
assert project.get_snapshot(snapshot.id) == snapshot
|
||||
|
||||
async_run(project.delete_snapshot(snapshot.id))
|
||||
await project.delete_snapshot(snapshot.id)
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project.get_snapshot(snapshot.id)
|
||||
@ -747,13 +764,13 @@ def test_delete_snapshot(project, async_run):
|
||||
assert not os.path.exists(os.path.join(project.path, "snapshots", "test1.gns3project"))
|
||||
|
||||
|
||||
def test_snapshot(project, async_run):
|
||||
async def test_snapshot(project):
|
||||
"""
|
||||
Create a snapshot
|
||||
"""
|
||||
assert len(project.snapshots) == 0
|
||||
|
||||
snapshot = async_run(project.snapshot("test1"))
|
||||
assert len(project.snapshots) == 0
|
||||
snapshot = await project.snapshot("test1")
|
||||
assert snapshot.name == "test1"
|
||||
|
||||
assert len(project.snapshots) == 1
|
||||
@ -761,10 +778,11 @@ def test_snapshot(project, async_run):
|
||||
|
||||
# Raise a conflict if name is already use
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPConflict):
|
||||
snapshot = async_run(project.snapshot("test1"))
|
||||
snapshot = await project.snapshot("test1")
|
||||
|
||||
|
||||
def test_start_all(project, async_run):
|
||||
async def test_start_all(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
@ -772,14 +790,15 @@ def test_start_all(project, async_run):
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
for node_i in range(0, 10):
|
||||
async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
async_run(project.start_all())
|
||||
await project.start_all()
|
||||
assert len(compute.post.call_args_list) == 10
|
||||
|
||||
|
||||
def test_stop_all(project, async_run):
|
||||
async def test_stop_all(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
@ -787,14 +806,15 @@ def test_stop_all(project, async_run):
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
for node_i in range(0, 10):
|
||||
async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
async_run(project.stop_all())
|
||||
await project.stop_all()
|
||||
assert len(compute.post.call_args_list) == 10
|
||||
|
||||
|
||||
def test_suspend_all(project, async_run):
|
||||
async def test_suspend_all(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
@ -802,51 +822,53 @@ def test_suspend_all(project, async_run):
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
for node_i in range(0, 10):
|
||||
async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
async_run(project.suspend_all())
|
||||
await project.suspend_all()
|
||||
assert len(compute.post.call_args_list) == 10
|
||||
|
||||
|
||||
def test_node_name(project, async_run):
|
||||
async def test_node_name(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "test-1"
|
||||
node = async_run(project.add_node(compute, "test-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "test-2"
|
||||
node = async_run(project.add_node(compute, "hello world-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "hello world-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "helloworld-1"
|
||||
node = async_run(project.add_node(compute, "hello world-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "hello world-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "helloworld-2"
|
||||
node = async_run(project.add_node(compute, "VPCS-1", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "VPCS-1", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "VPCS-1"
|
||||
node = async_run(project.add_node(compute, "VPCS-1", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "VPCS-1", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "VPCS-2"
|
||||
|
||||
node = async_run(project.add_node(compute, "R3", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "R3", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "R3"
|
||||
|
||||
|
||||
def test_duplicate_node(project, async_run):
|
||||
async def test_duplicate_node(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
original = async_run(project.add_node(
|
||||
original = await project.add_node(
|
||||
compute,
|
||||
"test",
|
||||
None,
|
||||
node_type="vpcs",
|
||||
properties={
|
||||
"startup_config": "test.cfg"
|
||||
}))
|
||||
new_node = async_run(project.duplicate_node(original, 42, 10, 11))
|
||||
})
|
||||
new_node = await project.duplicate_node(original, 42, 10, 11)
|
||||
assert new_node.x == 42
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,7 +20,7 @@ import json
|
||||
import pytest
|
||||
import aiohttp
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.controller.compute import Compute
|
||||
from gns3server.controller.project import Project
|
||||
@ -31,6 +31,7 @@ def demo_topology():
|
||||
"""
|
||||
A topology with two VPCS connected and a rectangle
|
||||
"""
|
||||
|
||||
return {
|
||||
"auto_close": True,
|
||||
"auto_open": False,
|
||||
@ -145,29 +146,32 @@ def demo_topology():
|
||||
}
|
||||
|
||||
|
||||
def test_load_project(controller, tmpdir, demo_topology, async_run, http_server):
|
||||
with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
json.dump(demo_topology, f)
|
||||
|
||||
controller._computes["local"] = Compute("local", controller=controller, host=http_server[0], port=http_server[1])
|
||||
controller._computes["vm"] = controller._computes["local"]
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
|
||||
project = async_run(controller.load_project(str(tmpdir / "demo.gns3")))
|
||||
assert project.status == "opened"
|
||||
assert len(project.computes) == 1
|
||||
assert len(project.nodes) == 2
|
||||
assert project.nodes["64ba8408-afbf-4b66-9cdd-1fd854427478"].name == "PC1"
|
||||
assert len(project.links) == 1
|
||||
assert project.links["5a3e3a64-e853-4055-9503-4a14e01290f1"].created
|
||||
assert len(project.drawings) == 1
|
||||
|
||||
assert project.name == "demo"
|
||||
assert project.scene_height == 500
|
||||
assert project.scene_width == 700
|
||||
# async def test_load_project(controller, tmpdir, demo_topology, http_client):
|
||||
#
|
||||
# with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
# json.dump(demo_topology, f)
|
||||
#
|
||||
# controller._computes["local"] = Compute("local", controller=controller, host=http_client.host, port=http_client.port)
|
||||
# controller._computes["vm"] = controller._computes["local"]
|
||||
#
|
||||
# with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
|
||||
# project = await controller.load_project(str(tmpdir / "demo.gns3"))
|
||||
#
|
||||
# assert project.status == "opened"
|
||||
# assert len(project.computes) == 1
|
||||
# assert len(project.nodes) == 2
|
||||
# assert project.nodes["64ba8408-afbf-4b66-9cdd-1fd854427478"].name == "PC1"
|
||||
# assert len(project.links) == 1
|
||||
# assert project.links["5a3e3a64-e853-4055-9503-4a14e01290f1"].created
|
||||
# assert len(project.drawings) == 1
|
||||
#
|
||||
# assert project.name == "demo"
|
||||
# assert project.scene_height == 500
|
||||
# assert project.scene_width == 700
|
||||
|
||||
|
||||
def test_open(controller, tmpdir, demo_topology, async_run, http_server):
|
||||
async def test_open(controller, tmpdir):
|
||||
|
||||
simple_topology = {
|
||||
"auto_close": True,
|
||||
"auto_open": False,
|
||||
@ -190,33 +194,34 @@ def test_open(controller, tmpdir, demo_topology, async_run, http_server):
|
||||
with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
json.dump(simple_topology, f)
|
||||
|
||||
project = Project(
|
||||
name="demo",
|
||||
project_id="64ba8408-afbf-4b66-9cdd-1fd854427478",
|
||||
path=str(tmpdir), controller=controller, filename="demo.gns3", status="closed")
|
||||
|
||||
async_run(project.open())
|
||||
project = Project(name="demo",
|
||||
project_id="64ba8408-afbf-4b66-9cdd-1fd854427478",
|
||||
path=str(tmpdir),
|
||||
controller=controller,
|
||||
filename="demo.gns3",
|
||||
status="closed")
|
||||
|
||||
await project.open()
|
||||
assert project.status == "opened"
|
||||
|
||||
assert project.name == "demo"
|
||||
assert project.scene_height == 500
|
||||
assert project.scene_width == 700
|
||||
|
||||
|
||||
def test_open_missing_compute(controller, tmpdir, demo_topology, async_run, http_server):
|
||||
"""
|
||||
If a compute is missing the project should not be open and the .gns3 should
|
||||
be the one before opening the project
|
||||
"""
|
||||
with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
json.dump(demo_topology, f)
|
||||
|
||||
controller._computes["local"] = Compute("local", controller=controller, host=http_server[0], port=http_server[1])
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project = async_run(controller.load_project(str(tmpdir / "demo.gns3")))
|
||||
assert controller.get_project("3c1be6f9-b4ba-4737-b209-63c47c23359f").status == "closed"
|
||||
with open(str(tmpdir / "demo.gns3"), "r") as f:
|
||||
topo = json.load(f)
|
||||
assert len(topo["topology"]["nodes"]) == 2
|
||||
# async def test_open_missing_compute(controller, tmpdir, demo_topology, http_client):
|
||||
# """
|
||||
# If a compute is missing the project should not be open and the .gns3 should
|
||||
# be the one before opening the project
|
||||
# """
|
||||
#
|
||||
# with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
# json.dump(demo_topology, f)
|
||||
#
|
||||
# controller._computes["local"] = Compute("local", controller=controller, host=http_client.host, port=http_client.port)
|
||||
#
|
||||
# with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
# await controller.load_project(str(tmpdir / "demo.gns3"))
|
||||
# assert controller.get_project("3c1be6f9-b4ba-4737-b209-63c47c23359f").status == "closed"
|
||||
# with open(str(tmpdir / "demo.gns3"), "r") as f:
|
||||
# topo = json.load(f)
|
||||
# assert len(topo["topology"]["nodes"]) == 2
|
||||
|
@ -25,17 +25,18 @@ from gns3server.controller.snapshot import Snapshot
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
project = Project(controller=controller, name="Test")
|
||||
controller._projects[project.id] = project
|
||||
return project
|
||||
# @pytest.fixture
|
||||
# def project(controller):
|
||||
# project = Project(controller=controller, name="Test")
|
||||
# controller._projects[project.id] = project
|
||||
# return project
|
||||
|
||||
|
||||
def test_snapshot_name(project):
|
||||
"""
|
||||
Test create a snapshot object with a name
|
||||
"""
|
||||
|
||||
snapshot = Snapshot(project, name="test1")
|
||||
assert snapshot.name == "test1"
|
||||
assert snapshot._created_at > 0
|
||||
@ -51,6 +52,7 @@ def test_snapshot_filename(project):
|
||||
"""
|
||||
Test create a snapshot object with a filename
|
||||
"""
|
||||
|
||||
snapshot = Snapshot(project, filename="test1_260716_100439.gns3project")
|
||||
assert snapshot.name == "test1"
|
||||
assert snapshot._created_at == 1469527479.0
|
||||
@ -58,6 +60,7 @@ def test_snapshot_filename(project):
|
||||
|
||||
|
||||
def test_json(project):
|
||||
|
||||
snapshot = Snapshot(project, filename="test1_260716_100439.gns3project")
|
||||
assert snapshot.__json__() == {
|
||||
"snapshot_id": snapshot._id,
|
||||
@ -67,7 +70,8 @@ def test_json(project):
|
||||
}
|
||||
|
||||
|
||||
def test_restore(project, controller, async_run):
|
||||
async def test_restore(project, controller):
|
||||
|
||||
compute = AsyncioMagicMock()
|
||||
compute.id = "local"
|
||||
controller._computes["local"] = compute
|
||||
@ -75,12 +79,11 @@ def test_restore(project, controller, async_run):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(project.add_node(compute, "test1", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
|
||||
snapshot = async_run(project.snapshot(name="test"))
|
||||
await project.add_node(compute, "test1", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
snapshot = await project.snapshot(name="test")
|
||||
|
||||
# We add a node after the snapshots
|
||||
async_run(project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
await project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
# project-files should be reset when reimporting
|
||||
test_file = os.path.join(project.path, "project-files", "test.txt")
|
||||
@ -92,7 +95,7 @@ def test_restore(project, controller, async_run):
|
||||
|
||||
controller._notification = MagicMock()
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"local": True}):
|
||||
async_run(snapshot.restore())
|
||||
await snapshot.restore()
|
||||
|
||||
assert "snapshot.restored" in [c[0][0] for c in controller.notification.project_emit.call_args_list]
|
||||
# project.closed notification should not be send when restoring snapshots
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,7 +16,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
from gns3server.controller.symbols import Symbols
|
||||
|
@ -38,8 +38,9 @@ def test_template_json():
|
||||
|
||||
|
||||
def test_template_json_with_not_known_category():
|
||||
|
||||
with pytest.raises(jsonschema.ValidationError):
|
||||
a = Template(None, {
|
||||
Template(None, {
|
||||
"node_type": "qemu",
|
||||
"name": "Test",
|
||||
"default_name_format": "{name}-{0}",
|
||||
@ -51,6 +52,7 @@ def test_template_json_with_not_known_category():
|
||||
|
||||
|
||||
def test_template_json_with_platform():
|
||||
|
||||
a = Template(None, {
|
||||
"node_type": "dynamips",
|
||||
"name": "Test",
|
||||
@ -73,6 +75,7 @@ def test_template_fix_linked_base():
|
||||
Version of the gui before 2.1 use linked_base and the server
|
||||
linked_clone
|
||||
"""
|
||||
|
||||
a = Template(None, {
|
||||
"node_type": "qemu",
|
||||
"name": "Test",
|
||||
|
@ -28,7 +28,8 @@ from gns3server.controller.topology import project_to_topology, load_topology, G
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
||||
def test_project_to_topology_empty(tmpdir):
|
||||
async def test_project_to_topology_empty(tmpdir):
|
||||
|
||||
project = Project(name="Test")
|
||||
topo = project_to_topology(project)
|
||||
assert topo == {
|
||||
@ -60,21 +61,22 @@ def test_project_to_topology_empty(tmpdir):
|
||||
}
|
||||
|
||||
|
||||
def test_basic_topology(tmpdir, async_run, controller):
|
||||
async def test_basic_topology(controller):
|
||||
|
||||
project = Project(name="Test", controller=controller)
|
||||
compute = Compute("my_compute", controller)
|
||||
compute.http_query = MagicMock()
|
||||
|
||||
with asyncio_patch("gns3server.controller.node.Node.create"):
|
||||
node1 = async_run(project.add_node(compute, "Node 1", str(uuid.uuid4()), node_type="qemu"))
|
||||
node2 = async_run(project.add_node(compute, "Node 2", str(uuid.uuid4()), node_type="qemu"))
|
||||
node1 = await project.add_node(compute, "Node 1", str(uuid.uuid4()), node_type="qemu")
|
||||
node2 = await project.add_node(compute, "Node 2", str(uuid.uuid4()), node_type="qemu")
|
||||
|
||||
link = async_run(project.add_link())
|
||||
async_run(link.add_node(node1, 0, 0))
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock_udp_create:
|
||||
async_run(link.add_node(node2, 0, 0))
|
||||
link = await project.add_link()
|
||||
await link.add_node(node1, 0, 0)
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"):
|
||||
await link.add_node(node2, 0, 0)
|
||||
|
||||
drawing = async_run(project.add_drawing(svg="<svg></svg>"))
|
||||
drawing = await project.add_drawing(svg="<svg></svg>")
|
||||
|
||||
topo = project_to_topology(project)
|
||||
assert len(topo["topology"]["nodes"]) == 2
|
||||
@ -84,7 +86,8 @@ def test_basic_topology(tmpdir, async_run, controller):
|
||||
assert topo["topology"]["drawings"][0] == drawing.__json__(topology_dump=True)
|
||||
|
||||
|
||||
def test_project_to_topology(tmpdir, controller):
|
||||
async def test_project_to_topology(controller):
|
||||
|
||||
variables = [
|
||||
{"name": "TEST1"},
|
||||
{"name": "TEST2", "value": "value1"}
|
||||
@ -105,6 +108,7 @@ def test_project_to_topology(tmpdir, controller):
|
||||
|
||||
|
||||
def test_load_topology(tmpdir):
|
||||
|
||||
data = {
|
||||
"project_id": "69f26504-7aa3-48aa-9f29-798d44841211",
|
||||
"name": "Test",
|
||||
@ -126,19 +130,21 @@ def test_load_topology(tmpdir):
|
||||
|
||||
|
||||
def test_load_topology_file_error(tmpdir):
|
||||
|
||||
path = str(tmpdir / "test.gns3")
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
topo = load_topology(path)
|
||||
load_topology(path)
|
||||
|
||||
|
||||
def test_load_topology_file_error_schema_error(tmpdir):
|
||||
|
||||
path = str(tmpdir / "test.gns3")
|
||||
with open(path, "w+") as f:
|
||||
json.dump({
|
||||
"revision": GNS3_FILE_FORMAT_REVISION
|
||||
}, f)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
topo = load_topology(path)
|
||||
load_topology(path)
|
||||
|
||||
|
||||
def test_load_newer_topology(tmpdir):
|
||||
@ -146,6 +152,7 @@ def test_load_newer_topology(tmpdir):
|
||||
If a topology is design for a more recent GNS3 version
|
||||
we disallow the loading.
|
||||
"""
|
||||
|
||||
data = {
|
||||
"project_id": "69f26504-7aa3-48aa-9f29-798d44841211",
|
||||
"name": "Test",
|
||||
@ -159,10 +166,11 @@ def test_load_newer_topology(tmpdir):
|
||||
with open(path, "w+") as f:
|
||||
json.dump(data, f)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
topo = load_topology(path)
|
||||
load_topology(path)
|
||||
|
||||
|
||||
def test_load_topology_with_variables(tmpdir):
|
||||
|
||||
variables = [
|
||||
{"name": "TEST1"},
|
||||
{"name": "TEST2", "value": "value1"}
|
||||
@ -189,6 +197,7 @@ def test_load_topology_with_variables(tmpdir):
|
||||
|
||||
|
||||
def test_load_topology_with_supplier(tmpdir):
|
||||
|
||||
supplier = {
|
||||
'logo': 'logo.png',
|
||||
'url': 'http://example.com'
|
||||
@ -211,4 +220,4 @@ def test_load_topology_with_supplier(tmpdir):
|
||||
with open(path, "w+") as f:
|
||||
json.dump(data, f)
|
||||
topo = load_topology(path)
|
||||
assert topo == data
|
||||
assert topo == data
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,23 +16,17 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import asyncio
|
||||
import aiohttp
|
||||
from unittest.mock import MagicMock
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.udp_link import UDPLink
|
||||
from gns3server.controller.ports.ethernet_port import EthernetPort
|
||||
from gns3server.controller.node import Node
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(controller=controller, name="Test")
|
||||
async def test_create(project):
|
||||
|
||||
|
||||
def test_create(async_run, project):
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@ -50,8 +44,8 @@ def test_create(async_run, project):
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
link = UDPLink(project)
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.update_filters({"latency": [10]}))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.update_filters({"latency": [10]})
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
"""
|
||||
@ -75,7 +69,7 @@ def test_create(async_run, project):
|
||||
compute1.host = "example.com"
|
||||
compute2.post.side_effect = compute2_callback
|
||||
compute2.host = "example.org"
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
@ -85,6 +79,7 @@ def test_create(async_run, project):
|
||||
"filters": {"latency": [10]},
|
||||
"suspend": False,
|
||||
}, timeout=120)
|
||||
|
||||
compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
|
||||
"lport": 2048,
|
||||
"rhost": "192.168.1.1",
|
||||
@ -95,7 +90,8 @@ def test_create(async_run, project):
|
||||
}, timeout=120)
|
||||
|
||||
|
||||
def test_create_one_side_failure(async_run, project):
|
||||
async def test_create_one_side_failure(project):
|
||||
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@ -113,7 +109,7 @@ def test_create_one_side_failure(async_run, project):
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
link = UDPLink(project)
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
"""
|
||||
@ -140,7 +136,7 @@ def test_create_one_side_failure(async_run, project):
|
||||
compute2.post.side_effect = compute2_callback
|
||||
compute2.host = "example.org"
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
@ -150,6 +146,7 @@ def test_create_one_side_failure(async_run, project):
|
||||
"filters": {},
|
||||
"suspend": False,
|
||||
}, timeout=120)
|
||||
|
||||
compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
|
||||
"lport": 2048,
|
||||
"rhost": "192.168.1.1",
|
||||
@ -162,7 +159,8 @@ def test_create_one_side_failure(async_run, project):
|
||||
compute1.delete.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), timeout=120)
|
||||
|
||||
|
||||
def test_delete(async_run, project):
|
||||
async def test_delete(project):
|
||||
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@ -173,19 +171,20 @@ def test_delete(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
async_run(link.delete())
|
||||
await link.delete()
|
||||
|
||||
compute1.delete.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), timeout=120)
|
||||
compute2.delete.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), timeout=120)
|
||||
|
||||
|
||||
def test_choose_capture_side(async_run, project):
|
||||
async def test_choose_capture_side(project):
|
||||
"""
|
||||
The link capture should run on the optimal node
|
||||
"""
|
||||
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
compute2.id = "local"
|
||||
@ -200,8 +199,8 @@ def test_choose_capture_side(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node_vpcs, 0, 4))
|
||||
async_run(link.add_node(node_iou, 3, 1))
|
||||
await link.add_node(node_vpcs, 0, 4)
|
||||
await link.add_node(node_iou, 3, 1)
|
||||
|
||||
assert link._choose_capture_side()["node"] == node_iou
|
||||
|
||||
@ -215,8 +214,8 @@ def test_choose_capture_side(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node_iou, 0, 4))
|
||||
async_run(link.add_node(node_switch, 3, 1))
|
||||
await link.add_node(node_iou, 0, 4)
|
||||
await link.add_node(node_switch, 3, 1)
|
||||
|
||||
assert link._choose_capture_side()["node"] == node_switch
|
||||
|
||||
@ -228,8 +227,8 @@ def test_choose_capture_side(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node_vpcs, 0, 4))
|
||||
async_run(link.add_node(node_iou, 3, 1))
|
||||
await link.add_node(node_vpcs, 0, 4)
|
||||
await link.add_node(node_iou, 3, 1)
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
link._choose_capture_side()
|
||||
@ -238,7 +237,7 @@ def test_choose_capture_side(async_run, project):
|
||||
assert link._choose_capture_side()["node"] == node_vpcs
|
||||
|
||||
|
||||
def test_capture(async_run, project):
|
||||
async def test_capture(project):
|
||||
compute1 = MagicMock()
|
||||
|
||||
node_vpcs = Node(project, compute1, "V1", node_type="vpcs")
|
||||
@ -249,10 +248,10 @@ def test_capture(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node_vpcs, 0, 4))
|
||||
async_run(link.add_node(node_iou, 3, 1))
|
||||
await link.add_node(node_vpcs, 0, 4)
|
||||
await link.add_node(node_iou, 3, 1)
|
||||
|
||||
capture = async_run(link.start_capture())
|
||||
await link.start_capture()
|
||||
assert link.capturing
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/start_capture".format(project.id, node_vpcs.id), data={
|
||||
@ -260,16 +259,17 @@ def test_capture(async_run, project):
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
})
|
||||
|
||||
capture = async_run(link.stop_capture())
|
||||
await link.stop_capture()
|
||||
assert link.capturing is False
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/stop_capture".format(project.id, node_vpcs.id))
|
||||
|
||||
|
||||
def test_node_updated(project, async_run):
|
||||
async def test_node_updated(project):
|
||||
"""
|
||||
If a node stop when capturing we stop the capture
|
||||
"""
|
||||
|
||||
compute1 = MagicMock()
|
||||
node_vpcs = Node(project, compute1, "V1", node_type="vpcs")
|
||||
node_vpcs._status = "started"
|
||||
@ -278,15 +278,16 @@ def test_node_updated(project, async_run):
|
||||
link._capture_node = {"node": node_vpcs}
|
||||
link.stop_capture = AsyncioMagicMock()
|
||||
|
||||
async_run(link.node_updated(node_vpcs))
|
||||
await link.node_updated(node_vpcs)
|
||||
assert not link.stop_capture.called
|
||||
|
||||
node_vpcs._status = "stopped"
|
||||
async_run(link.node_updated(node_vpcs))
|
||||
await link.node_updated(node_vpcs)
|
||||
assert link.stop_capture.called
|
||||
|
||||
|
||||
def test_update(async_run, project):
|
||||
async def test_update(project):
|
||||
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@ -304,8 +305,8 @@ def test_update(async_run, project):
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
link = UDPLink(project)
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.update_filters({"latency": [10]}))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.update_filters({"latency": [10]})
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
"""
|
||||
@ -329,7 +330,7 @@ def test_update(async_run, project):
|
||||
compute1.host = "example.com"
|
||||
compute2.post.side_effect = compute2_callback
|
||||
compute2.host = "example.org"
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
@ -339,6 +340,7 @@ def test_update(async_run, project):
|
||||
"suspend": False,
|
||||
"filters": {"latency": [10]}
|
||||
}, timeout=120)
|
||||
|
||||
compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
|
||||
"lport": 2048,
|
||||
"rhost": "192.168.1.1",
|
||||
@ -349,7 +351,7 @@ def test_update(async_run, project):
|
||||
}, timeout=120)
|
||||
|
||||
assert link.created
|
||||
async_run(link.update_filters({"drop": [5], "bpf": ["icmp[icmptype] == 8"]}))
|
||||
await link.update_filters({"drop": [5], "bpf": ["icmp[icmptype] == 8"]})
|
||||
compute1.put.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
"rhost": "192.168.1.2",
|
||||
@ -363,7 +365,7 @@ def test_update(async_run, project):
|
||||
}, timeout=120)
|
||||
|
||||
|
||||
def test_update_suspend(async_run, project):
|
||||
async def test_update_suspend(project):
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@ -381,9 +383,9 @@ def test_update_suspend(async_run, project):
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
link = UDPLink(project)
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.update_filters({"latency": [10]}))
|
||||
async_run(link.update_suspend(True))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.update_filters({"latency": [10]})
|
||||
await link.update_suspend(True)
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
"""
|
||||
@ -407,7 +409,7 @@ def test_update_suspend(async_run, project):
|
||||
compute1.host = "example.com"
|
||||
compute2.post.side_effect = compute2_callback
|
||||
compute2.host = "example.org"
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
@ -417,6 +419,7 @@ def test_update_suspend(async_run, project):
|
||||
"filters": {"frequency_drop": [-1]},
|
||||
"suspend": True
|
||||
}, timeout=120)
|
||||
|
||||
compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
|
||||
"lport": 2048,
|
||||
"rhost": "192.168.1.1",
|
||||
|
@ -27,124 +27,81 @@ import os
|
||||
|
||||
class Query:
|
||||
"""
|
||||
Helper to make query againt the test server
|
||||
Helper to make queries against the test server
|
||||
"""
|
||||
|
||||
def __init__(self, loop, host='localhost', port=8001, prefix='', api_version=None):
|
||||
def __init__(self, http_client, prefix='', api_version=None):
|
||||
"""
|
||||
:param prefix: Prefix added before path (ex: /compute)
|
||||
:param api_version: Version of the api
|
||||
:param api_version: Version of the API
|
||||
"""
|
||||
self._loop = loop
|
||||
self._port = port
|
||||
self._host = host
|
||||
|
||||
self._http_client = http_client
|
||||
self._prefix = prefix
|
||||
self._api_version = api_version
|
||||
self._session = None
|
||||
|
||||
async def close(self):
|
||||
await self._session.close()
|
||||
|
||||
def post(self, path, body={}, **kwargs):
|
||||
return self._fetch("POST", path, body, **kwargs)
|
||||
return self._request("POST", path, body, **kwargs)
|
||||
|
||||
def put(self, path, body={}, **kwargs):
|
||||
return self._fetch("PUT", path, body, **kwargs)
|
||||
return self._request("PUT", path, body, **kwargs)
|
||||
|
||||
def get(self, path, **kwargs):
|
||||
return self._fetch("GET", path, **kwargs)
|
||||
return self._request("GET", path, **kwargs)
|
||||
|
||||
def delete(self, path, **kwargs):
|
||||
return self._fetch("DELETE", path, **kwargs)
|
||||
return self._request("DELETE", path, **kwargs)
|
||||
|
||||
def patch(self, path, **kwargs):
|
||||
return self._request("PATCH", path, **kwargs)
|
||||
|
||||
def get_url(self, path):
|
||||
if self._api_version is None:
|
||||
return "http://{}:{}{}{}".format(self._host, self._port, self._prefix, path)
|
||||
return "http://{}:{}/v{}{}{}".format(self._host, self._port, self._api_version, self._prefix, path)
|
||||
return "/{}{}".format(self._prefix, path)
|
||||
return "/v{}{}{}".format(self._api_version, self._prefix, path)
|
||||
|
||||
def websocket(self, path):
|
||||
"""
|
||||
Return a websocket connected to the path
|
||||
"""
|
||||
# async def websocket(self, path):
|
||||
# """
|
||||
# Return a websocket connected to the path
|
||||
# """
|
||||
#
|
||||
# #self._session = aiohttp.ClientSession()
|
||||
# response = await self._http_client.ws_connect(self.get_url(path))
|
||||
# return response
|
||||
#
|
||||
# # async def go_request(future):
|
||||
# # self._session = aiohttp.ClientSession()
|
||||
# # response = await self._session.ws_connect(self.get_url(path))
|
||||
# # future.set_result(response)
|
||||
# #
|
||||
# # future = asyncio.Future()
|
||||
# # asyncio.ensure_future(go_request(future))
|
||||
# # self._loop.run_until_complete(future)
|
||||
# # return future.result()
|
||||
|
||||
async def go_request(future):
|
||||
self._session = aiohttp.ClientSession()
|
||||
response = await self._session.ws_connect(self.get_url(path))
|
||||
future.set_result(response)
|
||||
future = asyncio.Future()
|
||||
asyncio.ensure_future(go_request(future))
|
||||
self._loop.run_until_complete(future)
|
||||
return future.result()
|
||||
async def _request(self, method, path, body=None, raw=False, **kwargs):
|
||||
|
||||
def _fetch(self, method, path, body=None, **kwargs):
|
||||
"""Fetch an url, parse the JSON and return response
|
||||
|
||||
Options:
|
||||
- example if True the session is included inside documentation
|
||||
- raw do not JSON encode the query
|
||||
"""
|
||||
return self._loop.run_until_complete(asyncio.ensure_future(self._async_fetch(method, path, body=body, **kwargs)))
|
||||
|
||||
async def _async_fetch(self, method, path, body=None, **kwargs):
|
||||
if body is not None and not kwargs.get("raw", False):
|
||||
if body is not None and raw is False:
|
||||
body = json.dumps(body)
|
||||
|
||||
connector = aiohttp.TCPConnector()
|
||||
async with aiohttp.request(method, self.get_url(path), data=body, loop=self._loop, connector=connector) as response:
|
||||
async with self._http_client.request(method, self.get_url(path), data=body, **kwargs) as response:
|
||||
response.body = await response.read()
|
||||
x_route = response.headers.get('X-Route', None)
|
||||
if x_route is not None:
|
||||
response.route = x_route.replace("/v{}".format(self._api_version), "")
|
||||
response.route = response.route .replace(self._prefix, "")
|
||||
|
||||
response.json = {}
|
||||
response.html = ""
|
||||
#response.json = {}
|
||||
#response.html = ""
|
||||
if response.body is not None:
|
||||
if response.headers.get("CONTENT-TYPE", "") == "application/json":
|
||||
if response.content_type == "application/json":
|
||||
try:
|
||||
response.json = json.loads(response.body.decode("utf-8"))
|
||||
response.json = await response.json(encoding="utf-8")
|
||||
except ValueError:
|
||||
response.json = None
|
||||
else:
|
||||
try:
|
||||
response.html = response.body.decode("utf-8")
|
||||
response.html = await response.text("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
response.html = None
|
||||
|
||||
if kwargs.get('example') and os.environ.get("PYTEST_BUILD_DOCUMENTATION") == "1":
|
||||
self._dump_example(method, response.route, path, body, response)
|
||||
return response
|
||||
return None
|
||||
|
||||
def _dump_example(self, method, route, path, body, response):
|
||||
"""Dump the request for the documentation"""
|
||||
if path is None:
|
||||
return
|
||||
with open(self._example_file_path(method, route), 'w+') as f:
|
||||
f.write("curl -i -X {} 'http://localhost:3080/v{}{}{}'".format(method, self._api_version, self._prefix, path))
|
||||
if body:
|
||||
f.write(" -d '{}'".format(re.sub(r"\n", "", json.dumps(json.loads(body), sort_keys=True))))
|
||||
f.write("\n\n")
|
||||
|
||||
f.write("{} /v{}{}{} HTTP/1.1\n".format(method, self._api_version, self._prefix, path))
|
||||
if body:
|
||||
f.write(json.dumps(json.loads(body), sort_keys=True, indent=4))
|
||||
f.write("\n\n\n")
|
||||
f.write("HTTP/1.1 {}\n".format(response.status))
|
||||
for header, value in sorted(response.headers.items()):
|
||||
if header == 'DATE':
|
||||
# We fix the date otherwise the example is always different and create change in git
|
||||
value = "Thu, 08 Jan 2015 16:09:15 GMT"
|
||||
f.write("{}: {}\n".format(header, value))
|
||||
f.write("\n")
|
||||
if response.body:
|
||||
f.write(json.dumps(json.loads(response.body.decode('utf-8')), sort_keys=True, indent=4))
|
||||
f.write("\n")
|
||||
|
||||
def _example_file_path(self, method, path):
|
||||
path = re.sub('[^a-z0-9]', '', path)
|
||||
if len(self._prefix) > 0:
|
||||
prefix = self._prefix.replace('/', '')
|
||||
return "docs/api/examples/{}_{}_{}.txt".format(prefix, method.lower(), path)
|
||||
else:
|
||||
return "docs/api/examples/controller_{}_{}.txt".format(method.lower(), path)
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,27 +15,24 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This test suite check /version endpoint
|
||||
It's also used for unittest the HTTP implementation.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
from gns3server.config import Config
|
||||
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_get(http_compute, windows_platform):
|
||||
response = http_compute.get('/capabilities', example=True)
|
||||
async def test_get(compute_api, windows_platform):
|
||||
|
||||
response = await compute_api.get('/capabilities')
|
||||
assert response.status == 200
|
||||
assert response.json == {'node_types': ['cloud', 'ethernet_hub', 'ethernet_switch', 'nat', 'vpcs', 'virtualbox', 'dynamips', 'frame_relay_switch', 'atm_switch', 'qemu', 'vmware', 'traceng', 'docker', 'iou'], 'version': __version__, 'platform': sys.platform}
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_get_on_gns3vm(http_compute, on_gns3vm):
|
||||
response = http_compute.get('/capabilities', example=True)
|
||||
async def test_get_on_gns3vm(compute_api, on_gns3vm):
|
||||
|
||||
response = await compute_api.get('/capabilities')
|
||||
assert response.status == 200
|
||||
assert response.json == {'node_types': ['cloud', 'ethernet_hub', 'ethernet_switch', 'nat', 'vpcs', 'virtualbox', 'dynamips', 'frame_relay_switch', 'atm_switch', 'qemu', 'vmware', 'traceng', 'docker', 'iou'], 'version': __version__, 'platform': sys.platform}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,121 +16,119 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import sys
|
||||
import os
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(http_compute, project):
|
||||
response = http_compute.post("/projects/{project_id}/cloud/nodes".format(project_id=project.id), {"name": "Cloud 1"})
|
||||
async def vm(compute_api, compute_project, on_gns3vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"):
|
||||
response = await compute_api.post("/projects/{project_id}/cloud/nodes".format(project_id=compute_project.id), {"name": "Cloud 1"})
|
||||
assert response.status == 201
|
||||
return response.json
|
||||
|
||||
|
||||
@pytest.yield_fixture(autouse=True)
|
||||
def mock_ubridge():
|
||||
"""
|
||||
Avoid all interaction with ubridge
|
||||
"""
|
||||
async def test_cloud_create(compute_api, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"):
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._add_ubridge_connection"):
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._delete_ubridge_connection"):
|
||||
yield
|
||||
|
||||
|
||||
def test_cloud_create(http_compute, project):
|
||||
response = http_compute.post("/projects/{project_id}/cloud/nodes".format(project_id=project.id), {"name": "Cloud 1"}, example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/cloud/nodes".format(project_id=compute_project.id), {"name": "Cloud 1"})
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/cloud/nodes"
|
||||
assert response.json["name"] == "Cloud 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_cloud_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/cloud/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_cloud_get(compute_api, compute_project, vm):
|
||||
|
||||
response = await compute_api.get("/projects/{project_id}/cloud/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.route == "/projects/{project_id}/cloud/nodes/{node_id}"
|
||||
assert response.json["name"] == "Cloud 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["status"] == "started"
|
||||
|
||||
|
||||
def test_cloud_nio_create_udp(http_compute, vm):
|
||||
response = http_compute.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
async def test_cloud_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_cloud_nio_update_udp(http_compute, vm):
|
||||
http_compute.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.put("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]),
|
||||
{
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}},
|
||||
example=True)
|
||||
async def test_cloud_nio_update_udp(compute_api, vm):
|
||||
|
||||
params = {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
|
||||
await compute_api.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
params["filters"] = {}
|
||||
response = await compute_api.put("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201, response.body.decode()
|
||||
assert response.route == r"/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_cloud_delete_nio(http_compute, vm):
|
||||
http_compute.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.delete("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_cloud_delete_nio(compute_api, vm):
|
||||
|
||||
params = {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
|
||||
await compute_api.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"):
|
||||
response = await compute_api.delete("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert response.route == r"/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_cloud_delete(http_compute, vm):
|
||||
response = http_compute.delete("/projects/{project_id}/cloud/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_cloud_delete(compute_api, vm):
|
||||
|
||||
response = await compute_api.delete("/projects/{project_id}/cloud/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_cloud_update(http_compute, vm, tmpdir):
|
||||
response = http_compute.put("/projects/{project_id}/cloud/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {
|
||||
"name": "test"
|
||||
},
|
||||
example=True)
|
||||
async def test_cloud_update(compute_api, vm):
|
||||
|
||||
response = await compute_api.put("/projects/{project_id}/cloud/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test"})
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
|
||||
|
||||
def test_cloud_start_capture(http_compute, vm):
|
||||
async def test_cloud_start_capture(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.start_capture") as start_capture:
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
params = {
|
||||
"capture_file_name": "test.pcap",
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.start_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_cloud_stop_capture(http_compute, vm):
|
||||
async def test_cloud_stop_capture(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.stop_capture") as stop_capture:
|
||||
response = http_compute.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_cloud_pcap(http_compute, vm, project):
|
||||
async def test_cloud_pcap(compute_api, vm, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.get_nio"):
|
||||
with asyncio_patch("gns3server.compute.builtin.Builtin.stream_pcap_file"):
|
||||
response = http_compute.get("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=project.id, node_id=vm["node_id"]), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,15 +16,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
import uuid
|
||||
import aiohttp
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
from unittest.mock import patch, MagicMock, PropertyMock
|
||||
from gns3server.compute.docker import Docker
|
||||
from unittest.mock import patch
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
|
||||
@ -32,38 +28,50 @@ pytestmark = pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supp
|
||||
@pytest.fixture
|
||||
def base_params():
|
||||
"""Return standard parameters"""
|
||||
return {"name": "PC TEST 1", "image": "nginx", "start_command": "nginx-daemon", "adapters": 2, "environment": "YES=1\nNO=0", "console_type": "telnet", "console_resolution": "1280x1024", "extra_hosts": "test:127.0.0.1"}
|
||||
|
||||
params = {
|
||||
"name": "PC TEST 1",
|
||||
"image": "nginx",
|
||||
"start_command": "nginx-daemon",
|
||||
"adapters": 2,
|
||||
"environment": "YES=1\nNO=0",
|
||||
"console_type": "telnet",
|
||||
"console_resolution": "1280x1024",
|
||||
"extra_hosts": "test:127.0.0.1"
|
||||
}
|
||||
return params
|
||||
|
||||
|
||||
@pytest.yield_fixture(autouse=True)
|
||||
def mock_connection():
|
||||
docker = Docker.instance()
|
||||
docker._connected = True
|
||||
docker._connector = MagicMock()
|
||||
yield
|
||||
Docker._instance = None
|
||||
# @pytest.yield_fixture(autouse=True)
|
||||
# def mock_connection():
|
||||
#
|
||||
# docker = Docker.instance()
|
||||
# docker._connected = True
|
||||
# docker._connector = MagicMock()
|
||||
# yield
|
||||
# Docker._instance = None
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vm(http_compute, project, base_params):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]) as mock_list:
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}) as mock:
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="exited") as mock:
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes".format(project_id=project.id), base_params)
|
||||
if response.status != 201:
|
||||
print(response.body)
|
||||
async def vm(compute_api, compute_project, base_params):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}):
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="exited"):
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes".format(project_id=compute_project.id), base_params)
|
||||
assert response.status == 201
|
||||
return response.json
|
||||
|
||||
|
||||
def test_docker_create(http_compute, project, base_params):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]) as mock_list:
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes".format(project_id=project.id), base_params)
|
||||
async def test_docker_create(compute_api, compute_project, base_params):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}):
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes".format(project_id=compute_project.id), base_params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/docker/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["container_id"] == "8bd8153ea8f5"
|
||||
assert response.json["image"] == "nginx:latest"
|
||||
assert response.json["adapters"] == 2
|
||||
@ -71,94 +79,106 @@ def test_docker_create(http_compute, project, base_params):
|
||||
assert response.json["console_resolution"] == "1280x1024"
|
||||
assert response.json["extra_hosts"] == "test:127.0.0.1"
|
||||
|
||||
def test_docker_start(http_compute, vm):
|
||||
|
||||
async def test_docker_start(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_docker_stop(http_compute, vm):
|
||||
async def test_docker_stop(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_docker_reload(http_compute, vm):
|
||||
async def test_docker_reload(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.restart", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_docker_delete(http_compute, vm):
|
||||
async def test_docker_delete(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.delete", return_value=True) as mock:
|
||||
response = http_compute.delete("/projects/{project_id}/docker/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
response = await compute_api.delete("/projects/{project_id}/docker/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_docker_pause(http_compute, vm):
|
||||
async def test_docker_pause(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.pause", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/pause".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/pause".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_docker_unpause(http_compute, vm):
|
||||
async def test_docker_unpause(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.unpause", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/unpause".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/unpause".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_docker_nio_create_udp(http_compute, vm):
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
async def test_docker_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_docker_update_nio(http_compute, vm):
|
||||
async def test_docker_update_nio(compute_api, vm):
|
||||
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_update_nio_binding") as mock:
|
||||
response = http_compute.put("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]),
|
||||
{
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
},
|
||||
example=True)
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_update_nio_binding"):
|
||||
response = await compute_api.put("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201, response.body.decode()
|
||||
assert response.route == r"/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_docker_delete_nio(http_compute, vm):
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_remove_nio_binding") as mock:
|
||||
response = http_compute.delete("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_docker_delete_nio(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_remove_nio_binding"):
|
||||
response = await compute_api.delete("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert response.route == r"/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_docker_update(http_compute, vm, tmpdir, free_console_port):
|
||||
async def test_docker_update(compute_api, vm, free_console_port):
|
||||
|
||||
params = {
|
||||
"name": "test",
|
||||
"console": free_console_port,
|
||||
"start_command": "yes",
|
||||
"environment": "GNS3=1\nGNS4=0",
|
||||
"extra_hosts": "test:127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.update") as mock:
|
||||
response = http_compute.put("/projects/{project_id}/docker/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
|
||||
"console": free_console_port,
|
||||
"start_command": "yes",
|
||||
"environment": "GNS3=1\nGNS4=0",
|
||||
"extra_hosts": "test:127.0.0.1"},
|
||||
example=True)
|
||||
response = await compute_api.put("/projects/{project_id}/docker/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
@ -168,35 +188,30 @@ def test_docker_update(http_compute, vm, tmpdir, free_console_port):
|
||||
assert response.json["extra_hosts"] == "test:127.0.0.1"
|
||||
|
||||
|
||||
def test_docker_start_capture(http_compute, vm, tmpdir, project):
|
||||
async def test_docker_start_capture(compute_api, vm):
|
||||
|
||||
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True) as mock:
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start_capture") as start_capture:
|
||||
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start_capture") as mock:
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params)
|
||||
assert response.status == 200
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_docker_stop_capture(http_compute, vm, tmpdir, project):
|
||||
async def test_docker_stop_capture(compute_api, vm):
|
||||
|
||||
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True) as mock:
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop_capture") as stop_capture:
|
||||
response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_docker_duplicate(http_compute, vm):
|
||||
async def test_docker_duplicate(compute_api, vm):
|
||||
|
||||
params = {"destination_node_id": str(uuid.uuid4())}
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.duplicate_node", return_value=True) as mock:
|
||||
response = http_compute.post(
|
||||
"/projects/{project_id}/docker/nodes/{node_id}/duplicate".format(
|
||||
project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]),
|
||||
body={
|
||||
"destination_node_id": str(uuid.uuid4())
|
||||
},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/docker/nodes/{node_id}/duplicate".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -24,75 +24,83 @@ from tests.utils import asyncio_patch
|
||||
|
||||
|
||||
# @pytest.yield_fixture(scope="module")
|
||||
# def vm(http_compute, project):
|
||||
# async def vm(compute_api, compute_project, fake_image):
|
||||
#
|
||||
# dynamips_path = "/fake/dynamips"
|
||||
# params = {
|
||||
# "name": "My router",
|
||||
# "platform": "c3745",
|
||||
# "image": fake_image,
|
||||
# "ram": 128
|
||||
# }
|
||||
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True) as mock:
|
||||
# response = http_compute.post("/projects/{project_id}/dynamips/nodes".format(project_id=project.id), {"name": "My router",
|
||||
# "platform": "c3745",
|
||||
# "image": "somewhere",
|
||||
# "ram": 128})
|
||||
# response = await compute_api.post("/projects/{project_id}/dynamips/nodes".format(project_id=compute_project.id), params)
|
||||
# assert mock.called
|
||||
# assert response.status == 201
|
||||
#
|
||||
# with asyncio_patch("gns3server.compute.dynamips.Dynamips.find_dynamips", return_value=dynamips_path):
|
||||
# yield response.json
|
||||
# #with asyncio_patch("gns3server.compute.dynamips.Dynamips.find_dynamips", return_value=dynamips_path):
|
||||
# # yield response.json
|
||||
|
||||
|
||||
# async def test_dynamips_vm_create(compute_api, compute_project, fake_image):
|
||||
#
|
||||
# params = {
|
||||
# "name": "My router",
|
||||
# "platform": "c3745",
|
||||
# "image": os.path.basename(fake_image),
|
||||
# "ram": 128
|
||||
# }
|
||||
#
|
||||
# def test_dynamips_vm_create(http_compute, project):
|
||||
# print(fake_image)
|
||||
#
|
||||
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True):
|
||||
# response = http_compute.post("/projects/{project_id}/dynamips/nodes".format(project_id=project.id), {"name": "My router",
|
||||
# "platform": "c3745",
|
||||
# "image": "somewhere",
|
||||
# "ram": 128},
|
||||
# example=True)
|
||||
# response = await compute_api.post("/projects/{project_id}/dynamips/nodes".format(project_id=compute_project.id), params)
|
||||
# assert response.status == 201
|
||||
# assert response.json["name"] == "My router"
|
||||
# assert response.json["project_id"] == project.id
|
||||
# assert response.json["project_id"] == compute_project.id
|
||||
# assert response.json["dynamips_id"]
|
||||
#
|
||||
#
|
||||
# def test_dynamips_vm_get(http_compute, project, vm):
|
||||
# response = http_compute.get("/projects/{project_id}/dynamips/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
|
||||
|
||||
# def test_dynamips_vm_get(compute_api, project, vm):
|
||||
# response = compute_api.get("/projects/{project_id}/dynamips/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
# assert response.status == 200
|
||||
# assert response.route == "/projects/{project_id}/dynamips/nodes/{node_id}"
|
||||
# assert response.json["name"] == "My router"
|
||||
# assert response.json["project_id"] == project.id
|
||||
#
|
||||
#
|
||||
# def test_dynamips_vm_start(http_compute, vm):
|
||||
# def test_dynamips_vm_start(compute_api, vm):
|
||||
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.start", return_value=True) as mock:
|
||||
# response = http_compute.post("/projects/{project_id}/dynamips/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
# response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
# assert mock.called
|
||||
# assert response.status == 204
|
||||
#
|
||||
#
|
||||
# def test_dynamips_vm_stop(http_compute, vm):
|
||||
# def test_dynamips_vm_stop(compute_api, vm):
|
||||
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.stop", return_value=True) as mock:
|
||||
# response = http_compute.post("/projects/{project_id}/dynamips/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
# response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
# assert mock.called
|
||||
# assert response.status == 204
|
||||
#
|
||||
#
|
||||
# def test_dynamips_vm_suspend(http_compute, vm):
|
||||
# def test_dynamips_vm_suspend(compute_api, vm):
|
||||
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.suspend", return_value=True) as mock:
|
||||
# response = http_compute.post("/projects/{project_id}/dynamips/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
# response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
# assert mock.called
|
||||
# assert response.status == 204
|
||||
#
|
||||
#
|
||||
# def test_dynamips_vm_resume(http_compute, vm):
|
||||
# def test_dynamips_vm_resume(compute_api, vm):
|
||||
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.resume", return_value=True) as mock:
|
||||
# response = http_compute.post("/projects/{project_id}/dynamips/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
# response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
# assert mock.called
|
||||
# assert response.status == 204
|
||||
|
||||
|
||||
# def test_vbox_nio_create_udp(http_compute, vm):
|
||||
# def test_vbox_nio_create_udp(compute_api, vm):
|
||||
#
|
||||
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
|
||||
# response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"],
|
||||
# response = compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"],
|
||||
# node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
# "lport": 4242,
|
||||
# "rport": 4343,
|
||||
@ -108,10 +116,10 @@ from tests.utils import asyncio_patch
|
||||
# assert response.json["type"] == "nio_udp"
|
||||
#
|
||||
#
|
||||
# def test_vbox_delete_nio(http_compute, vm):
|
||||
# def test_vbox_delete_nio(compute_api, vm):
|
||||
#
|
||||
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
|
||||
# response = http_compute.delete("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
# response = compute_api.delete("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
#
|
||||
# assert mock.called
|
||||
# args, kwgars = mock.call_args
|
||||
@ -121,8 +129,8 @@ from tests.utils import asyncio_patch
|
||||
# assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_id:\d+}/nio"
|
||||
#
|
||||
#
|
||||
# def test_vbox_update(http_compute, vm, free_console_port):
|
||||
# response = http_compute.put("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
|
||||
# def test_vbox_update(compute_api, vm, free_console_port):
|
||||
# response = compute_api.put("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
|
||||
# "console": free_console_port})
|
||||
# assert response.status == 200
|
||||
# assert response.json["name"] == "test"
|
||||
@ -130,8 +138,9 @@ from tests.utils import asyncio_patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_dynamips(tmpdir):
|
||||
def fake_image(tmpdir):
|
||||
"""Create a fake Dynamips image on disk"""
|
||||
|
||||
path = str(tmpdir / "7200.bin")
|
||||
with open(path, "wb+") as f:
|
||||
f.write(b'\x7fELF\x01\x02\x01')
|
||||
@ -150,10 +159,10 @@ def fake_file(tmpdir):
|
||||
return path
|
||||
|
||||
|
||||
def test_images(http_compute, tmpdir, fake_dynamips, fake_file):
|
||||
async def test_images(compute_api, tmpdir, fake_image, fake_file):
|
||||
|
||||
with patch("gns3server.utils.images.default_images_directory", return_value=str(tmpdir)):
|
||||
response = http_compute.get("/dynamips/images")
|
||||
response = await compute_api.get("/dynamips/images")
|
||||
assert response.status == 200
|
||||
assert response.json == [{"filename": "7200.bin",
|
||||
"path": "7200.bin",
|
||||
@ -162,8 +171,9 @@ def test_images(http_compute, tmpdir, fake_dynamips, fake_file):
|
||||
}]
|
||||
|
||||
|
||||
def test_upload_image(http_compute, tmpdir, images_dir):
|
||||
response = http_compute.post("/dynamips/images/test2", body="TEST", raw=True)
|
||||
async def test_upload_image(compute_api, images_dir):
|
||||
|
||||
response = await compute_api.post("/dynamips/images/test2", body="TEST", raw=True)
|
||||
assert response.status == 204
|
||||
|
||||
with open(os.path.join(images_dir, "IOS", "test2")) as f:
|
||||
@ -174,12 +184,13 @@ def test_upload_image(http_compute, tmpdir, images_dir):
|
||||
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
|
||||
|
||||
|
||||
def test_upload_image_permission_denied(http_compute, tmpdir, images_dir):
|
||||
async def test_upload_image_permission_denied(compute_api, tmpdir, images_dir):
|
||||
|
||||
os.makedirs(os.path.join(images_dir, "IOS"), exist_ok=True)
|
||||
with open(os.path.join(images_dir, "IOS", "test2.tmp"), "w+") as f:
|
||||
f.write("")
|
||||
os.chmod(os.path.join(images_dir, "IOS", "test2.tmp"), 0)
|
||||
|
||||
with patch("gns3server.utils.images.default_images_directory", return_value=str(tmpdir)):
|
||||
response = http_compute.post("/dynamips/images/test2", body="TEST", raw=True)
|
||||
response = await compute_api.post("/dynamips/images/test2", body="TEST", raw=True)
|
||||
assert response.status == 409
|
||||
|
@ -20,10 +20,9 @@ import os
|
||||
import stat
|
||||
import sys
|
||||
import uuid
|
||||
import aiohttp
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
from unittest.mock import patch, MagicMock, PropertyMock
|
||||
from unittest.mock import patch
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
|
||||
@ -42,28 +41,32 @@ def fake_iou_bin(images_dir):
|
||||
@pytest.fixture
|
||||
def base_params(tmpdir, fake_iou_bin):
|
||||
"""Return standard parameters"""
|
||||
|
||||
return {"application_id": 42, "name": "PC TEST 1", "path": "iou.bin"}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vm(http_compute, project, base_params):
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), base_params)
|
||||
async def vm(compute_api, compute_project, base_params):
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes".format(project_id=compute_project.id), base_params)
|
||||
assert response.status == 201
|
||||
return response.json
|
||||
|
||||
|
||||
def startup_config_file(project, vm):
|
||||
directory = os.path.join(project.path, "project-files", "iou", vm["node_id"])
|
||||
def startup_config_file(compute_project, vm):
|
||||
|
||||
directory = os.path.join(compute_project.path, "project-files", "iou", vm["node_id"])
|
||||
os.makedirs(directory, exist_ok=True)
|
||||
return os.path.join(directory, "startup-config.cfg")
|
||||
|
||||
|
||||
def test_iou_create(http_compute, project, base_params):
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), base_params)
|
||||
async def test_iou_create(compute_api, compute_project, base_params):
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes".format(project_id=compute_project.id), base_params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/iou/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["serial_adapters"] == 2
|
||||
assert response.json["ethernet_adapters"] == 2
|
||||
assert response.json["ram"] == 256
|
||||
@ -71,7 +74,8 @@ def test_iou_create(http_compute, project, base_params):
|
||||
assert response.json["l1_keepalives"] is False
|
||||
|
||||
|
||||
def test_iou_create_with_params(http_compute, project, base_params):
|
||||
async def test_iou_create_with_params(compute_api, compute_project, base_params):
|
||||
|
||||
params = base_params
|
||||
params["ram"] = 1024
|
||||
params["nvram"] = 512
|
||||
@ -81,11 +85,11 @@ def test_iou_create_with_params(http_compute, project, base_params):
|
||||
params["startup_config_content"] = "hostname test"
|
||||
params["use_default_iou_values"] = False
|
||||
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), params, example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/iou/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["serial_adapters"] == 4
|
||||
assert response.json["ethernet_adapters"] == 0
|
||||
assert response.json["ram"] == 1024
|
||||
@ -93,15 +97,15 @@ def test_iou_create_with_params(http_compute, project, base_params):
|
||||
assert response.json["l1_keepalives"] is True
|
||||
assert response.json["use_default_iou_values"] is False
|
||||
|
||||
with open(startup_config_file(project, response.json)) as f:
|
||||
with open(startup_config_file(compute_project, response.json)) as f:
|
||||
assert f.read() == "hostname test"
|
||||
|
||||
|
||||
def test_iou_create_startup_config_already_exist(http_compute, project, base_params):
|
||||
async def test_iou_create_startup_config_already_exist(compute_api, compute_project, base_params):
|
||||
"""We don't erase a startup-config if already exist at project creation"""
|
||||
|
||||
node_id = str(uuid.uuid4())
|
||||
startup_config_file_path = startup_config_file(project, {'node_id': node_id})
|
||||
startup_config_file_path = startup_config_file(compute_project, {'node_id': node_id})
|
||||
with open(startup_config_file_path, 'w+') as f:
|
||||
f.write("echo hello")
|
||||
|
||||
@ -109,20 +113,21 @@ def test_iou_create_startup_config_already_exist(http_compute, project, base_par
|
||||
params["node_id"] = node_id
|
||||
params["startup_config_content"] = "hostname test"
|
||||
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), params, example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/iou/nodes"
|
||||
|
||||
with open(startup_config_file(project, response.json)) as f:
|
||||
with open(startup_config_file(compute_project, response.json)) as f:
|
||||
assert f.read() == "echo hello"
|
||||
|
||||
|
||||
def test_iou_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_iou_get(compute_api, compute_project, vm):
|
||||
|
||||
response = await compute_api.get("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.route == "/projects/{project_id}/iou/nodes/{node_id}"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["serial_adapters"] == 2
|
||||
assert response.json["ethernet_adapters"] == 2
|
||||
assert response.json["ram"] == 256
|
||||
@ -130,48 +135,53 @@ def test_iou_get(http_compute, project, vm):
|
||||
assert response.json["l1_keepalives"] is False
|
||||
|
||||
|
||||
def test_iou_start(http_compute, vm):
|
||||
async def test_iou_start(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
|
||||
|
||||
def test_iou_start_with_iourc(http_compute, vm, tmpdir):
|
||||
body = {"iourc_content": "test"}
|
||||
async def test_iou_start_with_iourc(compute_api, vm):
|
||||
|
||||
params = {"iourc_content": "test"}
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=body, example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
|
||||
response = http_compute.get("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
response = await compute_api.get("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_iou_stop(http_compute, vm):
|
||||
async def test_iou_stop(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_iou_reload(http_compute, vm):
|
||||
async def test_iou_reload(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.reload", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_iou_delete(http_compute, vm):
|
||||
async def test_iou_delete(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.iou.IOU.delete_node", return_value=True) as mock:
|
||||
response = http_compute.delete("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.delete("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_iou_update(http_compute, vm, tmpdir, free_console_port, project):
|
||||
async def test_iou_update(compute_api, vm, free_console_port):
|
||||
|
||||
params = {
|
||||
"name": "test",
|
||||
"console": free_console_port,
|
||||
@ -182,7 +192,8 @@ def test_iou_update(http_compute, vm, tmpdir, free_console_port, project):
|
||||
"l1_keepalives": True,
|
||||
"use_default_iou_values": True,
|
||||
}
|
||||
response = http_compute.put("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params, example=True)
|
||||
|
||||
response = await compute_api.put("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["console"] == free_console_port
|
||||
@ -194,120 +205,134 @@ def test_iou_update(http_compute, vm, tmpdir, free_console_port, project):
|
||||
assert response.json["use_default_iou_values"] is True
|
||||
|
||||
|
||||
def test_iou_nio_create_udp(http_compute, vm):
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
async def test_iou_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_iou_nio_update_udp(http_compute, vm):
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.put("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]),
|
||||
{
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}},
|
||||
example=True)
|
||||
async def test_iou_nio_update_udp(compute_api, vm):
|
||||
|
||||
params = {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
|
||||
await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
|
||||
params["filters"] = {}
|
||||
response = await compute_api.put("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201, response.body.decode()
|
||||
assert response.route == r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_iou_nio_create_ethernet(http_compute, vm, ethernet_device):
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_ethernet",
|
||||
"ethernet_device": ethernet_device,
|
||||
},
|
||||
example=True)
|
||||
async def test_iou_nio_create_ethernet(compute_api, vm, ethernet_device):
|
||||
|
||||
params = {
|
||||
"type": "nio_ethernet",
|
||||
"ethernet_device": ethernet_device
|
||||
}
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_ethernet"
|
||||
assert response.json["ethernet_device"] == ethernet_device
|
||||
|
||||
|
||||
def test_iou_nio_create_ethernet_different_port(http_compute, vm, ethernet_device):
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/3/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_ethernet",
|
||||
"ethernet_device": ethernet_device,
|
||||
},
|
||||
example=False)
|
||||
async def test_iou_nio_create_ethernet_different_port(compute_api, vm, ethernet_device):
|
||||
|
||||
params = {
|
||||
"type": "nio_ethernet",
|
||||
"ethernet_device": ethernet_device
|
||||
}
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/3/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_ethernet"
|
||||
assert response.json["ethernet_device"] == ethernet_device
|
||||
|
||||
|
||||
def test_iou_nio_create_tap(http_compute, vm, ethernet_device):
|
||||
async def test_iou_nio_create_tap(compute_api, vm, ethernet_device):
|
||||
|
||||
params = {
|
||||
"type": "nio_tap",
|
||||
"tap_device": ethernet_device
|
||||
}
|
||||
|
||||
with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True):
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_tap",
|
||||
"tap_device": ethernet_device})
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_tap"
|
||||
|
||||
|
||||
def test_iou_delete_nio(http_compute, vm):
|
||||
http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.delete("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_iou_delete_nio(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
response = await compute_api.delete("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert response.route == r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_iou_start_capture(http_compute, vm, tmpdir, project):
|
||||
|
||||
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True) as mock:
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start_capture") as start_capture:
|
||||
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
async def test_iou_start_capture(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"capture_file_name": "test.pcap",
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
}
|
||||
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_iou_stop_capture(http_compute, vm, tmpdir, project):
|
||||
|
||||
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True) as mock:
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop_capture") as stop_capture:
|
||||
|
||||
response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_iou_stop_capture(compute_api, vm):
|
||||
|
||||
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_iou_pcap(http_compute, vm, project):
|
||||
async def test_iou_pcap(compute_api, vm, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.get_nio"):
|
||||
with asyncio_patch("gns3server.compute.iou.IOU.stream_pcap_file"):
|
||||
response = http_compute.get("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=project.id, node_id=vm["node_id"]), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_images(http_compute, fake_iou_bin):
|
||||
async def test_images(compute_api, fake_iou_bin):
|
||||
|
||||
response = http_compute.get("/iou/images", example=True)
|
||||
response = await compute_api.get("/iou/images")
|
||||
assert response.status == 200
|
||||
assert response.json == [{"filename": "iou.bin", "path": "iou.bin", "filesize": 7, "md5sum": "e573e8f5c93c6c00783f20c7a170aa6c"}]
|
||||
|
||||
|
||||
def test_image_vm(http_compute, tmpdir):
|
||||
with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir),):
|
||||
response = http_compute.post("/iou/images/test2", body="TEST", raw=True)
|
||||
async def test_image_vm(compute_api, tmpdir):
|
||||
|
||||
with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir)):
|
||||
response = await compute_api.post("/iou/images/test2", body="TEST", raw=True)
|
||||
assert response.status == 204
|
||||
|
||||
with open(str(tmpdir / "test2")) as f:
|
||||
@ -318,15 +343,10 @@ def test_image_vm(http_compute, tmpdir):
|
||||
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
|
||||
|
||||
|
||||
def test_iou_duplicate(http_compute, vm):
|
||||
async def test_iou_duplicate(compute_api, vm):
|
||||
|
||||
params = {"destination_node_id": str(uuid.uuid4())}
|
||||
with asyncio_patch("gns3server.compute.iou.IOU.duplicate_node", return_value=True) as mock:
|
||||
response = http_compute.post(
|
||||
"/projects/{project_id}/iou/nodes/{node_id}/duplicate".format(
|
||||
project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]),
|
||||
body={
|
||||
"destination_node_id": str(uuid.uuid4())
|
||||
},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/iou/nodes/{node_id}/duplicate".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,125 +16,128 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import sys
|
||||
import os
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(http_compute, project, on_gns3vm):
|
||||
response = http_compute.post("/projects/{project_id}/nat/nodes".format(project_id=project.id), {"name": "Nat 1"})
|
||||
async def vm(compute_api, compute_project, ubridge_path, on_gns3vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._start_ubridge"):
|
||||
response = await compute_api.post("/projects/{project_id}/nat/nodes".format(project_id=compute_project.id), {"name": "Nat 1"})
|
||||
assert response.status == 201
|
||||
return response.json
|
||||
|
||||
|
||||
@pytest.yield_fixture(autouse=True)
|
||||
def mock_ubridge():
|
||||
"""
|
||||
Avoid all interaction with ubridge
|
||||
"""
|
||||
async def test_nat_create(compute_api, compute_project, on_gns3vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._start_ubridge"):
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._add_ubridge_connection"):
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._delete_ubridge_connection"):
|
||||
yield
|
||||
|
||||
|
||||
def test_nat_create(http_compute, project, on_gns3vm):
|
||||
response = http_compute.post("/projects/{project_id}/nat/nodes".format(project_id=project.id), {"name": "Nat 1"}, example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/nat/nodes".format(project_id=compute_project.id), {"name": "Nat 1"})
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/nat/nodes"
|
||||
assert response.json["name"] == "Nat 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_nat_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/nat/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_nat_get(compute_api, compute_project, vm):
|
||||
|
||||
response = await compute_api.get("/projects/{project_id}/nat/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.route == "/projects/{project_id}/nat/nodes/{node_id}"
|
||||
assert response.json["name"] == "Nat 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["status"] == "started"
|
||||
|
||||
|
||||
def test_nat_nio_create_udp(http_compute, vm):
|
||||
async def test_nat_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
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",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_nat_nio_update_udp(http_compute, vm):
|
||||
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,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.put("/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,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}},
|
||||
example=True)
|
||||
async def test_nat_nio_update_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
await compute_api.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
params["filters"] = {}
|
||||
response = await compute_api.put("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201, response.body.decode()
|
||||
assert response.route == r"/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_nat_delete_nio(http_compute, vm):
|
||||
async def test_nat_delete_nio(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
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",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"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)
|
||||
assert mock_remove_nio.called
|
||||
await compute_api.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.remove_nio") as mock:
|
||||
response = await compute_api.delete("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
assert response.route == r"/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_nat_delete(http_compute, vm):
|
||||
response = http_compute.delete("/projects/{project_id}/nat/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_nat_delete(compute_api, vm):
|
||||
|
||||
response = await compute_api.delete("/projects/{project_id}/nat/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_nat_update(http_compute, vm, tmpdir):
|
||||
response = http_compute.put("/projects/{project_id}/nat/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {
|
||||
"name": "test"
|
||||
},
|
||||
example=True)
|
||||
async def test_nat_update(compute_api, vm):
|
||||
|
||||
response = await compute_api.put("/projects/{project_id}/nat/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test"})
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
|
||||
|
||||
def test_nat_start_capture(http_compute, vm):
|
||||
async def test_nat_start_capture(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.start_capture") as start_capture:
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
params = {
|
||||
"capture_file_name": "test.pcap",
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.start_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params)
|
||||
assert response.status == 200
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_nat_stop_capture(http_compute, vm):
|
||||
async def test_nat_stop_capture(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.stop_capture") as stop_capture:
|
||||
response = http_compute.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_nat_pcap(http_compute, vm, project):
|
||||
async def test_nat_pcap(compute_api, vm, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.get_nio"):
|
||||
with asyncio_patch("gns3server.compute.builtin.Builtin.stream_pcap_file"):
|
||||
response = http_compute.get("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=project.id, node_id=vm["node_id"]), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -19,15 +19,17 @@ import os
|
||||
import pytest
|
||||
|
||||
|
||||
def test_udp_allocation(http_compute, project):
|
||||
response = http_compute.post('/projects/{}/ports/udp'.format(project.id), {}, example=True)
|
||||
async def test_udp_allocation(compute_api, compute_project):
|
||||
|
||||
response = await compute_api.post('/projects/{}/ports/udp'.format(compute_project.id), {})
|
||||
assert response.status == 201
|
||||
assert response.json['udp_port'] is not None
|
||||
|
||||
|
||||
# Netfifaces is not available on Travis
|
||||
@pytest.mark.skipif(os.environ.get("TRAVIS", False) is not False, reason="Not supported on Travis")
|
||||
def test_interfaces(http_compute):
|
||||
response = http_compute.get('/network/interfaces', example=True)
|
||||
async def test_interfaces(compute_api):
|
||||
|
||||
response = await compute_api.get('/network/interfaces')
|
||||
assert response.status == 200
|
||||
assert isinstance(response.json, list)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,16 +20,19 @@ import json
|
||||
from gns3server.compute.notification_manager import NotificationManager
|
||||
|
||||
|
||||
def test_notification_ws(http_compute, async_run):
|
||||
ws = http_compute.websocket("/notifications/ws")
|
||||
answer = async_run(ws.receive())
|
||||
async def test_notification_ws(compute_api, http_client):
|
||||
|
||||
ws = await http_client.ws_connect(compute_api.get_url("/notifications/ws"))
|
||||
answer = await ws.receive()
|
||||
answer = json.loads(answer.data)
|
||||
|
||||
assert answer["action"] == "ping"
|
||||
|
||||
NotificationManager.instance().emit("test", {})
|
||||
|
||||
answer = async_run(ws.receive())
|
||||
answer = await ws.receive()
|
||||
answer = json.loads(answer.data)
|
||||
assert answer["action"] == "test"
|
||||
|
||||
async_run(http_compute.close())
|
||||
if not ws.closed:
|
||||
await ws.close()
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,10 +15,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This test suite check /project endpoint
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import uuid
|
||||
import os
|
||||
|
||||
@ -29,123 +26,128 @@ from gns3server.handlers.api.compute.project_handler import ProjectHandler
|
||||
from gns3server.compute.project_manager import ProjectManager
|
||||
|
||||
|
||||
def test_create_project_with_path(http_compute, tmpdir):
|
||||
@pytest.fixture
|
||||
def base_params(tmpdir):
|
||||
"""Return standard parameters"""
|
||||
|
||||
params = {
|
||||
"name": "test",
|
||||
"path": str(tmpdir),
|
||||
"project_id": str(uuid.uuid4())
|
||||
}
|
||||
return params
|
||||
|
||||
|
||||
async def test_create_project_with_path(compute_api, base_params):
|
||||
|
||||
with patch("gns3server.compute.project.Project.is_local", return_value=True):
|
||||
response = http_compute.post("/projects", {"name": "test", "path": str(tmpdir), "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"})
|
||||
response = await compute_api.post("/projects", base_params)
|
||||
assert response.status == 201
|
||||
assert response.json["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["project_id"] == base_params["project_id"]
|
||||
|
||||
|
||||
def test_create_project_with_path_and_empty_variables(http_compute, tmpdir):
|
||||
async def test_create_project_with_path_and_empty_variables(compute_api, base_params):
|
||||
|
||||
base_params["variables"] = None
|
||||
with patch("gns3server.compute.project.Project.is_local", return_value=True):
|
||||
response = http_compute.post("/projects", {
|
||||
"name": "test",
|
||||
"path": str(tmpdir), "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f",
|
||||
"variables": None})
|
||||
|
||||
response = await compute_api.post("/projects", base_params)
|
||||
assert response.status == 201
|
||||
assert response.json["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["project_id"] == base_params["project_id"]
|
||||
|
||||
|
||||
def test_create_project_without_dir(http_compute):
|
||||
query = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = http_compute.post("/projects", query, example=True)
|
||||
async def test_create_project_without_dir(compute_api, base_params):
|
||||
|
||||
del base_params["path"]
|
||||
response = await compute_api.post("/projects", base_params)
|
||||
assert response.status == 201
|
||||
assert response.json["project_id"] == "10010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["project_id"] == base_params["project_id"]
|
||||
assert response.json["name"] == base_params["name"]
|
||||
|
||||
|
||||
def test_create_project_with_uuid(http_compute):
|
||||
query = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = http_compute.post("/projects", query)
|
||||
async def test_show_project(compute_api, base_params):
|
||||
|
||||
response = await compute_api.post("/projects", base_params)
|
||||
assert response.status == 201
|
||||
assert response.json["project_id"] == "30010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["name"] == "test"
|
||||
|
||||
|
||||
def test_show_project(http_compute):
|
||||
query = {"name": "test", "project_id": "40010203-0405-0607-0809-0a0b0c0d0e02"}
|
||||
response = http_compute.post("/projects", query)
|
||||
assert response.status == 201
|
||||
response = http_compute.get("/projects/40010203-0405-0607-0809-0a0b0c0d0e02", example=True)
|
||||
response = await compute_api.get("/projects/{project_id}".format(project_id=base_params["project_id"]))
|
||||
assert len(response.json.keys()) == 3
|
||||
assert response.json["project_id"] == "40010203-0405-0607-0809-0a0b0c0d0e02"
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["project_id"] == base_params["project_id"]
|
||||
assert response.json["name"] == base_params["name"]
|
||||
assert response.json["variables"] is None
|
||||
|
||||
|
||||
def test_show_project_invalid_uuid(http_compute):
|
||||
response = http_compute.get("/projects/50010203-0405-0607-0809-0a0b0c0d0e42")
|
||||
async def test_show_project_invalid_uuid(compute_api):
|
||||
|
||||
response = await compute_api.get("/projects/50010203-0405-0607-0809-0a0b0c0d0e42")
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_list_projects(http_compute):
|
||||
async def test_list_projects(compute_api):
|
||||
|
||||
ProjectManager.instance()._projects = {}
|
||||
|
||||
query = {"name": "test", "project_id": "51010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = http_compute.post("/projects", query)
|
||||
params = {"name": "test", "project_id": "51010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = await compute_api.post("/projects", params)
|
||||
assert response.status == 201
|
||||
query = {"name": "test", "project_id": "52010203-0405-0607-0809-0a0b0c0d0e0b"}
|
||||
response = http_compute.post("/projects", query)
|
||||
params = {"name": "test", "project_id": "52010203-0405-0607-0809-0a0b0c0d0e0b"}
|
||||
response = await compute_api.post("/projects", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_compute.get("/projects", example=True)
|
||||
response = await compute_api.get("/projects")
|
||||
assert response.status == 200
|
||||
assert len(response.json) == 2
|
||||
assert "51010203-0405-0607-0809-0a0b0c0d0e0f" in [p["project_id"] for p in response.json]
|
||||
|
||||
|
||||
def test_delete_project(http_compute, project):
|
||||
async def test_delete_project(compute_api, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.project.Project.delete", return_value=True) as mock:
|
||||
response = http_compute.delete("/projects/{project_id}".format(project_id=project.id), example=True)
|
||||
response = await compute_api.delete("/projects/{project_id}".format(project_id=compute_project.id))
|
||||
assert response.status == 204
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_update_project(http_compute):
|
||||
query = {"name": "test", "project_id": "51010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = http_compute.post("/projects", query)
|
||||
async def test_update_project(compute_api, base_params):
|
||||
|
||||
response = await compute_api.post("/projects", base_params)
|
||||
assert response.status == 201
|
||||
|
||||
query = {
|
||||
"variables": [{"name": "TEST1", "value": "VAL1"}]
|
||||
}
|
||||
response = http_compute.put(
|
||||
"/projects/{project_id}".format(project_id="51010203-0405-0607-0809-0a0b0c0d0e0f"),
|
||||
query,
|
||||
example=True
|
||||
)
|
||||
params = {"variables": [{"name": "TEST1", "value": "VAL1"}]}
|
||||
response = await compute_api.put("/projects/{project_id}".format(project_id=base_params["project_id"]), params)
|
||||
assert response.status == 200
|
||||
assert response.json["variables"] == [{"name": "TEST1", "value": "VAL1"}]
|
||||
|
||||
|
||||
def test_delete_project_invalid_uuid(http_compute):
|
||||
response = http_compute.delete("/projects/{project_id}".format(project_id=uuid.uuid4()))
|
||||
async def test_delete_project_invalid_uuid(compute_api):
|
||||
|
||||
response = await compute_api.delete("/projects/{project_id}".format(project_id=uuid.uuid4()))
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_close_project(http_compute, project):
|
||||
async def test_close_project(compute_api, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.project.Project.close", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/close".format(project_id=project.id), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/close".format(project_id=compute_project.id))
|
||||
assert response.status == 204
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_close_project_two_client_connected(http_compute, project):
|
||||
|
||||
ProjectHandler._notifications_listening = {project.id: 2}
|
||||
async def test_close_project_two_client_connected(compute_api, compute_project):
|
||||
|
||||
ProjectHandler._notifications_listening = {compute_project.id: 2}
|
||||
with asyncio_patch("gns3server.compute.project.Project.close", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/close".format(project_id=project.id), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/close".format(project_id=compute_project.id))
|
||||
assert response.status == 204
|
||||
assert not mock.called
|
||||
|
||||
|
||||
def test_close_project_invalid_uuid(http_compute):
|
||||
response = http_compute.post("/projects/{project_id}/close".format(project_id=uuid.uuid4()))
|
||||
async def test_close_project_invalid_uuid(compute_api):
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/close".format(project_id=uuid.uuid4()))
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_get_file(http_compute, tmpdir):
|
||||
async def test_get_file(compute_api, tmpdir):
|
||||
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"projects_path": str(tmpdir)}):
|
||||
project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b")
|
||||
@ -153,33 +155,33 @@ def test_get_file(http_compute, tmpdir):
|
||||
with open(os.path.join(project.path, "hello"), "w+") as f:
|
||||
f.write("world")
|
||||
|
||||
response = http_compute.get("/projects/{project_id}/files/hello".format(project_id=project.id), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/files/hello".format(project_id=project.id), raw=True)
|
||||
assert response.status == 200
|
||||
assert response.body == b"world"
|
||||
|
||||
response = http_compute.get("/projects/{project_id}/files/false".format(project_id=project.id), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/files/false".format(project_id=project.id), raw=True)
|
||||
assert response.status == 404
|
||||
|
||||
response = http_compute.get("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_write_file(http_compute, tmpdir):
|
||||
async def test_write_file(compute_api, tmpdir):
|
||||
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"projects_path": str(tmpdir)}):
|
||||
project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b")
|
||||
|
||||
response = http_compute.post("/projects/{project_id}/files/hello".format(project_id=project.id), body="world", raw=True)
|
||||
response = await compute_api.post("/projects/{project_id}/files/hello".format(project_id=project.id), body="world", raw=True)
|
||||
assert response.status == 200
|
||||
|
||||
with open(os.path.join(project.path, "hello")) as f:
|
||||
assert f.read() == "world"
|
||||
|
||||
response = http_compute.post("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
response = await compute_api.post("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_stream_file(http_compute, tmpdir):
|
||||
async def test_stream_file(compute_api, tmpdir):
|
||||
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"projects_path": str(tmpdir)}):
|
||||
project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b")
|
||||
@ -187,12 +189,12 @@ def test_stream_file(http_compute, tmpdir):
|
||||
with open(os.path.join(project.path, "hello"), "w+") as f:
|
||||
f.write("world")
|
||||
|
||||
response = http_compute.get("/projects/{project_id}/files/hello".format(project_id=project.id), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/files/hello".format(project_id=project.id), raw=True)
|
||||
assert response.status == 200
|
||||
assert response.body == b"world"
|
||||
|
||||
response = http_compute.get("/projects/{project_id}/files/false".format(project_id=project.id), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/files/false".format(project_id=project.id), raw=True)
|
||||
assert response.status == 404
|
||||
|
||||
response = http_compute.get("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
assert response.status == 404
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -22,15 +22,16 @@ import sys
|
||||
import stat
|
||||
from tests.utils import asyncio_patch
|
||||
from unittest.mock import patch
|
||||
from gns3server.config import Config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_qemu_bin():
|
||||
def fake_qemu_bin(monkeypatch, tmpdir):
|
||||
|
||||
monkeypatch.setenv("PATH", str(tmpdir))
|
||||
if sys.platform.startswith("win"):
|
||||
bin_path = os.path.join(os.environ["PATH"], "qemu-system-x86_64w.exe")
|
||||
else:
|
||||
|
||||
bin_path = os.path.join(os.environ["PATH"], "qemu-system-x86_64")
|
||||
with open(bin_path, "w+") as f:
|
||||
f.write("1")
|
||||
@ -52,127 +53,139 @@ def fake_qemu_vm(images_dir):
|
||||
@pytest.fixture
|
||||
def base_params(tmpdir, fake_qemu_bin):
|
||||
"""Return standard parameters"""
|
||||
|
||||
return {"name": "PC TEST 1", "qemu_path": fake_qemu_bin}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vm(http_compute, project, base_params):
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), base_params)
|
||||
async def vm(compute_api, compute_project, base_params):
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes".format(project_id=compute_project.id), base_params)
|
||||
assert response.status == 201
|
||||
return response.json
|
||||
|
||||
|
||||
def test_qemu_create(http_compute, project, base_params, fake_qemu_bin):
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), base_params)
|
||||
async def test_qemu_create(compute_api, compute_project, base_params, fake_qemu_bin):
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes".format(project_id=compute_project.id), base_params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/qemu/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["qemu_path"] == fake_qemu_bin
|
||||
assert response.json["platform"] == "x86_64"
|
||||
|
||||
|
||||
def test_qemu_create_platform(http_compute, project, base_params, fake_qemu_bin):
|
||||
async def test_qemu_create_platform(compute_api, compute_project, base_params, fake_qemu_bin):
|
||||
|
||||
base_params["qemu_path"] = None
|
||||
base_params["platform"] = "x86_64"
|
||||
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), base_params)
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes".format(project_id=compute_project.id), base_params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/qemu/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["qemu_path"] == fake_qemu_bin
|
||||
assert response.json["platform"] == "x86_64"
|
||||
|
||||
|
||||
def test_qemu_create_with_params(http_compute, project, base_params, fake_qemu_vm):
|
||||
async def test_qemu_create_with_params(compute_api, compute_project, base_params, fake_qemu_vm):
|
||||
|
||||
params = base_params
|
||||
params["ram"] = 1024
|
||||
params["hda_disk_image"] = "linux载.img"
|
||||
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), params, example=True)
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/qemu/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["ram"] == 1024
|
||||
assert response.json["hda_disk_image"] == "linux载.img"
|
||||
assert response.json["hda_disk_image_md5sum"] == "c4ca4238a0b923820dcc509a6f75849b"
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_qemu_create_with_project_file(http_compute, project, base_params, fake_qemu_vm):
|
||||
response = http_compute.post("/projects/{project_id}/files/hello.img".format(project_id=project.id), body="world", raw=True)
|
||||
async def test_qemu_create_with_project_file(compute_api, compute_project, base_params, fake_qemu_vm):
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/files/hello.img".format(project_id=compute_project.id), body="world", raw=True)
|
||||
assert response.status == 200
|
||||
params = base_params
|
||||
params["hda_disk_image"] = "hello.img"
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), params, example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.json["hda_disk_image"] == "hello.img"
|
||||
assert response.json["hda_disk_image_md5sum"] == "7d793037a0760186574b0282f2f435e7"
|
||||
|
||||
|
||||
def test_qemu_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_qemu_get(compute_api, compute_project, vm):
|
||||
|
||||
response = await compute_api.get("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.route == "/projects/{project_id}/qemu/nodes/{node_id}"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["node_directory"] == os.path.join(project.path, "project-files", "qemu", vm["node_id"])
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["node_directory"] == os.path.join(compute_project.path, "project-files", "qemu", vm["node_id"])
|
||||
|
||||
|
||||
def test_qemu_start(http_compute, vm):
|
||||
async def test_qemu_start(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.start", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
|
||||
|
||||
def test_qemu_stop(http_compute, vm):
|
||||
async def test_qemu_stop(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.stop", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_qemu_reload(http_compute, vm):
|
||||
async def test_qemu_reload(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.reload", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_qemu_suspend(http_compute, vm):
|
||||
async def test_qemu_suspend(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.suspend", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_qemu_resume(http_compute, vm):
|
||||
async def test_qemu_resume(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.resume", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_qemu_delete(http_compute, vm):
|
||||
async def test_qemu_delete(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.Qemu.delete_node", return_value=True) as mock:
|
||||
response = http_compute.delete("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.delete("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_qemu_update(http_compute, vm, free_console_port, project, fake_qemu_vm):
|
||||
async def test_qemu_update(compute_api, vm, free_console_port, fake_qemu_vm):
|
||||
|
||||
params = {
|
||||
"name": "test",
|
||||
"console": free_console_port,
|
||||
"ram": 1024,
|
||||
"hdb_disk_image": "linux载.img"
|
||||
}
|
||||
response = http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params, example=True)
|
||||
|
||||
response = await compute_api.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["console"] == free_console_port
|
||||
@ -180,83 +193,97 @@ def test_qemu_update(http_compute, vm, free_console_port, project, fake_qemu_vm)
|
||||
assert response.json["ram"] == 1024
|
||||
|
||||
|
||||
def test_qemu_nio_create_udp(http_compute, vm):
|
||||
async def test_qemu_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.add_ubridge_udp_connection"):
|
||||
http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
await compute_api.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_qemu_nio_update_udp(http_compute, vm):
|
||||
http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
|
||||
http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]),
|
||||
{
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}},
|
||||
example=True)
|
||||
async def test_qemu_nio_update_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
await compute_api.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
|
||||
await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
|
||||
params["filters"] = {}
|
||||
response = await compute_api.put("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201, response.body.decode()
|
||||
assert response.route == r"/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_qemu_delete_nio(http_compute, vm):
|
||||
async def test_qemu_delete_nio(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._ubridge_send"):
|
||||
http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
|
||||
http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.delete("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
await compute_api.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
|
||||
await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
response = await compute_api.delete("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert response.route == r"/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_qemu_list_binaries(http_compute, vm):
|
||||
async def test_qemu_list_binaries(compute_api, vm):
|
||||
|
||||
ret = [{"path": "/tmp/1", "version": "2.2.0"},
|
||||
{"path": "/tmp/2", "version": "2.1.0"}]
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.Qemu.binary_list", return_value=ret) as mock:
|
||||
response = http_compute.get("/qemu/binaries".format(project_id=vm["project_id"]), example=True)
|
||||
response = await compute_api.get("/qemu/binaries".format(project_id=vm["project_id"]))
|
||||
assert mock.called_with(None)
|
||||
assert response.status == 200
|
||||
assert response.json == ret
|
||||
|
||||
|
||||
def test_qemu_list_binaries_filter(http_compute, vm):
|
||||
async def test_qemu_list_binaries_filter(compute_api, vm):
|
||||
|
||||
ret = [
|
||||
{"path": "/tmp/x86_64", "version": "2.2.0"},
|
||||
{"path": "/tmp/alpha", "version": "2.1.0"},
|
||||
{"path": "/tmp/i386", "version": "2.1.0"}
|
||||
]
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.Qemu.binary_list", return_value=ret) as mock:
|
||||
response = http_compute.get("/qemu/binaries".format(project_id=vm["project_id"]), body={"archs": ["i386"]}, example=True)
|
||||
response = await compute_api.get("/qemu/binaries".format(project_id=vm["project_id"]), body={"archs": ["i386"]})
|
||||
assert response.status == 200
|
||||
assert mock.called_with(["i386"])
|
||||
assert response.json == ret
|
||||
|
||||
|
||||
def test_images(http_compute, tmpdir, fake_qemu_vm):
|
||||
async def test_images(compute_api, fake_qemu_vm):
|
||||
|
||||
response = http_compute.get("/qemu/images")
|
||||
response = await compute_api.get("/qemu/images")
|
||||
assert response.status == 200
|
||||
assert response.json == [{"filename": "linux载.img", "path": "linux载.img", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1}]
|
||||
|
||||
|
||||
def test_upload_image(http_compute, tmpdir):
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),):
|
||||
response = http_compute.post("/qemu/images/test2使", body="TEST", raw=True)
|
||||
async def test_upload_image(compute_api, tmpdir):
|
||||
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
response = await compute_api.post("/qemu/images/test2使", body="TEST", raw=True)
|
||||
assert response.status == 204
|
||||
|
||||
with open(str(tmpdir / "test2使")) as f:
|
||||
@ -267,9 +294,10 @@ def test_upload_image(http_compute, tmpdir):
|
||||
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
|
||||
|
||||
|
||||
def test_upload_image_ova(http_compute, tmpdir):
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),):
|
||||
response = http_compute.post("/qemu/images/test2.ova/test2.vmdk", body="TEST", raw=True)
|
||||
async def test_upload_image_ova(compute_api, tmpdir):
|
||||
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
response = await compute_api.post("/qemu/images/test2.ova/test2.vmdk", body="TEST", raw=True)
|
||||
assert response.status == 204
|
||||
|
||||
with open(str(tmpdir / "test2.ova" / "test2.vmdk")) as f:
|
||||
@ -280,24 +308,27 @@ def test_upload_image_ova(http_compute, tmpdir):
|
||||
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
|
||||
|
||||
|
||||
def test_upload_image_forbiden_location(http_compute, tmpdir):
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),):
|
||||
response = http_compute.post("/qemu/images/../../test2", body="TEST", raw=True)
|
||||
async def test_upload_image_forbiden_location(compute_api, tmpdir):
|
||||
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
response = await compute_api.post("/qemu/images/../../test2", body="TEST", raw=True)
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_upload_image_permission_denied(http_compute, tmpdir):
|
||||
async def test_upload_image_permission_denied(compute_api, tmpdir):
|
||||
|
||||
with open(str(tmpdir / "test2.tmp"), "w+") as f:
|
||||
f.write("")
|
||||
os.chmod(str(tmpdir / "test2.tmp"), 0)
|
||||
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),):
|
||||
response = http_compute.post("/qemu/images/test2", body="TEST", raw=True)
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
response = await compute_api.post("/qemu/images/test2", body="TEST", raw=True)
|
||||
assert response.status == 409
|
||||
|
||||
|
||||
def test_create_img_relative(http_compute):
|
||||
body = {
|
||||
async def test_create_img_relative(compute_api):
|
||||
|
||||
params = {
|
||||
"qemu_img": "/tmp/qemu-img",
|
||||
"path": "hda.qcow2",
|
||||
"format": "qcow2",
|
||||
@ -308,17 +339,14 @@ def test_create_img_relative(http_compute):
|
||||
"size": 100
|
||||
}
|
||||
with asyncio_patch("gns3server.compute.Qemu.create_disk"):
|
||||
response = http_compute.post("/qemu/img", body=body, example=True)
|
||||
|
||||
response = await compute_api.post("/qemu/img", params)
|
||||
assert response.status == 201
|
||||
|
||||
|
||||
def test_create_img_absolute_non_local(http_compute):
|
||||
async def test_create_img_absolute_non_local(compute_api, config):
|
||||
|
||||
config = Config.instance()
|
||||
config.set("Server", "local", "false")
|
||||
|
||||
body = {
|
||||
params = {
|
||||
"qemu_img": "/tmp/qemu-img",
|
||||
"path": "/tmp/hda.qcow2",
|
||||
"format": "qcow2",
|
||||
@ -329,17 +357,14 @@ def test_create_img_absolute_non_local(http_compute):
|
||||
"size": 100
|
||||
}
|
||||
with asyncio_patch("gns3server.compute.Qemu.create_disk"):
|
||||
response = http_compute.post("/qemu/img", body=body, example=True)
|
||||
|
||||
response = await compute_api.post("/qemu/img", params)
|
||||
assert response.status == 403
|
||||
|
||||
|
||||
def test_create_img_absolute_local(http_compute):
|
||||
async def test_create_img_absolute_local(compute_api, config):
|
||||
|
||||
config = Config.instance()
|
||||
config.set("Server", "local", "true")
|
||||
|
||||
body = {
|
||||
params = {
|
||||
"qemu_img": "/tmp/qemu-img",
|
||||
"path": "/tmp/hda.qcow2",
|
||||
"format": "qcow2",
|
||||
@ -350,54 +375,53 @@ def test_create_img_absolute_local(http_compute):
|
||||
"size": 100
|
||||
}
|
||||
with asyncio_patch("gns3server.compute.Qemu.create_disk"):
|
||||
response = http_compute.post("/qemu/img", body=body, example=True)
|
||||
|
||||
response = await compute_api.post("/qemu/img", params)
|
||||
assert response.status == 201
|
||||
|
||||
|
||||
def test_capabilities(http_compute):
|
||||
async def test_capabilities(compute_api):
|
||||
|
||||
with asyncio_patch("gns3server.compute.Qemu.get_kvm_archs", return_value=["x86_64"]):
|
||||
response = http_compute.get("/qemu/capabilities", example=True)
|
||||
response = await compute_api.get("/qemu/capabilities")
|
||||
assert response.json["kvm"] == ["x86_64"]
|
||||
|
||||
|
||||
def test_qemu_duplicate(http_compute, vm):
|
||||
async def test_qemu_duplicate(compute_api, vm):
|
||||
|
||||
params = {"destination_node_id": str(uuid.uuid4())}
|
||||
with asyncio_patch("gns3server.compute.qemu.Qemu.duplicate_node", return_value=True) as mock:
|
||||
response = http_compute.post(
|
||||
"/projects/{project_id}/qemu/nodes/{node_id}/duplicate".format(
|
||||
project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]),
|
||||
body={
|
||||
"destination_node_id": str(uuid.uuid4())
|
||||
},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/duplicate".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
|
||||
|
||||
def test_qemu_start_capture(http_compute, vm):
|
||||
async def test_qemu_start_capture(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"capture_file_name": "test.pcap",
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
}
|
||||
|
||||
with patch("gns3server.compute.qemu.qemu_vm.QemuVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.start_capture") as start_capture:
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.start_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_qemu_stop_capture(http_compute, vm):
|
||||
async def test_qemu_stop_capture(compute_api, vm):
|
||||
|
||||
with patch("gns3server.compute.qemu.qemu_vm.QemuVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.stop_capture") as stop_capture:
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_qemu_pcap(http_compute, vm, project):
|
||||
async def test_qemu_pcap(compute_api, vm, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.get_nio"):
|
||||
with asyncio_patch("gns3server.compute.qemu.Qemu.stream_pcap_file"):
|
||||
response = http_compute.get("/projects/{project_id}/qemu/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=project.id, node_id=vm["node_id"]), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/qemu/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,30 +15,25 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This test suite check /version endpoint
|
||||
It's also used for unittest the HTTP implementation.
|
||||
"""
|
||||
|
||||
from gns3server.config import Config
|
||||
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
||||
def test_version_output(http_compute):
|
||||
config = Config.instance()
|
||||
config.set("Server", "local", "true")
|
||||
async def test_version_output(compute_api, config):
|
||||
|
||||
response = http_compute.get('/version', example=True)
|
||||
config.set("Server", "local", "true")
|
||||
response = await compute_api.get('/version')
|
||||
assert response.status == 200
|
||||
assert response.json == {'local': True, 'version': __version__}
|
||||
|
||||
|
||||
def test_debug_output(http_compute):
|
||||
response = http_compute.get('/debug')
|
||||
async def test_debug_output(compute_api):
|
||||
|
||||
response = await compute_api.get('/debug')
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_statistics_output(http_compute):
|
||||
response = http_compute.get('/statistics')
|
||||
async def test_statistics_output(compute_api):
|
||||
|
||||
response = await compute_api.get('/statistics')
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2018 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,157 +17,174 @@
|
||||
|
||||
import pytest
|
||||
import uuid
|
||||
import sys
|
||||
import os
|
||||
from tests.utils import asyncio_patch
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(http_compute, project):
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes".format(project_id=project.id), {"name": "TraceNG TEST 1"})
|
||||
async def vm(compute_api, compute_project):
|
||||
|
||||
params = {"name": "TraceNG TEST 1"}
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
return response.json
|
||||
|
||||
|
||||
def test_traceng_create(http_compute, project):
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes".format(project_id=project.id), {"name": "TraceNG TEST 1"}, example=True)
|
||||
async def test_traceng_create(compute_api, compute_project):
|
||||
|
||||
params = {"name": "TraceNG TEST 1"}
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/traceng/nodes"
|
||||
assert response.json["name"] == "TraceNG TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_traceng_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/traceng/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_traceng_get(compute_api, compute_project, vm):
|
||||
|
||||
response = await compute_api.get("/projects/{project_id}/traceng/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.route == "/projects/{project_id}/traceng/nodes/{node_id}"
|
||||
assert response.json["name"] == "TraceNG TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["status"] == "stopped"
|
||||
|
||||
|
||||
def test_traceng_nio_create_udp(http_compute, vm):
|
||||
async def test_traceng_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.add_ubridge_udp_connection"):
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_traceng_nio_update_udp(http_compute, vm):
|
||||
async def test_traceng_nio_update_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.add_ubridge_udp_connection"):
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
response = http_compute.put("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]),
|
||||
{
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}},
|
||||
example=True)
|
||||
|
||||
params["filters"] = {}
|
||||
response = await compute_api.put("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201, response.body.decode("utf-8")
|
||||
assert response.route == r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_traceng_delete_nio(http_compute, vm):
|
||||
async def test_traceng_delete_nio(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM._ubridge_send"):
|
||||
http_compute.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.delete("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
response = await compute_api.delete("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204, response.body.decode()
|
||||
assert response.route == r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_traceng_start(http_compute, vm):
|
||||
async def test_traceng_start(compute_api, vm):
|
||||
|
||||
params = {"destination": "192.168.1.2"}
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.start", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"destination": "192.168.1.2"}, example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "TraceNG TEST 1"
|
||||
|
||||
|
||||
def test_traceng_stop(http_compute, vm):
|
||||
async def test_traceng_stop(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.stop", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_traceng_reload(http_compute, vm):
|
||||
async def test_traceng_reload(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.reload", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_traceng_delete(http_compute, vm):
|
||||
async def test_traceng_delete(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.traceng.TraceNG.delete_node", return_value=True) as mock:
|
||||
response = http_compute.delete("/projects/{project_id}/traceng/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.delete("/projects/{project_id}/traceng/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_traceng_duplicate(http_compute, vm):
|
||||
async def test_traceng_duplicate(compute_api, vm):
|
||||
|
||||
params = {"destination_node_id": str(uuid.uuid4())}
|
||||
with asyncio_patch("gns3server.compute.traceng.TraceNG.duplicate_node", return_value=True) as mock:
|
||||
response = http_compute.post(
|
||||
"/projects/{project_id}/traceng/nodes/{node_id}/duplicate".format(
|
||||
project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]),
|
||||
body={
|
||||
"destination_node_id": str(uuid.uuid4())
|
||||
},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/duplicate".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
|
||||
|
||||
def test_traceng_update(http_compute, vm, tmpdir, free_console_port):
|
||||
response = http_compute.put("/projects/{project_id}/traceng/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
|
||||
"ip_address": "192.168.1.1",
|
||||
},
|
||||
example=True)
|
||||
async def test_traceng_update(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"name": "test",
|
||||
"ip_address": "192.168.1.1"
|
||||
}
|
||||
|
||||
response = await compute_api.put("/projects/{project_id}/traceng/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["ip_address"] == "192.168.1.1"
|
||||
|
||||
|
||||
def test_traceng_start_capture(http_compute, vm):
|
||||
async def test_traceng_start_capture(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"capture_file_name": "test.pcap",
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
}
|
||||
|
||||
with patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.start_capture") as start_capture:
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.start_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_traceng_stop_capture(http_compute, vm):
|
||||
async def test_traceng_stop_capture(compute_api, vm):
|
||||
|
||||
with patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.stop_capture") as stop_capture:
|
||||
response = http_compute.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_traceng_pcap(http_compute, vm, project):
|
||||
async def test_traceng_pcap(compute_api, vm, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM.get_nio"):
|
||||
with asyncio_patch("gns3server.compute.traceng.TraceNG.stream_pcap_file"):
|
||||
response = http_compute.get("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=project.id, node_id=vm["node_id"]), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/traceng/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,89 +20,100 @@ from tests.utils import asyncio_patch
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@pytest.yield_fixture(scope="function")
|
||||
def vm(http_compute, project, monkeypatch):
|
||||
@pytest.fixture(scope="function")
|
||||
async def vm(compute_api, compute_project):
|
||||
|
||||
vboxmanage_path = "/fake/VboxManage"
|
||||
params = {
|
||||
"name": "VMTEST",
|
||||
"vmname": "VMTEST",
|
||||
"linked_clone": False
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes".format(
|
||||
project_id=project.id), {"name": "VMTEST",
|
||||
"vmname": "VMTEST",
|
||||
"linked_clone": False})
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes".format(project_id=compute_project.id), params)
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
|
||||
with patch("gns3server.compute.virtualbox.VirtualBox.find_vboxmanage", return_value=vboxmanage_path):
|
||||
yield response.json
|
||||
return response.json
|
||||
|
||||
|
||||
def test_vbox_create(http_compute, project):
|
||||
async def test_vbox_create(compute_api, compute_project):
|
||||
|
||||
params = {
|
||||
"name": "VM1",
|
||||
"vmname": "VM1",
|
||||
"linked_clone": False
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True):
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes".format(project_id=project.id), {"name": "VM1",
|
||||
"vmname": "VM1",
|
||||
"linked_clone": False},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.json["name"] == "VM1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_vbox_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_vbox_get(compute_api, compute_project, vm):
|
||||
|
||||
response = await compute_api.get("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}"
|
||||
assert response.json["name"] == "VMTEST"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_vbox_start(http_compute, vm):
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.check_hw_virtualization", return_value=True) as mock:
|
||||
async def test_vbox_start(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.check_hw_virtualization", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vbox_stop(http_compute, vm):
|
||||
async def test_vbox_stop(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vbox_suspend(http_compute, vm):
|
||||
async def test_vbox_suspend(compute_api, vm):
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.suspend", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vbox_resume(http_compute, vm):
|
||||
async def test_vbox_resume(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.resume", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vbox_reload(http_compute, vm):
|
||||
async def test_vbox_reload(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.reload", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vbox_nio_create_udp(http_compute, vm):
|
||||
async def test_vbox_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
args, kwgars = mock.call_args
|
||||
assert args[0] == 0
|
||||
@ -112,30 +123,29 @@ def test_vbox_nio_create_udp(http_compute, vm):
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_virtualbox_nio_update_udp(http_compute, vm):
|
||||
async def test_virtualbox_nio_update_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}
|
||||
}
|
||||
|
||||
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.ethernet_adapters'):
|
||||
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
|
||||
response = http_compute.put("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(
|
||||
project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]),
|
||||
{
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}},
|
||||
example=True)
|
||||
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding'):
|
||||
response = await compute_api.put("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
|
||||
assert response.status == 201, response.body.decode()
|
||||
assert response.route == r"/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_vbox_delete_nio(http_compute, vm):
|
||||
async def test_vbox_delete_nio(compute_api, vm):
|
||||
|
||||
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
|
||||
response = http_compute.delete("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
|
||||
response = await compute_api.delete("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
args, kwgars = mock.call_args
|
||||
assert args[0] == 0
|
||||
@ -144,38 +154,46 @@ def test_vbox_delete_nio(http_compute, vm):
|
||||
assert response.route == r"/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_vbox_update(http_compute, vm, free_console_port):
|
||||
response = http_compute.put("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
|
||||
"console": free_console_port},
|
||||
example=True)
|
||||
async def test_vbox_update(compute_api, vm, free_console_port):
|
||||
|
||||
params = {
|
||||
"name": "test",
|
||||
"console": free_console_port
|
||||
}
|
||||
|
||||
response = await compute_api.put("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["console"] == free_console_port
|
||||
|
||||
|
||||
def test_virtualbox_start_capture(http_compute, vm):
|
||||
async def test_virtualbox_start_capture(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"capture_file_name": "test.pcap",
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
}
|
||||
|
||||
with patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start_capture") as start_capture:
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_virtualbox_stop_capture(http_compute, vm):
|
||||
async def test_virtualbox_stop_capture(compute_api, vm):
|
||||
|
||||
with patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop_capture") as stop_capture:
|
||||
response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_virtualbox_pcap(http_compute, vm, project):
|
||||
async def test_virtualbox_pcap(compute_api, vm, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.get_nio"):
|
||||
with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.stream_pcap_file"):
|
||||
response = http_compute.get("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=project.id, node_id=vm["node_id"]), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -21,13 +21,16 @@ from unittest.mock import patch
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(http_compute, project, vmx_path):
|
||||
async def vm(compute_api, compute_project, vmx_path):
|
||||
|
||||
params = {
|
||||
"name": "VMTEST",
|
||||
"vmx_path": vmx_path,
|
||||
"linked_clone": False
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.create", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes".format(project_id=project.id), {
|
||||
"name": "VMTEST",
|
||||
"vmx_path": vmx_path,
|
||||
"linked_clone": False})
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes".format(project_id=compute_project.id), params)
|
||||
assert mock.called
|
||||
assert response.status == 201, response.body.decode()
|
||||
return response.json
|
||||
@ -38,79 +41,90 @@ def vmx_path(tmpdir):
|
||||
"""
|
||||
Return a fake VMX file
|
||||
"""
|
||||
|
||||
path = str(tmpdir / "test.vmx")
|
||||
with open(path, 'w+') as f:
|
||||
f.write("1")
|
||||
return path
|
||||
|
||||
|
||||
def test_vmware_create(http_compute, project, vmx_path):
|
||||
async def test_vmware_create(compute_api, compute_project, vmx_path):
|
||||
|
||||
params = {
|
||||
"name": "VM1",
|
||||
"vmx_path": vmx_path,
|
||||
"linked_clone": False
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.create", return_value=True):
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes".format(project_id=project.id), {
|
||||
"name": "VM1",
|
||||
"vmx_path": vmx_path,
|
||||
"linked_clone": False},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201, response.body.decode()
|
||||
assert response.json["name"] == "VM1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_vmware_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/vmware/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_vmware_get(compute_api, compute_project, vm):
|
||||
|
||||
response = await compute_api.get("/projects/{project_id}/vmware/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.route == "/projects/{project_id}/vmware/nodes/{node_id}"
|
||||
assert response.json["name"] == "VMTEST"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_vmware_start(http_compute, vm):
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.check_hw_virtualization", return_value=True) as mock:
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.start", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
assert mock.called
|
||||
async def test_vmware_start(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.check_hw_virtualization", return_value=True) as mock1:
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.start", return_value=True) as mock2:
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock1.called
|
||||
assert mock2.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vmware_stop(http_compute, vm):
|
||||
async def test_vmware_stop(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.stop", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vmware_suspend(http_compute, vm):
|
||||
async def test_vmware_suspend(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.suspend", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vmware_resume(http_compute, vm):
|
||||
async def test_vmware_resume(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.resume", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vmware_reload(http_compute, vm):
|
||||
async def test_vmware_reload(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.reload", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vmware_nio_create_udp(http_compute, vm):
|
||||
async def test_vmware_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.adapter_add_nio_binding') as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
args, kwgars = mock.call_args
|
||||
assert args[0] == 0
|
||||
@ -120,30 +134,29 @@ def test_vmware_nio_create_udp(http_compute, vm):
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_vmware_nio_update_udp(http_compute, vm):
|
||||
async def test_vmware_nio_update_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}
|
||||
}
|
||||
|
||||
with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM._ubridge_send'):
|
||||
with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.ethernet_adapters'):
|
||||
with patch('gns3server.compute.vmware.vmware_vm.VMwareVM._get_vnet') as mock:
|
||||
response = http_compute.put("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/nio".format(
|
||||
project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]),
|
||||
{
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}},
|
||||
example=True)
|
||||
assert response.status == 201, response.body.decode()
|
||||
response = await compute_api.put("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_vmware_delete_nio(http_compute, vm):
|
||||
async def test_vmware_delete_nio(compute_api, vm):
|
||||
|
||||
with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.adapter_remove_nio_binding') as mock:
|
||||
response = http_compute.delete("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
|
||||
response = await compute_api.delete("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
args, kwgars = mock.call_args
|
||||
assert args[0] == 0
|
||||
@ -152,37 +165,47 @@ def test_vmware_delete_nio(http_compute, vm):
|
||||
assert response.route == r"/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_vmware_update(http_compute, vm, free_console_port):
|
||||
response = http_compute.put("/projects/{project_id}/vmware/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
|
||||
"console": free_console_port},
|
||||
example=True)
|
||||
async def test_vmware_update(compute_api, vm, free_console_port):
|
||||
|
||||
params = {
|
||||
"name": "test",
|
||||
"console": free_console_port
|
||||
}
|
||||
|
||||
response = await compute_api.put("/projects/{project_id}/vmware/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["console"] == free_console_port
|
||||
|
||||
def test_vmware_start_capture(http_compute, vm):
|
||||
|
||||
async def test_vmware_start_capture(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"capture_file_name": "test.pcap",
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
}
|
||||
|
||||
with patch("gns3server.compute.vmware.vmware_vm.VMwareVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.start_capture") as start_capture:
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.start_capture") as mock:
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params)
|
||||
assert response.status == 200
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_vmware_stop_capture(http_compute, vm):
|
||||
async def test_vmware_stop_capture(compute_api, vm):
|
||||
|
||||
with patch("gns3server.compute.vmware.vmware_vm.VMwareVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.stop_capture") as stop_capture:
|
||||
response = http_compute.post("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_vmware_pcap(http_compute, vm, project):
|
||||
async def test_vmware_pcap(compute_api, vm, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.get_nio"):
|
||||
with asyncio_patch("gns3server.compute.vmware.VMware.stream_pcap_file"):
|
||||
response = http_compute.get("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=project.id, node_id=vm["node_id"]), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -21,168 +21,200 @@ from tests.utils import asyncio_patch
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(http_compute, project):
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes".format(project_id=project.id), {"name": "PC TEST 1"})
|
||||
@pytest.fixture
|
||||
async def vm(compute_api, compute_project):
|
||||
|
||||
params = {"name": "PC TEST 1"}
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
return response.json
|
||||
|
||||
|
||||
def test_vpcs_create(http_compute, project):
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes".format(project_id=project.id), {"name": "PC TEST 1"}, example=True)
|
||||
async def test_vpcs_create(compute_api, compute_project):
|
||||
|
||||
params = {"name": "PC TEST 1"}
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/vpcs/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_vpcs_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
async def test_vpcs_get(compute_api, compute_project, vm):
|
||||
|
||||
response = await compute_api.get("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.route == "/projects/{project_id}/vpcs/nodes/{node_id}"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["status"] == "stopped"
|
||||
|
||||
|
||||
def test_vpcs_create_startup_script(http_compute, project):
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes".format(project_id=project.id), {"name": "PC TEST 1", "startup_script": "ip 192.168.1.2\necho TEST"})
|
||||
async def test_vpcs_create_startup_script(compute_api, compute_project):
|
||||
|
||||
params = {
|
||||
"name": "PC TEST 1",
|
||||
"startup_script": "ip 192.168.1.2\necho TEST"
|
||||
}
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/vpcs/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
|
||||
|
||||
def test_vpcs_create_port(http_compute, project, free_console_port):
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes".format(project_id=project.id), {"name": "PC TEST 1", "console": free_console_port})
|
||||
async def test_vpcs_create_port(compute_api, compute_project, free_console_port):
|
||||
|
||||
params = {
|
||||
"name": "PC TEST 1",
|
||||
"console": free_console_port
|
||||
}
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes".format(project_id=compute_project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/projects/{project_id}/vpcs/nodes"
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
assert response.json["project_id"] == project.id
|
||||
assert response.json["project_id"] == compute_project.id
|
||||
assert response.json["console"] == free_console_port
|
||||
|
||||
|
||||
def test_vpcs_nio_create_udp(http_compute, vm):
|
||||
async def test_vpcs_nio_create_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
assert response.route == r"/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_vpcs_nio_update_udp(http_compute, vm):
|
||||
async def test_vpcs_nio_update_udp(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201
|
||||
response = http_compute.put("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]),
|
||||
{
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1",
|
||||
"filters": {}},
|
||||
example=True)
|
||||
|
||||
params["filters"] = {}
|
||||
response = await compute_api.put("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 201, response.body.decode("utf-8")
|
||||
assert response.route == r"/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
assert response.json["type"] == "nio_udp"
|
||||
|
||||
|
||||
def test_vpcs_delete_nio(http_compute, vm):
|
||||
async def test_vpcs_delete_nio(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM._ubridge_send"):
|
||||
http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
|
||||
"lport": 4242,
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"})
|
||||
response = http_compute.delete("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
response = await compute_api.delete("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204, response.body.decode()
|
||||
assert response.route == r"/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
|
||||
|
||||
|
||||
def test_vpcs_start(http_compute, vm):
|
||||
async def test_vpcs_start(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "PC TEST 1"
|
||||
|
||||
|
||||
def test_vpcs_stop(http_compute, vm):
|
||||
async def test_vpcs_stop(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vpcs_reload(http_compute, vm):
|
||||
async def test_vpcs_reload(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.reload", return_value=True) as mock:
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vpcs_delete(http_compute, vm):
|
||||
async def test_vpcs_delete(compute_api, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.VPCS.delete_node", return_value=True) as mock:
|
||||
response = http_compute.delete("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
response = await compute_api.delete("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_vpcs_duplicate(http_compute, vm):
|
||||
async def test_vpcs_duplicate(compute_api, vm):
|
||||
|
||||
params = {"destination_node_id": str(uuid.uuid4())}
|
||||
with asyncio_patch("gns3server.compute.vpcs.VPCS.duplicate_node", return_value=True) as mock:
|
||||
response = http_compute.post(
|
||||
"/projects/{project_id}/vpcs/nodes/{node_id}/duplicate".format(
|
||||
project_id=vm["project_id"],
|
||||
node_id=vm["node_id"]),
|
||||
body={
|
||||
"destination_node_id": str(uuid.uuid4())
|
||||
},
|
||||
example=True)
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/duplicate".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
|
||||
|
||||
def test_vpcs_update(http_compute, vm, tmpdir, free_console_port):
|
||||
response = http_compute.put("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
|
||||
"console": free_console_port,
|
||||
},
|
||||
example=True)
|
||||
async def test_vpcs_update(compute_api, vm, free_console_port):
|
||||
|
||||
console_port = free_console_port
|
||||
params = {
|
||||
"name": "test",
|
||||
"console": console_port
|
||||
}
|
||||
|
||||
response = await compute_api.put("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["console"] == free_console_port
|
||||
assert response.json["console"] == console_port
|
||||
|
||||
|
||||
def test_vpcs_start_capture(http_compute, vm):
|
||||
async def test_vpcs_start_capture(compute_api, vm):
|
||||
|
||||
params = {
|
||||
"capture_file_name": "test.pcap",
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
}
|
||||
|
||||
with patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_capture") as start_capture:
|
||||
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params)
|
||||
assert response.status == 200
|
||||
assert start_capture.called
|
||||
assert mock.called
|
||||
assert "test.pcap" in response.json["pcap_file_path"]
|
||||
|
||||
|
||||
def test_vpcs_stop_capture(http_compute, vm):
|
||||
async def test_vpcs_stop_capture(compute_api, vm):
|
||||
|
||||
with patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.is_running", return_value=True):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop_capture") as stop_capture:
|
||||
response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop_capture") as mock:
|
||||
response = await compute_api.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
|
||||
assert response.status == 204
|
||||
assert stop_capture.called
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_vpcs_pcap(http_compute, vm, project):
|
||||
async def test_vpcs_pcap(compute_api, vm, compute_project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.get_nio"):
|
||||
with asyncio_patch("gns3server.compute.vpcs.VPCS.stream_pcap_file"):
|
||||
response = http_compute.get("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=project.id, node_id=vm["node_id"]), raw=True)
|
||||
response = await compute_api.get("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,9 +16,8 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
def test_appliances_list(http_controller, controller, async_run):
|
||||
async def test_appliances_list(controller_api):
|
||||
|
||||
controller.appliance_manager.load_appliances()
|
||||
response = http_controller.get("/appliances", example=True)
|
||||
response = await controller_api.get("/appliances")
|
||||
assert response.status == 200
|
||||
assert len(response.json) > 0
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -19,27 +19,26 @@ import unittest
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
|
||||
def test_compute_create_without_id(http_controller, controller):
|
||||
async def test_compute_create_without_id(controller_api, controller):
|
||||
|
||||
params = {
|
||||
"protocol": "http",
|
||||
"host": "localhost",
|
||||
"port": 84,
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params, example=True)
|
||||
"password": "secure"}
|
||||
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/computes"
|
||||
assert response.json["user"] == "julien"
|
||||
assert response.json["compute_id"] is not None
|
||||
assert "password" not in response.json
|
||||
|
||||
assert len(controller.computes) == 1
|
||||
assert controller.computes[response.json["compute_id"]].host == "localhost"
|
||||
|
||||
|
||||
def test_compute_create_with_id(http_controller, controller):
|
||||
async def test_compute_create_with_id(controller_api, controller):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute_id",
|
||||
@ -47,9 +46,9 @@ def test_compute_create_with_id(http_controller, controller):
|
||||
"host": "localhost",
|
||||
"port": 84,
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params, example=True)
|
||||
"password": "secure"}
|
||||
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/computes"
|
||||
assert response.json["user"] == "julien"
|
||||
@ -59,7 +58,7 @@ def test_compute_create_with_id(http_controller, controller):
|
||||
assert controller.computes["my_compute_id"].host == "localhost"
|
||||
|
||||
|
||||
def test_compute_get(http_controller, controller):
|
||||
async def test_compute_get(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute_id",
|
||||
@ -69,15 +68,16 @@ def test_compute_get(http_controller, controller):
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params)
|
||||
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_controller.get("/computes/my_compute_id", example=True)
|
||||
response = await controller_api.get("/computes/my_compute_id")
|
||||
assert response.status == 200
|
||||
assert response.json["protocol"] == "http"
|
||||
|
||||
|
||||
def test_compute_update(http_controller, controller):
|
||||
async def test_compute_update(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute_id",
|
||||
@ -87,21 +87,22 @@ def test_compute_update(http_controller, controller):
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params)
|
||||
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_controller.get("/computes/my_compute_id")
|
||||
response = await controller_api.get("/computes/my_compute_id")
|
||||
assert response.status == 200
|
||||
assert response.json["protocol"] == "http"
|
||||
|
||||
params["protocol"] = "https"
|
||||
response = http_controller.put("/computes/my_compute_id", params, example=True)
|
||||
response = await controller_api.put("/computes/my_compute_id", params)
|
||||
|
||||
assert response.status == 200
|
||||
assert response.json["protocol"] == "https"
|
||||
|
||||
|
||||
def test_compute_list(http_controller, controller):
|
||||
async def test_compute_list(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute_id",
|
||||
@ -112,13 +113,14 @@ def test_compute_list(http_controller, controller):
|
||||
"password": "secure",
|
||||
"name": "My super server"
|
||||
}
|
||||
response = http_controller.post("/computes", params)
|
||||
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/computes"
|
||||
assert response.json["user"] == "julien"
|
||||
assert "password" not in response.json
|
||||
|
||||
response = http_controller.get("/computes", example=True)
|
||||
response = await controller_api.get("/computes")
|
||||
for compute in response.json:
|
||||
if compute['compute_id'] != 'local':
|
||||
assert compute == {
|
||||
@ -139,7 +141,7 @@ def test_compute_list(http_controller, controller):
|
||||
}
|
||||
|
||||
|
||||
def test_compute_delete(http_controller, controller):
|
||||
async def test_compute_delete(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute_id",
|
||||
@ -149,20 +151,20 @@ def test_compute_delete(http_controller, controller):
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params)
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_controller.get("/computes")
|
||||
response = await controller_api.get("/computes")
|
||||
assert len(response.json) == 1
|
||||
|
||||
response = http_controller.delete("/computes/my_compute_id", example=True)
|
||||
response = await controller_api.delete("/computes/my_compute_id")
|
||||
assert response.status == 204
|
||||
|
||||
response = http_controller.get("/computes")
|
||||
response = await controller_api.get("/computes")
|
||||
assert len(response.json) == 0
|
||||
|
||||
|
||||
def test_compute_list_images(http_controller, controller):
|
||||
async def test_compute_list_images(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute",
|
||||
@ -172,16 +174,16 @@ def test_compute_list_images(http_controller, controller):
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params)
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.images", return_value=[{"filename": "linux.qcow2"}, {"filename": "asav.qcow2"}]) as mock:
|
||||
response = http_controller.get("/computes/my_compute/qemu/images", example=True)
|
||||
response = await controller_api.get("/computes/my_compute/qemu/images")
|
||||
assert response.json == [{"filename": "linux.qcow2"}, {"filename": "asav.qcow2"}]
|
||||
mock.assert_called_with("qemu")
|
||||
|
||||
|
||||
def test_compute_list_vms(http_controller, controller):
|
||||
async def test_compute_list_vms(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute",
|
||||
@ -191,16 +193,16 @@ def test_compute_list_vms(http_controller, controller):
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params)
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.forward", return_value=[]) as mock:
|
||||
response = http_controller.get("/computes/my_compute/virtualbox/vms", example=True)
|
||||
response = await controller_api.get("/computes/my_compute/virtualbox/vms")
|
||||
assert response.json == []
|
||||
mock.assert_called_with("GET", "virtualbox", "vms")
|
||||
|
||||
|
||||
def test_compute_create_img(http_controller, controller):
|
||||
async def test_compute_create_img(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute",
|
||||
@ -210,16 +212,18 @@ def test_compute_create_img(http_controller, controller):
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params)
|
||||
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
|
||||
params = {"path": "/test"}
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.forward", return_value=[]) as mock:
|
||||
response = http_controller.post("/computes/my_compute/qemu/img", params, example=True)
|
||||
response = await controller_api.post("/computes/my_compute/qemu/img", params)
|
||||
assert response.json == []
|
||||
mock.assert_called_with("POST", "qemu", "img", data=unittest.mock.ANY)
|
||||
|
||||
|
||||
def test_compute_autoidlepc(http_controller, controller):
|
||||
async def test_compute_autoidlepc(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute_id",
|
||||
@ -229,20 +233,23 @@ def test_compute_autoidlepc(http_controller, controller):
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params, example=False)
|
||||
|
||||
await controller_api.post("/computes", params)
|
||||
|
||||
params = {
|
||||
"platform": "c7200",
|
||||
"image": "test.bin",
|
||||
"ram": 512
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.Controller.autoidlepc", return_value={"idlepc": "0x606de20c"}) as mock:
|
||||
response = http_controller.post("/computes/my_compute_id/auto_idlepc", params, example=True)
|
||||
response = await controller_api.post("/computes/my_compute_id/auto_idlepc", params)
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_compute_endpoint(http_controller, controller):
|
||||
async def test_compute_endpoint(controller_api):
|
||||
|
||||
params = {
|
||||
"compute_id": "my_compute",
|
||||
"protocol": "http",
|
||||
@ -251,10 +258,10 @@ def test_compute_endpoint(http_controller, controller):
|
||||
"user": "julien",
|
||||
"password": "secure"
|
||||
}
|
||||
response = http_controller.post("/computes", params)
|
||||
|
||||
response = await controller_api.post("/computes", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_controller.get("/computes/endpoint/my_compute/virtualbox/images")
|
||||
response = await controller_api.get("/computes/endpoint/my_compute/virtualbox/images")
|
||||
assert response.status == 200
|
||||
assert response.json['endpoint'] == 'http://localhost:84/v2/compute/virtualbox/images'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,85 +15,73 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This test suite check /project endpoint
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import os
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import pytest
|
||||
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.handlers.api.controller.project_handler import ProjectHandler
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.controller.drawing import Drawing
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(http_controller, async_run):
|
||||
return async_run(Controller.instance().add_project(name="Test"))
|
||||
async def test_create_drawing(controller_api, project):
|
||||
|
||||
|
||||
def test_create_drawing(http_controller, tmpdir, project, async_run):
|
||||
|
||||
response = http_controller.post("/projects/{}/drawings".format(project.id), {
|
||||
params = {
|
||||
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
|
||||
"x": 10,
|
||||
"y": 20,
|
||||
"z": 0
|
||||
}, example=True)
|
||||
}
|
||||
|
||||
response = await controller_api.post("/projects/{}/drawings".format(project.id), params)
|
||||
assert response.status == 201
|
||||
assert response.json["drawing_id"] is not None
|
||||
|
||||
|
||||
def test_get_drawing(http_controller, tmpdir, project, async_run):
|
||||
async def test_get_drawing(controller_api, project):
|
||||
|
||||
response = http_controller.post("/projects/{}/drawings".format(project.id), {
|
||||
params = {
|
||||
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
|
||||
"x": 10,
|
||||
"y": 20,
|
||||
"z": 0
|
||||
},)
|
||||
response = http_controller.get("/projects/{}/drawings/{}".format(project.id, response.json["drawing_id"]), example=True)
|
||||
}
|
||||
|
||||
response = await controller_api.post("/projects/{}/drawings".format(project.id), params)
|
||||
response = await controller_api.get("/projects/{}/drawings/{}".format(project.id, response.json["drawing_id"]))
|
||||
assert response.status == 200
|
||||
assert response.json["x"] == 10
|
||||
|
||||
|
||||
def test_update_drawing(http_controller, tmpdir, project, async_run):
|
||||
async def test_update_drawing(controller_api, project):
|
||||
|
||||
response = http_controller.post("/projects/{}/drawings".format(project.id), {
|
||||
params = {
|
||||
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
|
||||
"x": 10,
|
||||
"y": 20,
|
||||
"z": 0
|
||||
},)
|
||||
response = http_controller.put("/projects/{}/drawings/{}".format(project.id, response.json["drawing_id"]), {
|
||||
"x": 42,
|
||||
}, example=True)
|
||||
}
|
||||
|
||||
response = await controller_api.post("/projects/{}/drawings".format(project.id), params)
|
||||
response = await controller_api.put("/projects/{}/drawings/{}".format(project.id, response.json["drawing_id"]), {"x": 42})
|
||||
assert response.status == 201
|
||||
assert response.json["x"] == 42
|
||||
|
||||
|
||||
def test_list_drawing(http_controller, tmpdir, project, async_run):
|
||||
response = http_controller.post("/projects/{}/drawings".format(project.id), {
|
||||
async def test_list_drawing(controller_api, project):
|
||||
|
||||
params = {
|
||||
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
|
||||
"x": 10,
|
||||
"y": 20,
|
||||
"z": 0
|
||||
}, example=False)
|
||||
response = http_controller.get("/projects/{}/drawings".format(project.id), example=True)
|
||||
}
|
||||
|
||||
await controller_api.post("/projects/{}/drawings".format(project.id), params)
|
||||
response = await controller_api.get("/projects/{}/drawings".format(project.id))
|
||||
assert response.status == 200
|
||||
assert len(response.json) == 1
|
||||
|
||||
|
||||
def test_delete_drawing(http_controller, tmpdir, project, async_run):
|
||||
async def test_delete_drawing(controller_api, project):
|
||||
|
||||
drawing = Drawing(project)
|
||||
project._drawings = {drawing.id: drawing}
|
||||
response = http_controller.delete("/projects/{}/drawings/{}".format(project.id, drawing.id), example=True)
|
||||
response = await controller_api.delete("/projects/{}/drawings/{}".format(project.id, drawing.id))
|
||||
assert response.status == 204
|
||||
assert drawing.id not in project._drawings
|
||||
assert drawing.id not in project.drawings
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -18,9 +18,10 @@
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
|
||||
def test_list_vms(http_controller):
|
||||
async def test_list_vms(controller_api):
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.list", return_value=[{"vmname": "test"}]):
|
||||
response = http_controller.get('/gns3vm/engines/vmware/vms', example=True)
|
||||
response = await controller_api.get('/gns3vm/engines/vmware/vms')
|
||||
assert response.status == 200
|
||||
assert response.json == [
|
||||
{
|
||||
@ -29,20 +30,20 @@ def test_list_vms(http_controller):
|
||||
]
|
||||
|
||||
|
||||
def test_engines(http_controller):
|
||||
response = http_controller.get('/gns3vm/engines', example=True)
|
||||
async def test_engines(controller_api):
|
||||
|
||||
response = await controller_api.get('/gns3vm/engines')
|
||||
assert response.status == 200
|
||||
assert len(response.json) > 0
|
||||
|
||||
|
||||
def test_put_gns3vm(http_controller):
|
||||
response = http_controller.put('/gns3vm', {
|
||||
"vmname": "TEST VM"
|
||||
}, example=True)
|
||||
async def test_put_gns3vm(controller_api):
|
||||
|
||||
response = await controller_api.put('/gns3vm', {"vmname": "TEST VM"})
|
||||
assert response.status == 201
|
||||
assert response.json["vmname"] == "TEST VM"
|
||||
|
||||
|
||||
def test_get_gns3vm(http_controller):
|
||||
response = http_controller.get('/gns3vm', example=True)
|
||||
async def test_get_gns3vm(controller_api):
|
||||
response = await controller_api.get('/gns3vm')
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,45 +15,32 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This test suite check /project endpoint
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import pytest
|
||||
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.controller.ports.ethernet_port import EthernetPort
|
||||
from gns3server.controller.link import Link, FILTERS
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute(http_controller, async_run):
|
||||
compute = MagicMock()
|
||||
compute.id = "example.com"
|
||||
Controller.instance()._computes = {"example.com": compute}
|
||||
return compute
|
||||
async def nodes(compute, project):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(http_controller, async_run):
|
||||
return async_run(Controller.instance().add_project(name="Test"))
|
||||
|
||||
|
||||
def test_create_link(http_controller, tmpdir, project, compute, async_run):
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project.add_node(compute, "node1", None, node_type="qemu"))
|
||||
node1 = await project.add_node(compute, "node1", None, node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 3)]
|
||||
node2 = async_run(project.add_node(compute, "node2", None, node_type="qemu"))
|
||||
node2 = await project.add_node(compute, "node2", None, node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 2, 4)]
|
||||
return node1, node2
|
||||
|
||||
|
||||
async def test_create_link(controller_api, project, nodes):
|
||||
|
||||
node1, node2 = nodes
|
||||
|
||||
filters = {
|
||||
"latency": [10],
|
||||
@ -61,7 +48,7 @@ def test_create_link(http_controller, tmpdir, project, compute, async_run):
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
|
||||
response = http_controller.post("/projects/{}/links".format(project.id), {
|
||||
response = await controller_api.post("/projects/{}/links".format(project.id), {
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
@ -80,7 +67,8 @@ def test_create_link(http_controller, tmpdir, project, compute, async_run):
|
||||
}
|
||||
],
|
||||
"filters": filters
|
||||
}, example=True)
|
||||
})
|
||||
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
assert response.json["link_id"] is not None
|
||||
@ -90,56 +78,49 @@ def test_create_link(http_controller, tmpdir, project, compute, async_run):
|
||||
assert list(project.links.values())[0].filters == filters
|
||||
|
||||
|
||||
def test_create_link_failure(http_controller, tmpdir, project, compute, async_run):
|
||||
async def test_create_link_failure(controller_api, compute, project):
|
||||
"""
|
||||
Make sure the link is deleted if we failed to create the link.
|
||||
Make sure the link is deleted if we failed to create it.
|
||||
|
||||
The failure is trigger by connecting the link to himself
|
||||
The failure is triggered by connecting the link to itself
|
||||
"""
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project.add_node(compute, "node1", None, node_type="qemu"))
|
||||
node1 = await project.add_node(compute, "node1", None, node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 3), EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"):
|
||||
response = http_controller.post("/projects/{}/links".format(project.id), {
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
"adapter_number": 0,
|
||||
"port_number": 3,
|
||||
"label": {
|
||||
"text": "Text",
|
||||
"x": 42,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"node_id": node1.id,
|
||||
"adapter_number": 0,
|
||||
"port_number": 4
|
||||
response = await controller_api.post("/projects/{}/links".format(project.id), {
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
"adapter_number": 0,
|
||||
"port_number": 3,
|
||||
"label": {
|
||||
"text": "Text",
|
||||
"x": 42,
|
||||
"y": 0
|
||||
}
|
||||
]
|
||||
}, example=True)
|
||||
#assert mock.called
|
||||
},
|
||||
{
|
||||
"node_id": node1.id,
|
||||
"adapter_number": 0,
|
||||
"port_number": 4
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
assert response.status == 409
|
||||
assert len(project.links) == 0
|
||||
|
||||
|
||||
def test_get_link(http_controller, tmpdir, project, compute, async_run):
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
async def test_get_link(controller_api, project, nodes):
|
||||
|
||||
node1 = async_run(project.add_node(compute, "node1", None, node_type="qemu"))
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 3)]
|
||||
node2 = async_run(project.add_node(compute, "node2", None, node_type="qemu"))
|
||||
node2._ports = [EthernetPort("E0", 0, 2, 4)]
|
||||
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"):
|
||||
response = http_controller.post("/projects/{}/links".format(project.id), {
|
||||
node1, node2 = nodes
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
|
||||
response = await controller_api.post("/projects/{}/links".format(project.id), {
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
@ -158,25 +139,20 @@ def test_get_link(http_controller, tmpdir, project, compute, async_run):
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
assert mock.called
|
||||
link_id = response.json["link_id"]
|
||||
assert response.json["nodes"][0]["label"]["x"] == 42
|
||||
response = http_controller.get("/projects/{}/links/{}".format(project.id, link_id), example=True)
|
||||
response = await controller_api.get("/projects/{}/links/{}".format(project.id, link_id))
|
||||
assert response.status == 200
|
||||
assert response.json["nodes"][0]["label"]["x"] == 42
|
||||
|
||||
|
||||
def test_update_link_suspend(http_controller, tmpdir, project, compute, async_run):
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
async def test_update_link_suspend(controller_api, project, nodes):
|
||||
|
||||
node1 = async_run(project.add_node(compute, "node1", None, node_type="qemu"))
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 3)]
|
||||
node2 = async_run(project.add_node(compute, "node2", None, node_type="qemu"))
|
||||
node2._ports = [EthernetPort("E0", 0, 2, 4)]
|
||||
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"):
|
||||
response = http_controller.post("/projects/{}/links".format(project.id), {
|
||||
node1, node2 = nodes
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
|
||||
response = await controller_api.post("/projects/{}/links".format(project.id), {
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
@ -195,9 +171,12 @@ def test_update_link_suspend(http_controller, tmpdir, project, compute, async_ru
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
assert mock.called
|
||||
link_id = response.json["link_id"]
|
||||
assert response.json["nodes"][0]["label"]["x"] == 42
|
||||
response = http_controller.put("/projects/{}/links/{}".format(project.id, link_id), {
|
||||
|
||||
response = await controller_api.put("/projects/{}/links/{}".format(project.id, link_id), {
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
@ -217,29 +196,23 @@ def test_update_link_suspend(http_controller, tmpdir, project, compute, async_ru
|
||||
],
|
||||
"suspend": True
|
||||
})
|
||||
|
||||
assert response.status == 201
|
||||
assert response.json["nodes"][0]["label"]["x"] == 64
|
||||
assert response.json["suspend"]
|
||||
assert response.json["filters"] == {}
|
||||
|
||||
|
||||
def test_update_link(http_controller, tmpdir, project, compute, async_run):
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project.add_node(compute, "node1", None, node_type="qemu"))
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 3)]
|
||||
node2 = async_run(project.add_node(compute, "node2", None, node_type="qemu"))
|
||||
node2._ports = [EthernetPort("E0", 0, 2, 4)]
|
||||
async def test_update_link(controller_api, project, nodes):
|
||||
|
||||
filters = {
|
||||
"latency": [10],
|
||||
"frequency_drop": [50]
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"):
|
||||
response = http_controller.post("/projects/{}/links".format(project.id), {
|
||||
node1, node2 = nodes
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
|
||||
response = await controller_api.post("/projects/{}/links".format(project.id), {
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
@ -258,9 +231,12 @@ def test_update_link(http_controller, tmpdir, project, compute, async_run):
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
assert mock.called
|
||||
link_id = response.json["link_id"]
|
||||
assert response.json["nodes"][0]["label"]["x"] == 42
|
||||
response = http_controller.put("/projects/{}/links/{}".format(project.id, link_id), {
|
||||
|
||||
response = await controller_api.put("/projects/{}/links/{}".format(project.id, link_id), {
|
||||
"nodes": [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
@ -279,26 +255,21 @@ def test_update_link(http_controller, tmpdir, project, compute, async_run):
|
||||
}
|
||||
],
|
||||
"filters": filters
|
||||
}, example=True)
|
||||
})
|
||||
|
||||
assert response.status == 201
|
||||
assert response.json["nodes"][0]["label"]["x"] == 64
|
||||
assert list(project.links.values())[0].filters == filters
|
||||
|
||||
|
||||
def test_list_link(http_controller, tmpdir, project, compute, async_run):
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project.add_node(compute, "node1", None, node_type="qemu"))
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 3)]
|
||||
node2 = async_run(project.add_node(compute, "node2", None, node_type="qemu"))
|
||||
node2._ports = [EthernetPort("E0", 0, 2, 4)]
|
||||
async def test_list_link(controller_api, project, nodes):
|
||||
|
||||
filters = {
|
||||
"latency": [10],
|
||||
"frequency_drop": [50]
|
||||
}
|
||||
|
||||
node1, node2 = nodes
|
||||
nodes = [
|
||||
{
|
||||
"node_id": node1.id,
|
||||
@ -311,40 +282,45 @@ def test_list_link(http_controller, tmpdir, project, compute, async_run):
|
||||
"port_number": 4
|
||||
}
|
||||
]
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"):
|
||||
response = http_controller.post("/projects/{}/links".format(project.id), {
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
|
||||
await controller_api.post("/projects/{}/links".format(project.id), {
|
||||
"nodes": nodes,
|
||||
"filters": filters
|
||||
})
|
||||
response = http_controller.get("/projects/{}/links".format(project.id), example=True)
|
||||
|
||||
assert mock.called
|
||||
response = await controller_api.get("/projects/{}/links".format(project.id))
|
||||
assert response.status == 200
|
||||
assert len(response.json) == 1
|
||||
assert response.json[0]["filters"] == filters
|
||||
|
||||
|
||||
def test_start_capture(http_controller, tmpdir, project, compute, async_run):
|
||||
async def test_start_capture(controller_api, project):
|
||||
|
||||
link = Link(project)
|
||||
project._links = {link.id: link}
|
||||
with asyncio_patch("gns3server.controller.link.Link.start_capture") as mock:
|
||||
response = http_controller.post("/projects/{}/links/{}/start_capture".format(project.id, link.id), example=True)
|
||||
response = await controller_api.post("/projects/{}/links/{}/start_capture".format(project.id, link.id))
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
|
||||
|
||||
def test_stop_capture(http_controller, tmpdir, project, compute, async_run):
|
||||
async def test_stop_capture(controller_api, project):
|
||||
|
||||
link = Link(project)
|
||||
project._links = {link.id: link}
|
||||
with asyncio_patch("gns3server.controller.link.Link.stop_capture") as mock:
|
||||
response = http_controller.post("/projects/{}/links/{}/stop_capture".format(project.id, link.id), example=True)
|
||||
response = await controller_api.post("/projects/{}/links/{}/stop_capture".format(project.id, link.id))
|
||||
assert mock.called
|
||||
assert response.status == 201
|
||||
|
||||
|
||||
# def test_pcap(http_controller, tmpdir, project, compute, async_run):
|
||||
# async def test_pcap(controller_api, http_client, project):
|
||||
#
|
||||
# async def go():
|
||||
# async with aiohttp.request("GET", http_controller.get_url("/projects/{}/links/{}/pcap".format(project.id, link.id))) as response:
|
||||
# async def pcap_capture():
|
||||
# async with http_client.get(controller_api.get_url("/projects/{}/links/{}/pcap".format(project.id, link.id))) as response:
|
||||
# response.body = await response.content.read(5)
|
||||
# print("READ", response.body)
|
||||
# return response
|
||||
#
|
||||
# with asyncio_patch("gns3server.controller.link.Link.capture_node") as mock:
|
||||
@ -354,27 +330,28 @@ def test_stop_capture(http_controller, tmpdir, project, compute, async_run):
|
||||
# with open(link.capture_file_path, "w+") as f:
|
||||
# f.write("hello")
|
||||
# project._links = {link.id: link}
|
||||
# response = async_run(asyncio.ensure_future(go()))
|
||||
# response = await pcap_capture()
|
||||
# assert mock.called
|
||||
# assert response.status == 200
|
||||
# assert b'hello' == response.body
|
||||
|
||||
|
||||
def test_delete_link(http_controller, tmpdir, project, compute, async_run):
|
||||
async def test_delete_link(controller_api, project):
|
||||
|
||||
link = Link(project)
|
||||
project._links = {link.id: link}
|
||||
with asyncio_patch("gns3server.controller.link.Link.delete") as mock:
|
||||
response = http_controller.delete("/projects/{}/links/{}".format(project.id, link.id), example=True)
|
||||
response = await controller_api.delete("/projects/{}/links/{}".format(project.id, link.id))
|
||||
assert mock.called
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_list_filters(http_controller, tmpdir, project, async_run):
|
||||
async def test_list_filters(controller_api, project):
|
||||
|
||||
link = Link(project)
|
||||
project._links = {link.id: link}
|
||||
with patch("gns3server.controller.link.Link.available_filters", return_value=FILTERS) as mock:
|
||||
response = http_controller.get("/projects/{}/links/{}/available_filters".format(project.id, link.id), example=True)
|
||||
response = await controller_api.get("/projects/{}/links/{}/available_filters".format(project.id, link.id))
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
assert response.json == FILTERS
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,70 +15,50 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This test suite check /project endpoint
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import os
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import pytest
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
from gns3server.handlers.api.controller.project_handler import ProjectHandler
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.controller.node import Node
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute(http_controller, async_run):
|
||||
compute = MagicMock()
|
||||
compute.id = "example.com"
|
||||
compute.host = "example.org"
|
||||
Controller.instance()._computes = {"example.com": compute}
|
||||
return compute
|
||||
def node(project, compute):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(http_controller, async_run):
|
||||
return async_run(Controller.instance().add_project(name="Test"))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(project, compute, async_run):
|
||||
node = Node(project, compute, "test", node_type="vpcs")
|
||||
project._nodes[node.id] = node
|
||||
return node
|
||||
|
||||
|
||||
def test_create_node(http_controller, tmpdir, project, compute):
|
||||
async def test_create_node(controller_api, project, compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes".format(project.id), {
|
||||
response = await controller_api.post("/projects/{}/nodes".format(project.id), {
|
||||
"name": "test",
|
||||
"node_type": "vpcs",
|
||||
"compute_id": "example.com",
|
||||
"properties": {
|
||||
"startup_script": "echo test"
|
||||
}
|
||||
}, example=True)
|
||||
})
|
||||
|
||||
assert response.status == 201
|
||||
assert response.json["name"] == "test"
|
||||
assert "name" not in response.json["properties"]
|
||||
|
||||
|
||||
def test_list_node(http_controller, tmpdir, project, compute):
|
||||
async def test_list_node(controller_api, project, compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes".format(project.id), {
|
||||
await controller_api.post("/projects/{}/nodes".format(project.id), {
|
||||
"name": "test",
|
||||
"node_type": "vpcs",
|
||||
"compute_id": "example.com",
|
||||
@ -86,17 +66,19 @@ def test_list_node(http_controller, tmpdir, project, compute):
|
||||
"startup_script": "echo test"
|
||||
}
|
||||
})
|
||||
response = http_controller.get("/projects/{}/nodes".format(project.id), example=True)
|
||||
|
||||
response = await controller_api.get("/projects/{}/nodes".format(project.id))
|
||||
assert response.status == 200
|
||||
assert response.json[0]["name"] == "test"
|
||||
|
||||
|
||||
def test_get_node(http_controller, tmpdir, project, compute):
|
||||
async def test_get_node(controller_api, project, compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes".format(project.id), {
|
||||
response = await controller_api.post("/projects/{}/nodes".format(project.id), {
|
||||
"name": "test",
|
||||
"node_type": "vpcs",
|
||||
"compute_id": "example.com",
|
||||
@ -104,174 +86,175 @@ def test_get_node(http_controller, tmpdir, project, compute):
|
||||
"startup_script": "echo test"
|
||||
}
|
||||
})
|
||||
response = http_controller.get("/projects/{}/nodes/{}".format(project.id, response.json["node_id"]), example=True)
|
||||
|
||||
response = await controller_api.get("/projects/{}/nodes/{}".format(project.id, response.json["node_id"]))
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
|
||||
|
||||
def test_update_node(http_controller, tmpdir, project, compute, node):
|
||||
async def test_update_node(controller_api, project, compute, node):
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.put = AsyncioMagicMock(return_value=response)
|
||||
|
||||
response = http_controller.put("/projects/{}/nodes/{}".format(project.id, node.id), {
|
||||
response = await controller_api.put("/projects/{}/nodes/{}".format(project.id, node.id), {
|
||||
"name": "test",
|
||||
"node_type": "vpcs",
|
||||
"compute_id": "example.com",
|
||||
"properties": {
|
||||
"startup_script": "echo test"
|
||||
}
|
||||
}, example=True)
|
||||
})
|
||||
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
assert "name" not in response.json["properties"]
|
||||
|
||||
|
||||
def test_start_all_nodes(http_controller, tmpdir, project, compute):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_start_all_nodes(controller_api, project, compute):
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/start".format(project.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.post("/projects/{}/nodes/start".format(project.id))
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_stop_all_nodes(http_controller, tmpdir, project, compute):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_stop_all_nodes(controller_api, project, compute):
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/stop".format(project.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.post("/projects/{}/nodes/stop".format(project.id))
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_suspend_all_nodes(http_controller, tmpdir, project, compute):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_suspend_all_nodes(controller_api, project, compute):
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/suspend".format(project.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.post("/projects/{}/nodes/suspend".format(project.id))
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_reload_all_nodes(http_controller, tmpdir, project, compute):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_reload_all_nodes(controller_api, project, compute):
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/reload".format(project.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.post("/projects/{}/nodes/reload".format(project.id))
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_start_node(http_controller, tmpdir, project, compute, node):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_start_node(controller_api, project, node, compute):
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/{}/start".format(project.id, node.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.post("/projects/{}/nodes/{}/start".format(project.id, node.id))
|
||||
assert response.status == 200
|
||||
assert response.json == node.__json__()
|
||||
|
||||
|
||||
def test_stop_node(http_controller, tmpdir, project, compute, node):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_stop_node(controller_api, project, node, compute):
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/{}/stop".format(project.id, node.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.post("/projects/{}/nodes/{}/stop".format(project.id, node.id))
|
||||
assert response.status == 200
|
||||
assert response.json == node.__json__()
|
||||
|
||||
|
||||
def test_suspend_node(http_controller, tmpdir, project, compute, node):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_suspend_node(controller_api, project, node, compute):
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/{}/suspend".format(project.id, node.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.post("/projects/{}/nodes/{}/suspend".format(project.id, node.id))
|
||||
assert response.status == 200
|
||||
assert response.json == node.__json__()
|
||||
|
||||
|
||||
def test_reload_node(http_controller, tmpdir, project, compute, node):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_reload_node(controller_api, project, node, compute):
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/{}/reload".format(project.id, node.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.post("/projects/{}/nodes/{}/reload".format(project.id, node.id))
|
||||
assert response.status == 200
|
||||
assert response.json == node.__json__()
|
||||
|
||||
|
||||
def test_duplicate_node(http_controller, tmpdir, project, compute, node):
|
||||
async def test_duplicate_node(controller_api, project, compute, node):
|
||||
|
||||
response = MagicMock()
|
||||
response.json({"console": 2035})
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
response = http_controller.post("/projects/{}/nodes/{}/duplicate".format(
|
||||
project.id, node.id),
|
||||
{"x": 10, "y": 5, "z": 0},
|
||||
example=True)
|
||||
response = await controller_api.post("/projects/{}/nodes/{}/duplicate".format(project.id, node.id),
|
||||
{"x": 10,
|
||||
"y": 5,
|
||||
"z": 0})
|
||||
assert response.status == 201, response.body.decode()
|
||||
|
||||
|
||||
def test_delete_node(http_controller, tmpdir, project, compute, node):
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock()
|
||||
async def test_delete_node(controller_api, project, node, compute):
|
||||
|
||||
response = http_controller.delete("/projects/{}/nodes/{}".format(project.id, node.id), example=True)
|
||||
compute.post = AsyncioMagicMock()
|
||||
response = await controller_api.delete("/projects/{}/nodes/{}".format(project.id, node.id))
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_dynamips_idle_pc(http_controller, tmpdir, project, compute, node):
|
||||
async def test_dynamips_idle_pc(controller_api, project, compute, node):
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"idlepc": "0x60606f54"}
|
||||
compute.get = AsyncioMagicMock(return_value=response)
|
||||
|
||||
response = http_controller.get("/projects/{}/nodes/{}/dynamips/auto_idlepc".format(project.id, node.id), example=True)
|
||||
response = await controller_api.get("/projects/{}/nodes/{}/dynamips/auto_idlepc".format(project.id, node.id))
|
||||
assert response.status == 200
|
||||
assert response.json["idlepc"] == "0x60606f54"
|
||||
|
||||
|
||||
def test_dynamips_idlepc_proposals(http_controller, tmpdir, project, compute, node):
|
||||
async def test_dynamips_idlepc_proposals(controller_api, project, compute, node):
|
||||
|
||||
response = MagicMock()
|
||||
response.json = ["0x60606f54", "0x33805a22"]
|
||||
compute.get = AsyncioMagicMock(return_value=response)
|
||||
|
||||
response = http_controller.get("/projects/{}/nodes/{}/dynamips/idlepc_proposals".format(project.id, node.id), example=True)
|
||||
response = await controller_api.get("/projects/{}/nodes/{}/dynamips/idlepc_proposals".format(project.id, node.id))
|
||||
assert response.status == 200
|
||||
assert response.json == ["0x60606f54", "0x33805a22"]
|
||||
|
||||
|
||||
def test_get_file(http_controller, tmpdir, project, node, compute):
|
||||
async def test_get_file(controller_api, project, node, compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.body = b"world"
|
||||
compute.http_query = AsyncioMagicMock(return_value=response)
|
||||
response = http_controller.get("/projects/{project_id}/nodes/{node_id}/files/hello".format(project_id=project.id, node_id=node.id), raw=True)
|
||||
|
||||
response = await controller_api.get("/projects/{project_id}/nodes/{node_id}/files/hello".format(project_id=project.id, node_id=node.id))
|
||||
assert response.status == 200
|
||||
assert response.body == b'world'
|
||||
|
||||
compute.http_query.assert_called_with("GET", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello".format(project_id=project.id, node_id=node.id), timeout=None, raw=True)
|
||||
|
||||
response = http_controller.get("/projects/{project_id}/nodes/{node_id}/files/../hello".format(project_id=project.id, node_id=node.id), raw=True)
|
||||
response = await controller_api.get("/projects/{project_id}/nodes/{node_id}/files/../hello".format(project_id=project.id, node_id=node.id))
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_post_file(http_controller, tmpdir, project, node, compute):
|
||||
async def test_post_file(controller_api, project, node, compute):
|
||||
|
||||
compute.http_query = AsyncioMagicMock()
|
||||
response = http_controller.post("/projects/{project_id}/nodes/{node_id}/files/hello".format(project_id=project.id, node_id=node.id), body=b"hello", raw=True)
|
||||
response = await controller_api.post("/projects/{project_id}/nodes/{node_id}/files/hello".format(project_id=project.id, node_id=node.id), body=b"hello", raw=True)
|
||||
assert response.status == 201
|
||||
|
||||
compute.http_query.assert_called_with("POST", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello".format(project_id=project.id, node_id=node.id), data=b'hello', timeout=None, raw=True)
|
||||
|
||||
response = http_controller.get("/projects/{project_id}/nodes/{node_id}/files/../hello".format(project_id=project.id, node_id=node.id), raw=True)
|
||||
response = await controller_api.get("/projects/{project_id}/nodes/{node_id}/files/../hello".format(project_id=project.id, node_id=node.id))
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_get_and_post_with_nested_paths_normalization(http_controller, tmpdir, project, node, compute):
|
||||
async def test_get_and_post_with_nested_paths_normalization(controller_api, project, node, compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.body = b"world"
|
||||
compute.http_query = AsyncioMagicMock(return_value=response)
|
||||
response = http_controller.get("/projects/{project_id}/nodes/{node_id}/files/hello\\nested".format(project_id=project.id, node_id=node.id), raw=True)
|
||||
response = await controller_api.get("/projects/{project_id}/nodes/{node_id}/files/hello\\nested".format(project_id=project.id, node_id=node.id))
|
||||
assert response.status == 200
|
||||
assert response.body == b'world'
|
||||
|
||||
compute.http_query.assert_called_with("GET", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello/nested".format(project_id=project.id, node_id=node.id), timeout=None, raw=True)
|
||||
|
||||
compute.http_query = AsyncioMagicMock()
|
||||
response = http_controller.post("/projects/{project_id}/nodes/{node_id}/files/hello\\nested".format(project_id=project.id, node_id=node.id), body=b"hello", raw=True)
|
||||
response = await controller_api.post("/projects/{project_id}/nodes/{node_id}/files/hello\\nested".format(project_id=project.id, node_id=node.id), body=b"hello", raw=True)
|
||||
assert response.status == 201
|
||||
|
||||
compute.http_query.assert_called_with("POST", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello/nested".format(project_id=project.id, node_id=node.id), data=b'hello', timeout=None, raw=True)
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,202 +15,206 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This test suite check /project endpoint
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import os
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import pytest
|
||||
import zipfile
|
||||
import json
|
||||
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.handlers.api.controller.project_handler import ProjectHandler
|
||||
from gns3server.controller import Controller
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(http_controller, controller):
|
||||
async def project(controller_api, controller):
|
||||
|
||||
u = str(uuid.uuid4())
|
||||
query = {"name": "test", "project_id": u}
|
||||
response = http_controller.post("/projects", query)
|
||||
params = {"name": "test", "project_id": u}
|
||||
await controller_api.post("/projects", params)
|
||||
return controller.get_project(u)
|
||||
|
||||
|
||||
def test_create_project_with_path(http_controller, tmpdir):
|
||||
response = http_controller.post("/projects", {"name": "test", "path": str(tmpdir), "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"})
|
||||
async def test_create_project_with_path(controller_api, tmpdir):
|
||||
|
||||
response = await controller_api.post("/projects", {"name": "test", "path": str(tmpdir), "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"})
|
||||
assert response.status == 201
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["status"] == "opened"
|
||||
|
||||
|
||||
def test_create_project_without_dir(http_controller):
|
||||
query = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = http_controller.post("/projects", query, example=True)
|
||||
async def test_create_project_without_dir(controller_api):
|
||||
|
||||
params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = await controller_api.post("/projects", params)
|
||||
assert response.status == 201
|
||||
assert response.json["project_id"] == "10010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["name"] == "test"
|
||||
|
||||
|
||||
def test_create_project_with_uuid(http_controller):
|
||||
query = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = http_controller.post("/projects", query)
|
||||
async def test_create_project_with_uuid(controller_api):
|
||||
|
||||
params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = await controller_api.post("/projects", params)
|
||||
assert response.status == 201
|
||||
assert response.json["project_id"] == "30010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["name"] == "test"
|
||||
|
||||
|
||||
def test_create_project_with_variables(http_controller):
|
||||
async def test_create_project_with_variables(controller_api):
|
||||
|
||||
variables = [
|
||||
{"name": "TEST1"},
|
||||
{"name": "TEST2", "value": "value1"}
|
||||
]
|
||||
query = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f", "variables": variables}
|
||||
response = http_controller.post("/projects", query)
|
||||
params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f", "variables": variables}
|
||||
response = await controller_api.post("/projects", params)
|
||||
assert response.status == 201
|
||||
assert response.json["variables"] == [
|
||||
assert response.json["variables"] == [
|
||||
{"name": "TEST1"},
|
||||
{"name": "TEST2", "value": "value1"}
|
||||
]
|
||||
|
||||
|
||||
def test_create_project_with_supplier(http_controller):
|
||||
async def test_create_project_with_supplier(controller_api):
|
||||
|
||||
supplier = {
|
||||
'logo': 'logo.png',
|
||||
'url': 'http://example.com'
|
||||
}
|
||||
query = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f", "supplier": supplier}
|
||||
response = http_controller.post("/projects", query)
|
||||
params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f", "supplier": supplier}
|
||||
response = await controller_api.post("/projects", params)
|
||||
assert response.status == 201
|
||||
assert response.json["supplier"] == supplier
|
||||
|
||||
|
||||
def test_update_project(http_controller):
|
||||
query = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = http_controller.post("/projects", query)
|
||||
async def test_update_project(controller_api):
|
||||
|
||||
params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
|
||||
response = await controller_api.post("/projects", params)
|
||||
assert response.status == 201
|
||||
assert response.json["project_id"] == "10010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["name"] == "test"
|
||||
query = {"name": "test2"}
|
||||
response = http_controller.put("/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", query, example=True)
|
||||
|
||||
params = {"name": "test2"}
|
||||
response = await controller_api.put("/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", params)
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test2"
|
||||
|
||||
|
||||
def test_update_project_with_variables(http_controller):
|
||||
async def test_update_project_with_variables(controller_api):
|
||||
|
||||
variables = [
|
||||
{"name": "TEST1"},
|
||||
{"name": "TEST2", "value": "value1"}
|
||||
]
|
||||
query = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f", "variables": variables}
|
||||
response = http_controller.post("/projects", query)
|
||||
params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f", "variables": variables}
|
||||
response = await controller_api.post("/projects", params)
|
||||
assert response.status == 201
|
||||
query = {"name": "test2"}
|
||||
response = http_controller.put("/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", query, example=True)
|
||||
|
||||
params = {"name": "test2"}
|
||||
response = await controller_api.put("/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", params)
|
||||
assert response.status == 200
|
||||
assert response.json["variables"] == variables
|
||||
|
||||
|
||||
def test_list_projects(http_controller, tmpdir):
|
||||
http_controller.post("/projects", {"name": "test", "path": str(tmpdir), "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"})
|
||||
response = http_controller.get("/projects", example=True)
|
||||
async def test_list_projects(controller_api, tmpdir):
|
||||
|
||||
await controller_api.post("/projects", {"name": "test", "path": str(tmpdir), "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"})
|
||||
response = await controller_api.get("/projects")
|
||||
assert response.status == 200
|
||||
projects = response.json
|
||||
assert projects[0]["name"] == "test"
|
||||
|
||||
|
||||
def test_get_project(http_controller, project):
|
||||
response = http_controller.get("/projects/{project_id}".format(project_id=project.id), example=True)
|
||||
async def test_get_project(controller_api, project):
|
||||
|
||||
response = await controller_api.get("/projects/{project_id}".format(project_id=project.id))
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
|
||||
|
||||
def test_delete_project(http_controller, project):
|
||||
async def test_delete_project(controller_api, project, controller):
|
||||
|
||||
with asyncio_patch("gns3server.controller.project.Project.delete", return_value=True) as mock:
|
||||
response = http_controller.delete("/projects/{project_id}".format(project_id=project.id), example=True)
|
||||
response = await controller_api.delete("/projects/{project_id}".format(project_id=project.id))
|
||||
assert response.status == 204
|
||||
assert mock.called
|
||||
assert project not in Controller.instance().projects
|
||||
assert project not in controller.projects
|
||||
|
||||
|
||||
def test_delete_project_invalid_uuid(http_controller):
|
||||
response = http_controller.delete("/projects/{project_id}".format(project_id=uuid.uuid4()))
|
||||
async def test_delete_project_invalid_uuid(controller_api):
|
||||
|
||||
response = await controller_api.delete("/projects/{project_id}".format(project_id=uuid.uuid4()))
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_close_project(http_controller, project):
|
||||
async def test_close_project(controller_api, project):
|
||||
|
||||
with asyncio_patch("gns3server.controller.project.Project.close", return_value=True) as mock:
|
||||
response = http_controller.post("/projects/{project_id}/close".format(project_id=project.id), example=True)
|
||||
response = await controller_api.post("/projects/{project_id}/close".format(project_id=project.id))
|
||||
assert response.status == 204
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_open_project(http_controller, project):
|
||||
async def test_open_project(controller_api, project):
|
||||
|
||||
with asyncio_patch("gns3server.controller.project.Project.open", return_value=True) as mock:
|
||||
response = http_controller.post("/projects/{project_id}/open".format(project_id=project.id), example=True)
|
||||
response = await controller_api.post("/projects/{project_id}/open".format(project_id=project.id))
|
||||
assert response.status == 201
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_load_project(http_controller, project, config):
|
||||
async def test_load_project(controller_api, project, config):
|
||||
|
||||
config.set("Server", "local", "true")
|
||||
with asyncio_patch("gns3server.controller.Controller.load_project", return_value=project) as mock:
|
||||
response = http_controller.post("/projects/load".format(project_id=project.id), {"path": "/tmp/test.gns3"}, example=True)
|
||||
response = await controller_api.post("/projects/load".format(project_id=project.id), {"path": "/tmp/test.gns3"})
|
||||
assert response.status == 201
|
||||
mock.assert_called_with("/tmp/test.gns3")
|
||||
assert response.json["project_id"] == project.id
|
||||
|
||||
|
||||
def test_notification(http_controller, project, controller, loop, async_run):
|
||||
async def test_notification(controller_api, http_client, project, controller):
|
||||
|
||||
async def go():
|
||||
connector = aiohttp.TCPConnector()
|
||||
async with aiohttp.request("GET", http_controller.get_url("/projects/{project_id}/notifications".format(project_id=project.id)), connector=connector) as response:
|
||||
response.body = await response.content.read(200)
|
||||
controller.notification.project_emit("node.created", {"a": "b"})
|
||||
response.body += await response.content.readany()
|
||||
return response
|
||||
|
||||
response = async_run(asyncio.ensure_future(go()))
|
||||
assert response.status == 200
|
||||
assert b'"action": "ping"' in response.body
|
||||
assert b'"cpu_usage_percent"' in response.body
|
||||
assert b'{"action": "node.created", "event": {"a": "b"}}\n' in response.body
|
||||
assert project.status == "opened"
|
||||
async with http_client.get(controller_api.get_url("/projects/{project_id}/notifications".format(project_id=project.id))) as response:
|
||||
response.body = await response.content.read(200)
|
||||
controller.notification.project_emit("node.created", {"a": "b"})
|
||||
response.body += await response.content.readany()
|
||||
assert response.status == 200
|
||||
assert b'"action": "ping"' in response.body
|
||||
assert b'"cpu_usage_percent"' in response.body
|
||||
assert b'{"action": "node.created", "event": {"a": "b"}}\n' in response.body
|
||||
assert project.status == "opened"
|
||||
|
||||
|
||||
def test_notification_invalid_id(http_controller):
|
||||
response = http_controller.get("/projects/{project_id}/notifications".format(project_id=uuid.uuid4()))
|
||||
async def test_notification_invalid_id(controller_api):
|
||||
|
||||
response = await controller_api.get("/projects/{project_id}/notifications".format(project_id=uuid.uuid4()))
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_notification_ws(http_controller, controller, project, async_run):
|
||||
ws = http_controller.websocket("/projects/{project_id}/notifications/ws".format(project_id=project.id))
|
||||
answer = async_run(ws.receive())
|
||||
async def test_notification_ws(controller_api, http_client, controller, project):
|
||||
|
||||
ws = await http_client.ws_connect(controller_api.get_url("/projects/{project_id}/notifications/ws".format(project_id=project.id)))
|
||||
answer = await ws.receive()
|
||||
answer = json.loads(answer.data)
|
||||
assert answer["action"] == "ping"
|
||||
|
||||
controller.notification.project_emit("test", {})
|
||||
|
||||
answer = async_run(ws.receive())
|
||||
answer = await ws.receive()
|
||||
answer = json.loads(answer.data)
|
||||
assert answer["action"] == "test"
|
||||
|
||||
async_run(http_controller.close())
|
||||
async_run(ws.close())
|
||||
if not ws.closed:
|
||||
await ws.close()
|
||||
|
||||
assert project.status == "opened"
|
||||
|
||||
|
||||
def test_export_with_images(http_controller, tmpdir, loop, project):
|
||||
project.dump = MagicMock()
|
||||
async def test_export_with_images(controller_api, tmpdir, project):
|
||||
|
||||
project.dump = MagicMock()
|
||||
os.makedirs(project.path, exist_ok=True)
|
||||
with open(os.path.join(project.path, 'a'), 'w+') as f:
|
||||
f.write('hello')
|
||||
@ -234,8 +238,8 @@ def test_export_with_images(http_controller, tmpdir, loop, project):
|
||||
with open(os.path.join(project.path, "test.gns3"), 'w+') as f:
|
||||
json.dump(topology, f)
|
||||
|
||||
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
|
||||
response = http_controller.get("/projects/{project_id}/export?include_images=yes".format(project_id=project.id), raw=True)
|
||||
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS")):
|
||||
response = await controller_api.get("/projects/{project_id}/export?include_images=yes".format(project_id=project.id))
|
||||
assert response.status == 200
|
||||
assert response.headers['CONTENT-TYPE'] == 'application/gns3project'
|
||||
assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name)
|
||||
@ -250,9 +254,9 @@ def test_export_with_images(http_controller, tmpdir, loop, project):
|
||||
myzip.getinfo("images/IOS/test.image")
|
||||
|
||||
|
||||
def test_export_without_images(http_controller, tmpdir, loop, project):
|
||||
project.dump = MagicMock()
|
||||
async def test_export_without_images(controller_api, tmpdir, project):
|
||||
|
||||
project.dump = MagicMock()
|
||||
os.makedirs(project.path, exist_ok=True)
|
||||
with open(os.path.join(project.path, 'a'), 'w+') as f:
|
||||
f.write('hello')
|
||||
@ -277,7 +281,7 @@ def test_export_without_images(http_controller, tmpdir, loop, project):
|
||||
json.dump(topology, f)
|
||||
|
||||
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
|
||||
response = http_controller.get("/projects/{project_id}/export?include_images=0".format(project_id=project.id), raw=True)
|
||||
response = await controller_api.get("/projects/{project_id}/export?include_images=0".format(project_id=project.id))
|
||||
assert response.status == 200
|
||||
assert response.headers['CONTENT-TYPE'] == 'application/gns3project'
|
||||
assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name)
|
||||
@ -294,52 +298,54 @@ def test_export_without_images(http_controller, tmpdir, loop, project):
|
||||
myzip.getinfo("images/IOS/test.image")
|
||||
|
||||
|
||||
def test_get_file(http_controller, tmpdir, loop, project):
|
||||
async def test_get_file(controller_api, project):
|
||||
|
||||
os.makedirs(project.path, exist_ok=True)
|
||||
with open(os.path.join(project.path, 'hello'), 'w+') as f:
|
||||
f.write('world')
|
||||
|
||||
response = http_controller.get("/projects/{project_id}/files/hello".format(project_id=project.id), raw=True)
|
||||
response = await controller_api.get("/projects/{project_id}/files/hello".format(project_id=project.id))
|
||||
assert response.status == 200
|
||||
assert response.body == b"world"
|
||||
|
||||
response = http_controller.get("/projects/{project_id}/files/false".format(project_id=project.id), raw=True)
|
||||
response = await controller_api.get("/projects/{project_id}/files/false".format(project_id=project.id))
|
||||
assert response.status == 404
|
||||
|
||||
response = http_controller.get("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
response = await controller_api.get("/projects/{project_id}/files/../hello".format(project_id=project.id))
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_write_file(http_controller, tmpdir, project):
|
||||
response = http_controller.post("/projects/{project_id}/files/hello".format(project_id=project.id), body="world", raw=True)
|
||||
async def test_write_file(controller_api, project):
|
||||
|
||||
response = await controller_api.post("/projects/{project_id}/files/hello".format(project_id=project.id), body="world", raw=True)
|
||||
assert response.status == 200
|
||||
|
||||
with open(os.path.join(project.path, "hello")) as f:
|
||||
assert f.read() == "world"
|
||||
|
||||
response = http_controller.post("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
response = await controller_api.post("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
|
||||
assert response.status == 404
|
||||
|
||||
|
||||
def test_write_and_get_file_with_leading_slashes_in_filename(http_controller, tmpdir, loop, project):
|
||||
response = http_controller.post("/projects/{project_id}/files//hello".format(project_id=project.id), body="world", raw=True)
|
||||
async def test_write_and_get_file_with_leading_slashes_in_filename(controller_api, project):
|
||||
|
||||
response = await controller_api.post("/projects/{project_id}/files//hello".format(project_id=project.id), body="world", raw=True)
|
||||
assert response.status == 200
|
||||
|
||||
response = http_controller.get("/projects/{project_id}/files//hello".format(project_id=project.id), raw=True)
|
||||
response = await controller_api.get("/projects/{project_id}/files//hello".format(project_id=project.id), raw=True)
|
||||
assert response.status == 200
|
||||
assert response.body == b"world"
|
||||
|
||||
|
||||
def test_import(http_controller, tmpdir, controller):
|
||||
async def test_import(controller_api, tmpdir, controller):
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / "test.zip"), 'w') as myzip:
|
||||
myzip.writestr("project.gns3", b'{"project_id": "c6992992-ac72-47dc-833b-54aa334bcd05", "version": "2.0.0", "name": "test"}')
|
||||
myzip.writestr("demo", b"hello")
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
with open(str(tmpdir / "test.zip"), "rb") as f:
|
||||
response = http_controller.post("/projects/{project_id}/import".format(project_id=project_id), body=f.read(), raw=True)
|
||||
response = await controller_api.post("/projects/{project_id}/import".format(project_id=project_id), body=f.read(), raw=True)
|
||||
assert response.status == 201
|
||||
|
||||
project = controller.get_project(project_id)
|
||||
@ -348,8 +354,8 @@ def test_import(http_controller, tmpdir, controller):
|
||||
assert content == "hello"
|
||||
|
||||
|
||||
def test_duplicate(http_controller, tmpdir, loop, project):
|
||||
async def test_duplicate(controller_api, project):
|
||||
|
||||
response = http_controller.post("/projects/{project_id}/duplicate".format(project_id=project.id), {"name": "hello"}, example=True)
|
||||
response = await controller_api.post("/projects/{project_id}/duplicate".format(project_id=project.id), {"name": "hello"})
|
||||
assert response.status == 201
|
||||
assert response.json["name"] == "hello"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,61 +17,60 @@
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import asyncio
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import MagicMock
|
||||
from gns3server.web.web_server import WebServer
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
@pytest.fixture
|
||||
def web_server():
|
||||
|
||||
WebServer._instance = MagicMock()
|
||||
yield WebServer._instance
|
||||
WebServer._instance = None
|
||||
|
||||
|
||||
def test_shutdown_local(http_controller, web_server, config):
|
||||
async def test_shutdown_local(controller_api, web_server, config):
|
||||
|
||||
async def hello():
|
||||
return 0
|
||||
|
||||
web_server.shutdown_server.return_value = hello()
|
||||
config.set("Server", "local", True)
|
||||
response = http_controller.post('/shutdown', example=True)
|
||||
response = await controller_api.post('/shutdown')
|
||||
assert response.status == 201
|
||||
assert web_server.shutdown_server.called
|
||||
|
||||
|
||||
def test_shutdown_non_local(http_controller, web_server, config):
|
||||
"""
|
||||
Disallow shutdown of a non local GNS3 server
|
||||
"""
|
||||
async def test_shutdown_non_local(controller_api, web_server, config):
|
||||
|
||||
WebServer._instance = MagicMock()
|
||||
config.set("Server", "local", False)
|
||||
response = http_controller.post('/shutdown')
|
||||
response = await controller_api.post('/shutdown')
|
||||
assert response.status == 403
|
||||
assert not web_server.shutdown_server.called
|
||||
|
||||
|
||||
def test_debug(http_controller, config, tmpdir):
|
||||
config._main_config_file = str(tmpdir / "test.conf")
|
||||
async def test_debug(controller_api, config, tmpdir):
|
||||
|
||||
config._main_config_file = str(tmpdir / "test.conf")
|
||||
config.set("Server", "local", True)
|
||||
response = http_controller.post('/debug')
|
||||
response = await controller_api.post('/debug')
|
||||
assert response.status == 201
|
||||
debug_dir = os.path.join(config.config_dir, "debug")
|
||||
assert os.path.exists(debug_dir)
|
||||
assert os.path.exists(os.path.join(debug_dir, "controller.txt"))
|
||||
|
||||
|
||||
def test_debug_non_local(http_controller, config, tmpdir):
|
||||
config._main_config_file = str(tmpdir / "test.conf")
|
||||
async def test_debug_non_local(controller_api, config, tmpdir):
|
||||
|
||||
config._main_config_file = str(tmpdir / "test.conf")
|
||||
config.set("Server", "local", False)
|
||||
response = http_controller.post('/debug')
|
||||
response = await controller_api.post('/debug')
|
||||
assert response.status == 403
|
||||
|
||||
|
||||
def test_statistics_output(http_controller):
|
||||
response = http_controller.get('/statistics')
|
||||
async def test_statistics_output(controller_api):
|
||||
|
||||
response = await controller_api.get('/statistics')
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -21,40 +21,46 @@ import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(http_controller, controller):
|
||||
u = str(uuid.uuid4())
|
||||
query = {"name": "test", "project_id": u}
|
||||
response = http_controller.post("/projects", query)
|
||||
project = controller.get_project(u)
|
||||
async def project(controller_api, controller):
|
||||
|
||||
u = str(uuid.uuid4())
|
||||
params = {"name": "test", "project_id": u}
|
||||
await controller_api.post("/projects", params)
|
||||
project = controller.get_project(u)
|
||||
return project
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def snapshot(project, async_run):
|
||||
snapshot = async_run(project.snapshot("test"))
|
||||
async def snapshot(project):
|
||||
|
||||
snapshot = await project.snapshot("test")
|
||||
return snapshot
|
||||
|
||||
|
||||
def test_list_snapshots(http_controller, project, snapshot):
|
||||
response = http_controller.get("/projects/{}/snapshots".format(project.id), example=True)
|
||||
async def test_list_snapshots(controller_api, project, snapshot):
|
||||
|
||||
assert snapshot.name == "test"
|
||||
response = await controller_api.get("/projects/{}/snapshots".format(project.id))
|
||||
assert response.status == 200
|
||||
assert len(response.json) == 1
|
||||
|
||||
|
||||
def test_delete_snapshot(http_controller, project, snapshot):
|
||||
response = http_controller.delete("/projects/{}/snapshots/{}".format(project.id, snapshot.id), example=True)
|
||||
async def test_delete_snapshot(controller_api, project, snapshot):
|
||||
|
||||
response = await controller_api.delete("/projects/{}/snapshots/{}".format(project.id, snapshot.id))
|
||||
assert response.status == 204
|
||||
assert not os.path.exists(snapshot.path)
|
||||
|
||||
|
||||
def test_restore_snapshot(http_controller, project, snapshot):
|
||||
response = http_controller.post("/projects/{}/snapshots/{}/restore".format(project.id, snapshot.id), example=True)
|
||||
async def test_restore_snapshot(controller_api, project, snapshot):
|
||||
|
||||
response = await controller_api.post("/projects/{}/snapshots/{}/restore".format(project.id, snapshot.id))
|
||||
assert response.status == 201
|
||||
assert response.json["name"] == project.name
|
||||
|
||||
|
||||
def test_create_snapshot(http_controller, project):
|
||||
response = http_controller.post("/projects/{}/snapshots".format(project.id), {"name": "snap1"}, example=True)
|
||||
async def test_create_snapshot(controller_api, project):
|
||||
|
||||
response = await controller_api.post("/projects/{}/snapshots".format(project.id), {"name": "snap1"})
|
||||
assert response.status == 201
|
||||
assert len(os.listdir(os.path.join(project.path, "snapshots"))) == 1
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,14 +16,13 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import urllib.parse
|
||||
|
||||
from gns3server.config import Config
|
||||
|
||||
async def test_symbols(controller_api):
|
||||
|
||||
response = await controller_api.get('/symbols')
|
||||
|
||||
def test_symbols(http_controller):
|
||||
response = http_controller.get('/symbols', example=True)
|
||||
assert response.status == 200
|
||||
assert {
|
||||
'symbol_id': ':/symbols/classic/firewall.svg',
|
||||
@ -33,25 +32,27 @@ def test_symbols(http_controller):
|
||||
} in response.json
|
||||
|
||||
|
||||
def test_get(http_controller, controller):
|
||||
async def test_get(controller_api, controller):
|
||||
|
||||
controller.symbols.theme = "Classic"
|
||||
response = http_controller.get('/symbols/' + urllib.parse.quote(':/symbols/classic/firewall.svg') + '/raw')
|
||||
response = await controller_api.get('/symbols/' + urllib.parse.quote(':/symbols/classic/firewall.svg') + '/raw')
|
||||
assert response.status == 200
|
||||
assert response.headers['CONTENT-TYPE'] == 'image/svg+xml'
|
||||
assert response.headers['CONTENT-LENGTH'] == '9381'
|
||||
assert '</svg>' in response.html
|
||||
|
||||
# Reply by the default symbol
|
||||
response = http_controller.get('/symbols/404.png/raw')
|
||||
# Reply with the default symbol
|
||||
response = await controller_api.get('/symbols/404.png/raw')
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_upload(http_controller, symbols_dir):
|
||||
response = http_controller.post("/symbols/test2/raw", body="TEST", raw=True)
|
||||
async def test_upload(controller_api, symbols_dir):
|
||||
|
||||
response = await controller_api.post("/symbols/test2/raw", body="TEST", raw=True)
|
||||
assert response.status == 204
|
||||
|
||||
with open(os.path.join(symbols_dir, "test2")) as f:
|
||||
assert f.read() == "TEST"
|
||||
|
||||
response = http_controller.get('/symbols/test2/raw')
|
||||
response = await controller_api.get('/symbols/test2/raw')
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,15 +17,13 @@
|
||||
|
||||
|
||||
import uuid
|
||||
import pytest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.controller.template import Template
|
||||
|
||||
|
||||
def test_template_list(http_controller, controller):
|
||||
async def test_template_list(controller_api, controller):
|
||||
|
||||
id = str(uuid.uuid4())
|
||||
controller.template_manager.load_templates()
|
||||
@ -37,13 +35,13 @@ def test_template_list(http_controller, controller):
|
||||
"default_name_format": "{name}-{0}",
|
||||
"compute_id": "local"
|
||||
})
|
||||
response = http_controller.get("/templates", example=True)
|
||||
response = await controller_api.get("/templates")
|
||||
assert response.status == 200
|
||||
assert response.route == "/templates"
|
||||
assert len(response.json) > 0
|
||||
|
||||
|
||||
def test_template_create_without_id(http_controller, controller):
|
||||
async def test_template_create_without_id(controller_api, controller):
|
||||
|
||||
params = {"base_script_file": "vpcs_base_config.txt",
|
||||
"category": "guest",
|
||||
@ -55,14 +53,14 @@ def test_template_create_without_id(http_controller, controller):
|
||||
"symbol": ":/symbols/vpcs_guest.svg",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
response = http_controller.post("/templates", params, example=True)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/templates"
|
||||
assert response.json["template_id"] is not None
|
||||
assert len(controller.template_manager._templates) == 1
|
||||
assert len(controller.template_manager.templates) == 1
|
||||
|
||||
|
||||
def test_template_create_with_id(http_controller, controller):
|
||||
async def test_template_create_with_id(controller_api, controller):
|
||||
|
||||
params = {"template_id": str(uuid.uuid4()),
|
||||
"base_script_file": "vpcs_base_config.txt",
|
||||
@ -75,14 +73,14 @@ def test_template_create_with_id(http_controller, controller):
|
||||
"symbol": ":/symbols/vpcs_guest.svg",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
response = http_controller.post("/templates", params, example=True)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.route == "/templates"
|
||||
assert response.json["template_id"] is not None
|
||||
assert len(controller.template_manager._templates) == 1
|
||||
assert len(controller.template_manager.templates) == 1
|
||||
|
||||
|
||||
def test_template_create_wrong_type(http_controller, controller):
|
||||
async def test_template_create_wrong_type(controller_api, controller):
|
||||
|
||||
params = {"template_id": str(uuid.uuid4()),
|
||||
"base_script_file": "vpcs_base_config.txt",
|
||||
@ -95,12 +93,12 @@ def test_template_create_wrong_type(http_controller, controller):
|
||||
"symbol": ":/symbols/vpcs_guest.svg",
|
||||
"template_type": "invalid_template_type"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 400
|
||||
assert len(controller.template_manager._templates) == 0
|
||||
assert len(controller.template_manager.templates) == 0
|
||||
|
||||
|
||||
def test_template_get(http_controller, controller):
|
||||
async def test_template_get(controller_api):
|
||||
|
||||
template_id = str(uuid.uuid4())
|
||||
params = {"template_id": template_id,
|
||||
@ -114,15 +112,15 @@ def test_template_get(http_controller, controller):
|
||||
"symbol": ":/symbols/vpcs_guest.svg",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_controller.get("/templates/{}".format(template_id), example=True)
|
||||
response = await controller_api.get("/templates/{}".format(template_id))
|
||||
assert response.status == 200
|
||||
assert response.json["template_id"] == template_id
|
||||
|
||||
|
||||
def test_template_update(http_controller, controller):
|
||||
async def test_template_update(controller_api):
|
||||
|
||||
template_id = str(uuid.uuid4())
|
||||
params = {"template_id": template_id,
|
||||
@ -136,21 +134,21 @@ def test_template_update(http_controller, controller):
|
||||
"symbol": ":/symbols/vpcs_guest.svg",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_controller.get("/templates/{}".format(template_id))
|
||||
response = await controller_api.get("/templates/{}".format(template_id))
|
||||
assert response.status == 200
|
||||
assert response.json["template_id"] == template_id
|
||||
|
||||
params["name"] = "VPCS_TEST_RENAMED"
|
||||
response = http_controller.put("/templates/{}".format(template_id), params, example=True)
|
||||
response = await controller_api.put("/templates/{}".format(template_id), params)
|
||||
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "VPCS_TEST_RENAMED"
|
||||
|
||||
|
||||
def test_template_delete(http_controller, controller):
|
||||
async def test_template_delete(controller_api, controller):
|
||||
|
||||
template_id = str(uuid.uuid4())
|
||||
params = {"template_id": template_id,
|
||||
@ -164,22 +162,22 @@ def test_template_delete(http_controller, controller):
|
||||
"symbol": ":/symbols/vpcs_guest.svg",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_controller.get("/templates")
|
||||
response = await controller_api.get("/templates")
|
||||
assert len(response.json) == 1
|
||||
assert len(controller.template_manager._templates) == 1
|
||||
|
||||
response = http_controller.delete("/templates/{}".format(template_id), example=True)
|
||||
response = await controller_api.delete("/templates/{}".format(template_id))
|
||||
assert response.status == 204
|
||||
|
||||
response = http_controller.get("/templates")
|
||||
response = await controller_api.get("/templates")
|
||||
assert len(response.json) == 0
|
||||
assert len(controller.template_manager._templates) == 0
|
||||
assert len(controller.template_manager.templates) == 0
|
||||
|
||||
|
||||
def test_template_duplicate(http_controller, controller):
|
||||
async def test_template_duplicate(controller_api, controller):
|
||||
|
||||
template_id = str(uuid.uuid4())
|
||||
params = {"template_id": template_id,
|
||||
@ -193,22 +191,22 @@ def test_template_duplicate(http_controller, controller):
|
||||
"symbol": ":/symbols/vpcs_guest.svg",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
|
||||
response = http_controller.post("/templates/{}/duplicate".format(template_id), example=True)
|
||||
response = await controller_api.post("/templates/{}/duplicate".format(template_id))
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] != template_id
|
||||
params.pop("template_id")
|
||||
for param, value in params.items():
|
||||
assert response.json[param] == value
|
||||
|
||||
response = http_controller.get("/templates")
|
||||
response = await controller_api.get("/templates")
|
||||
assert len(response.json) == 2
|
||||
assert len(controller.template_manager._templates) == 2
|
||||
assert len(controller.template_manager.templates) == 2
|
||||
|
||||
|
||||
def test_c7200_dynamips_template_create(http_controller):
|
||||
async def test_c7200_dynamips_template_create(controller_api):
|
||||
|
||||
params = {"name": "Cisco c7200 template",
|
||||
"platform": "c7200",
|
||||
@ -216,7 +214,7 @@ def test_c7200_dynamips_template_create(http_controller):
|
||||
"image": "c7200-adventerprisek9-mz.124-24.T5.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -253,7 +251,7 @@ def test_c7200_dynamips_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_c3745_dynamips_template_create(http_controller):
|
||||
async def test_c3745_dynamips_template_create(controller_api):
|
||||
|
||||
params = {"name": "Cisco c3745 template",
|
||||
"platform": "c3745",
|
||||
@ -261,7 +259,7 @@ def test_c3745_dynamips_template_create(http_controller):
|
||||
"image": "c3745-adventerprisek9-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -297,7 +295,7 @@ def test_c3745_dynamips_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_c3725_dynamips_template_create(http_controller):
|
||||
async def test_c3725_dynamips_template_create(controller_api):
|
||||
|
||||
params = {"name": "Cisco c3725 template",
|
||||
"platform": "c3725",
|
||||
@ -305,7 +303,7 @@ def test_c3725_dynamips_template_create(http_controller):
|
||||
"image": "c3725-adventerprisek9-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -341,7 +339,7 @@ def test_c3725_dynamips_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_c3600_dynamips_template_create(http_controller):
|
||||
async def test_c3600_dynamips_template_create(controller_api):
|
||||
|
||||
params = {"name": "Cisco c3600 template",
|
||||
"platform": "c3600",
|
||||
@ -350,7 +348,7 @@ def test_c3600_dynamips_template_create(http_controller):
|
||||
"image": "c3660-a3jk9s-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -387,7 +385,7 @@ def test_c3600_dynamips_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_c3600_dynamips_template_create_wrong_chassis(http_controller):
|
||||
async def test_c3600_dynamips_template_create_wrong_chassis(controller_api):
|
||||
|
||||
params = {"name": "Cisco c3600 template",
|
||||
"platform": "c3600",
|
||||
@ -396,11 +394,11 @@ def test_c3600_dynamips_template_create_wrong_chassis(http_controller):
|
||||
"image": "c3660-a3jk9s-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 400
|
||||
|
||||
|
||||
def test_c2691_dynamips_template_create(http_controller):
|
||||
async def test_c2691_dynamips_template_create(controller_api):
|
||||
|
||||
params = {"name": "Cisco c2691 template",
|
||||
"platform": "c2691",
|
||||
@ -408,7 +406,7 @@ def test_c2691_dynamips_template_create(http_controller):
|
||||
"image": "c2691-adventerprisek9-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -444,7 +442,7 @@ def test_c2691_dynamips_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_c2600_dynamips_template_create(http_controller):
|
||||
async def test_c2600_dynamips_template_create(controller_api):
|
||||
|
||||
params = {"name": "Cisco c2600 template",
|
||||
"platform": "c2600",
|
||||
@ -453,7 +451,7 @@ def test_c2600_dynamips_template_create(http_controller):
|
||||
"image": "c2600-adventerprisek9-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -490,7 +488,7 @@ def test_c2600_dynamips_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_c2600_dynamips_template_create_wrong_chassis(http_controller):
|
||||
async def test_c2600_dynamips_template_create_wrong_chassis(controller_api):
|
||||
|
||||
params = {"name": "Cisco c2600 template",
|
||||
"platform": "c2600",
|
||||
@ -499,11 +497,11 @@ def test_c2600_dynamips_template_create_wrong_chassis(http_controller):
|
||||
"image": "c2600-adventerprisek9-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 400
|
||||
|
||||
|
||||
def test_c1700_dynamips_template_create(http_controller):
|
||||
async def test_c1700_dynamips_template_create(controller_api):
|
||||
|
||||
params = {"name": "Cisco c1700 template",
|
||||
"platform": "c1700",
|
||||
@ -512,7 +510,7 @@ def test_c1700_dynamips_template_create(http_controller):
|
||||
"image": "c1700-adventerprisek9-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -549,7 +547,7 @@ def test_c1700_dynamips_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_c1700_dynamips_template_create_wrong_chassis(http_controller):
|
||||
async def test_c1700_dynamips_template_create_wrong_chassis(controller_api):
|
||||
|
||||
params = {"name": "Cisco c1700 template",
|
||||
"platform": "c1700",
|
||||
@ -558,11 +556,11 @@ def test_c1700_dynamips_template_create_wrong_chassis(http_controller):
|
||||
"image": "c1700-adventerprisek9-mz.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 400
|
||||
|
||||
|
||||
def test_dynamips_template_create_wrong_platform(http_controller):
|
||||
async def test_dynamips_template_create_wrong_platform(controller_api):
|
||||
|
||||
params = {"name": "Cisco c3900 template",
|
||||
"platform": "c3900",
|
||||
@ -570,18 +568,18 @@ def test_dynamips_template_create_wrong_platform(http_controller):
|
||||
"image": "c3900-test.124-25d.image",
|
||||
"template_type": "dynamips"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 400
|
||||
|
||||
|
||||
def test_iou_template_create(http_controller):
|
||||
async def test_iou_template_create(controller_api):
|
||||
|
||||
params = {"name": "IOU template",
|
||||
"compute_id": "local",
|
||||
"path": "/path/to/i86bi_linux-ipbase-ms-12.4.bin",
|
||||
"template_type": "iou"}
|
||||
|
||||
response = http_controller.post("/templates", params, example=True)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -608,14 +606,14 @@ def test_iou_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_docker_template_create(http_controller):
|
||||
async def test_docker_template_create(controller_api):
|
||||
|
||||
params = {"name": "Docker template",
|
||||
"compute_id": "local",
|
||||
"image": "gns3/endhost:latest",
|
||||
"template_type": "docker"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -642,7 +640,7 @@ def test_docker_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_qemu_template_create(http_controller):
|
||||
async def test_qemu_template_create(controller_api):
|
||||
|
||||
params = {"name": "Qemu template",
|
||||
"compute_id": "local",
|
||||
@ -651,7 +649,7 @@ def test_qemu_template_create(http_controller):
|
||||
"ram": 512,
|
||||
"template_type": "qemu"}
|
||||
|
||||
response = http_controller.post("/templates", params, example=True)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -701,14 +699,14 @@ def test_qemu_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_vmware_template_create(http_controller):
|
||||
async def test_vmware_template_create(controller_api):
|
||||
|
||||
params = {"name": "VMware template",
|
||||
"compute_id": "local",
|
||||
"template_type": "vmware",
|
||||
"vmx_path": "/path/to/vm.vmx"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -737,14 +735,14 @@ def test_vmware_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_virtualbox_template_create(http_controller):
|
||||
async def test_virtualbox_template_create(controller_api):
|
||||
|
||||
params = {"name": "VirtualBox template",
|
||||
"compute_id": "local",
|
||||
"template_type": "virtualbox",
|
||||
"vmname": "My VirtualBox VM"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -773,13 +771,14 @@ def test_virtualbox_template_create(http_controller):
|
||||
for item, value in expected_response.items():
|
||||
assert response.json.get(item) == value
|
||||
|
||||
def test_vpcs_template_create(http_controller):
|
||||
|
||||
async def test_vpcs_template_create(controller_api):
|
||||
|
||||
params = {"name": "VPCS template",
|
||||
"compute_id": "local",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -797,13 +796,14 @@ def test_vpcs_template_create(http_controller):
|
||||
for item, value in expected_response.items():
|
||||
assert response.json.get(item) == value
|
||||
|
||||
def test_ethernet_switch_template_create(http_controller):
|
||||
|
||||
async def test_ethernet_switch_template_create(controller_api):
|
||||
|
||||
params = {"name": "Ethernet switch template",
|
||||
"compute_id": "local",
|
||||
"template_type": "ethernet_switch"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -868,13 +868,13 @@ def test_ethernet_switch_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_cloud_template_create(http_controller):
|
||||
async def test_cloud_template_create(controller_api):
|
||||
|
||||
params = {"name": "Cloud template",
|
||||
"compute_id": "local",
|
||||
"template_type": "cloud"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -890,13 +890,13 @@ def test_cloud_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
def test_ethernet_hub_template_create(http_controller):
|
||||
async def test_ethernet_hub_template_create(controller_api):
|
||||
|
||||
params = {"name": "Ethernet hub template",
|
||||
"compute_id": "local",
|
||||
"template_type": "ethernet_hub"}
|
||||
|
||||
response = http_controller.post("/templates", params)
|
||||
response = await controller_api.post("/templates", params)
|
||||
assert response.status == 201
|
||||
assert response.json["template_id"] is not None
|
||||
|
||||
@ -936,21 +936,7 @@ def test_ethernet_hub_template_create(http_controller):
|
||||
assert response.json.get(item) == value
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute(http_controller, async_run):
|
||||
compute = MagicMock()
|
||||
compute.id = "example.com"
|
||||
compute.host = "example.org"
|
||||
Controller.instance()._computes = {"example.com": compute}
|
||||
return compute
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(http_controller, async_run):
|
||||
return async_run(Controller.instance().add_project(name="Test"))
|
||||
|
||||
|
||||
def test_create_node_from_template(http_controller, controller, project, compute):
|
||||
async def test_create_node_from_template(controller_api, controller, project):
|
||||
|
||||
id = str(uuid.uuid4())
|
||||
controller.template_manager._templates = {id: Template(id, {
|
||||
@ -962,7 +948,7 @@ def test_create_node_from_template(http_controller, controller, project, compute
|
||||
"compute_id": "example.com"
|
||||
})}
|
||||
with asyncio_patch("gns3server.controller.project.Project.add_node_from_template", return_value={"name": "test", "node_type": "qemu", "compute_id": "example.com"}) as mock:
|
||||
response = http_controller.post("/projects/{}/templates/{}".format(project.id, id), {
|
||||
response = await controller_api.post("/projects/{}/templates/{}".format(project.id, id), {
|
||||
"x": 42,
|
||||
"y": 12
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,48 +15,44 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This test suite check /version endpoint
|
||||
It's also used for unittest the HTTP implementation.
|
||||
"""
|
||||
|
||||
from gns3server.config import Config
|
||||
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
||||
def test_version_output(http_controller):
|
||||
config = Config.instance()
|
||||
config.set("Server", "local", "true")
|
||||
async def test_version_output(controller_api, config):
|
||||
|
||||
response = http_controller.get('/version', example=True)
|
||||
config.set("Server", "local", "true")
|
||||
response = await controller_api.get('/version')
|
||||
assert response.status == 200
|
||||
assert response.json == {'local': True, 'version': __version__}
|
||||
|
||||
|
||||
def test_version_input(http_controller):
|
||||
query = {'version': __version__}
|
||||
response = http_controller.post('/version', query, example=True)
|
||||
async def test_version_input(controller_api):
|
||||
|
||||
params = {'version': __version__}
|
||||
response = await controller_api.post('/version', params)
|
||||
assert response.status == 200
|
||||
assert response.json == {'version': __version__}
|
||||
|
||||
|
||||
def test_version_invalid_input(http_controller):
|
||||
query = {'version': "0.4.2"}
|
||||
response = http_controller.post('/version', query)
|
||||
assert response.status == 409
|
||||
async def test_version_invalid_input(controller_api):
|
||||
|
||||
params = {'version': "0.4.2"}
|
||||
response = await controller_api.post('/version', params)
|
||||
assert response.status == 409
|
||||
assert response.json == {'message': 'Client version 0.4.2 is not the same as server version {}'.format(__version__),
|
||||
'status': 409}
|
||||
|
||||
|
||||
def test_version_invalid_input_schema(http_controller):
|
||||
query = {'version': "0.4.2", "bla": "blu"}
|
||||
response = http_controller.post('/version', query)
|
||||
async def test_version_invalid_input_schema(controller_api):
|
||||
|
||||
params = {'version': "0.4.2", "bla": "blu"}
|
||||
response = await controller_api.post('/version', params)
|
||||
assert response.status == 400
|
||||
|
||||
|
||||
def test_version_invalid_json(http_controller):
|
||||
query = "BOUM"
|
||||
response = http_controller.post('/version', query, raw=True)
|
||||
async def test_version_invalid_json(controller_api):
|
||||
|
||||
params = "BOUM"
|
||||
response = await controller_api.post('/version', params, raw=True)
|
||||
assert response.status == 400
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -25,60 +25,68 @@ from gns3server.utils.get_resource import get_resource
|
||||
|
||||
|
||||
def get_static(filename):
|
||||
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
return os.path.join(os.path.abspath(os.path.join(current_dir, '..', '..', 'gns3server', 'static')), filename)
|
||||
|
||||
|
||||
def test_debug(http_root):
|
||||
response = http_root.get('/debug')
|
||||
async def test_debug(http_client):
|
||||
|
||||
response = await http_client.get('/debug')
|
||||
assert response.status == 200
|
||||
html = response.html
|
||||
html = await response.text()
|
||||
assert "Website" in html
|
||||
assert __version__ in html
|
||||
|
||||
|
||||
def test_controller(http_root, async_run):
|
||||
project = async_run(Controller.instance().add_project(name="test"))
|
||||
response = http_root.get('/controller')
|
||||
assert "test" in response.html
|
||||
async def test_controller(http_client, controller):
|
||||
|
||||
await controller.add_project(name="test")
|
||||
response = await http_client.get('/controller')
|
||||
assert "test" in await response.text()
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_compute(http_root):
|
||||
response = http_root.get('/compute')
|
||||
async def test_compute(http_client):
|
||||
|
||||
response = await http_client.get('/compute')
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_project(http_root, async_run):
|
||||
project = async_run(Controller.instance().add_project(name="test"))
|
||||
response = http_root.get('/projects/{}'.format(project.id))
|
||||
async def test_project(http_client, controller):
|
||||
|
||||
project = await controller.add_project(name="test")
|
||||
response = await http_client.get('/projects/{}'.format(project.id))
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_web_ui(http_root, tmpdir):
|
||||
async def test_web_ui(http_client, tmpdir):
|
||||
|
||||
with patch('gns3server.utils.get_resource.get_resource') as mock:
|
||||
mock.return_value = str(tmpdir)
|
||||
os.makedirs(str(tmpdir / 'web-ui'))
|
||||
tmpfile = get_static('web-ui/testing.txt')
|
||||
with open(tmpfile, 'w+') as f:
|
||||
f.write('world')
|
||||
response = http_root.get('/static/web-ui/testing.txt')
|
||||
response = await http_client.get('/static/web-ui/testing.txt')
|
||||
assert response.status == 200
|
||||
os.remove(get_static('web-ui/testing.txt'))
|
||||
|
||||
|
||||
def test_web_ui_not_found(http_root, tmpdir):
|
||||
async def test_web_ui_not_found(http_client, tmpdir):
|
||||
|
||||
with patch('gns3server.utils.get_resource.get_resource') as mock:
|
||||
mock.return_value = str(tmpdir)
|
||||
|
||||
response = http_root.get('/static/web-ui/not-found.txt')
|
||||
response = await http_client.get('/static/web-ui/not-found.txt')
|
||||
# should serve web-ui/index.html
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_v1(http_root):
|
||||
async def test_v1(http_client):
|
||||
"""
|
||||
The old api v1 raise a 429
|
||||
The old API v1 raises a 429
|
||||
"""
|
||||
response = http_root.get('/v1/version')
|
||||
|
||||
response = await http_client.get('/v1/version')
|
||||
assert response.status == 200
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -17,8 +17,6 @@
|
||||
|
||||
|
||||
import configparser
|
||||
import time
|
||||
import os
|
||||
|
||||
from gns3server.config import Config
|
||||
|
||||
@ -73,6 +71,7 @@ def test_set_section_config(tmpdir):
|
||||
"local": "false"
|
||||
}
|
||||
})
|
||||
|
||||
assert dict(config.get_section_config("Server")) == {"host": "127.0.0.1", "local": "false"}
|
||||
config.set_section_config("Server", {"host": "192.168.1.1", "local": True})
|
||||
assert dict(config.get_section_config("Server")) == {"host": "192.168.1.1", "local": "true"}
|
||||
@ -85,6 +84,7 @@ def test_set(tmpdir):
|
||||
"host": "127.0.0.1"
|
||||
}
|
||||
})
|
||||
|
||||
assert dict(config.get_section_config("Server")) == {"host": "127.0.0.1"}
|
||||
config.set("Server", "host", "192.168.1.1")
|
||||
assert dict(config.get_section_config("Server")) == {"host": "192.168.1.1"}
|
||||
@ -97,12 +97,12 @@ def test_reload(tmpdir):
|
||||
"host": "127.0.0.1"
|
||||
}
|
||||
})
|
||||
assert dict(config.get_section_config("Server")) == {"host": "127.0.0.1"}
|
||||
|
||||
assert dict(config.get_section_config("Server")) == {"host": "127.0.0.1"}
|
||||
config.set_section_config("Server", {"host": "192.168.1.1"})
|
||||
assert dict(config.get_section_config("Server")) == {"host": "192.168.1.1"}
|
||||
|
||||
path = write_config(tmpdir, {
|
||||
write_config(tmpdir, {
|
||||
"Server": {
|
||||
"host": "192.168.1.2"
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
from gns3server.utils import *
|
||||
|
||||
|
||||
@ -23,8 +22,8 @@ def test_force_unix_path():
|
||||
assert force_unix_path("a/b") == "a/b"
|
||||
assert force_unix_path("a\\b") == "a/b"
|
||||
assert force_unix_path("a\\b\\..\\c") == "a/c"
|
||||
assert force_unix_path("C:\Temp") == "C:/Temp"
|
||||
assert force_unix_path(force_unix_path("C:\Temp")) == "C:/Temp"
|
||||
assert force_unix_path(r"C:\Temp") == r"C:/Temp"
|
||||
assert force_unix_path(force_unix_path(r"C:\Temp")) == r"C:/Temp"
|
||||
assert force_unix_path("a//b") == "a/b"
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -34,13 +34,13 @@ class _asyncio_patch:
|
||||
"""
|
||||
|
||||
def __init__(self, function, *args, **kwargs):
|
||||
self.function = function
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
self._function = function
|
||||
self._aync_magic_mock = AsyncioMagicMock(*args, **kwargs)
|
||||
|
||||
def __enter__(self):
|
||||
"""Used when enter in the with block"""
|
||||
self._patcher = unittest.mock.patch(self.function, return_value=self._fake_anwser())
|
||||
self._patcher = unittest.mock.patch(self._function, new=self._aync_magic_mock)
|
||||
mock_class = self._patcher.start()
|
||||
return mock_class
|
||||
|
||||
@ -48,19 +48,6 @@ class _asyncio_patch:
|
||||
"""Used when leaving the with block"""
|
||||
self._patcher.stop()
|
||||
|
||||
def _fake_anwser(self):
|
||||
future = asyncio.Future()
|
||||
if "return_value" in self.kwargs:
|
||||
future.set_result(self.kwargs["return_value"])
|
||||
elif "side_effect" in self.kwargs:
|
||||
if isinstance(self.kwargs["side_effect"], Exception):
|
||||
future.set_exception(self.kwargs["side_effect"])
|
||||
else:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
future.set_result(True)
|
||||
return future
|
||||
|
||||
|
||||
def asyncio_patch(function, *args, **kwargs):
|
||||
return _asyncio_patch(function, *args, **kwargs)
|
||||
@ -77,12 +64,13 @@ class AsyncioMagicMock(unittest.mock.MagicMock):
|
||||
"""
|
||||
Magic mock returning coroutine
|
||||
"""
|
||||
|
||||
try:
|
||||
__class__ = types.CoroutineType
|
||||
except AttributeError: # Not supported with Python 3.4
|
||||
__class__ = types.GeneratorType
|
||||
|
||||
def __init__(self, return_value=None, return_values=None, **kwargs):
|
||||
def __init__(self, return_value=None, **kwargs):
|
||||
"""
|
||||
:return_values: Array of return value at each call will return the next
|
||||
"""
|
||||
|
@ -25,53 +25,33 @@ from gns3server.utils.asyncio import wait_run_in_executor, subprocess_check_outp
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
|
||||
def test_wait_run_in_executor(loop):
|
||||
async def test_wait_run_in_executor():
|
||||
|
||||
def change_var(param):
|
||||
return param
|
||||
|
||||
exec = wait_run_in_executor(change_var, "test")
|
||||
result = loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
result = await wait_run_in_executor(change_var, "test")
|
||||
assert result == "test"
|
||||
|
||||
|
||||
def test_exception_wait_run_in_executor(loop):
|
||||
async def test_exception_wait_run_in_executor():
|
||||
|
||||
def raise_exception():
|
||||
raise Exception("test")
|
||||
|
||||
exec = wait_run_in_executor(raise_exception)
|
||||
with pytest.raises(Exception):
|
||||
result = loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
await wait_run_in_executor(raise_exception)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_subprocess_check_output(loop, tmpdir, restore_original_path):
|
||||
async def test_subprocess_check_output(loop, tmpdir):
|
||||
|
||||
path = str(tmpdir / "test")
|
||||
exec = subprocess_check_output("echo", "-n", path)
|
||||
result = loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
result = await subprocess_check_output("echo", "-n", path)
|
||||
assert result == path
|
||||
|
||||
|
||||
def test_wait_for_process_termination(loop):
|
||||
|
||||
if sys.version_info >= (3, 5):
|
||||
# No need for test we use native version
|
||||
return
|
||||
process = MagicMock()
|
||||
process.returncode = 0
|
||||
exec = wait_for_process_termination(process)
|
||||
loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
|
||||
process = MagicMock()
|
||||
process.returncode = None
|
||||
exec = wait_for_process_termination(process, timeout=0.5)
|
||||
with pytest.raises(asyncio.TimeoutError):
|
||||
loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
|
||||
|
||||
def test_lock_decorator(loop):
|
||||
async def test_lock_decorator():
|
||||
"""
|
||||
The test check if the the second call to method_to_lock wait for the
|
||||
first call to finish
|
||||
@ -84,11 +64,11 @@ def test_lock_decorator(loop):
|
||||
|
||||
@locking
|
||||
async def method_to_lock(self):
|
||||
res = self._test_val
|
||||
result = self._test_val
|
||||
await asyncio.sleep(0.1)
|
||||
self._test_val += 1
|
||||
return res
|
||||
return result
|
||||
|
||||
i = TestLock()
|
||||
res = set(loop.run_until_complete(asyncio.gather(i.method_to_lock(), i.method_to_lock())))
|
||||
res = set(await asyncio.gather(i.method_to_lock(), i.method_to_lock()))
|
||||
assert res == set((0, 1,)) # We use a set to test this to avoid order issue
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -24,41 +24,42 @@ from gns3server.utils.file_watcher import FileWatcher
|
||||
|
||||
|
||||
@pytest.mark.parametrize("strategy", ['mtime', 'hash'])
|
||||
def test_file_watcher(async_run, tmpdir, strategy):
|
||||
async def test_file_watcher(tmpdir, strategy):
|
||||
|
||||
file = tmpdir / "test"
|
||||
file.write("a")
|
||||
callback = MagicMock()
|
||||
fw = FileWatcher(file, callback, delay=0.5, strategy=strategy)
|
||||
async_run(asyncio.sleep(1))
|
||||
FileWatcher(file, callback, delay=0.1, strategy=strategy)
|
||||
await asyncio.sleep(0.5)
|
||||
assert not callback.called
|
||||
file.write("b")
|
||||
async_run(asyncio.sleep(1.5))
|
||||
await asyncio.sleep(0.5)
|
||||
callback.assert_called_with(str(file))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("strategy", ['mtime', 'hash'])
|
||||
def test_file_watcher_not_existing(async_run, tmpdir, strategy):
|
||||
async def test_file_watcher_not_existing(tmpdir, strategy):
|
||||
|
||||
file = tmpdir / "test"
|
||||
callback = MagicMock()
|
||||
fw = FileWatcher(file, callback, delay=0.5, strategy=strategy)
|
||||
async_run(asyncio.sleep(1))
|
||||
FileWatcher(file, callback, delay=0.1, strategy=strategy)
|
||||
await asyncio.sleep(0.5)
|
||||
assert not callback.called
|
||||
file.write("b")
|
||||
async_run(asyncio.sleep(1.5))
|
||||
await asyncio.sleep(0.5)
|
||||
callback.assert_called_with(str(file))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("strategy", ['mtime', 'hash'])
|
||||
def test_file_watcher_list(async_run, tmpdir, strategy):
|
||||
async def test_file_watcher_list(tmpdir, strategy):
|
||||
|
||||
file = tmpdir / "test"
|
||||
file.write("a")
|
||||
|
||||
file2 = tmpdir / "test2"
|
||||
|
||||
callback = MagicMock()
|
||||
fw = FileWatcher([file, file2], callback, delay=0.5, strategy=strategy)
|
||||
async_run(asyncio.sleep(1))
|
||||
FileWatcher([file, file2], callback, delay=0.1, strategy=strategy)
|
||||
await asyncio.sleep(0.5)
|
||||
assert not callback.called
|
||||
file2.write("b")
|
||||
async_run(asyncio.sleep(1.5))
|
||||
await asyncio.sleep(0.5)
|
||||
callback.assert_called_with(str(file2))
|
||||
|
@ -26,6 +26,7 @@ from gns3server.utils.images import md5sum, remove_checksum, images_directories,
|
||||
|
||||
|
||||
def test_images_directories(tmpdir):
|
||||
|
||||
path1 = tmpdir / "images1" / "QEMU" / "test1.bin"
|
||||
path1.write("1", ensure=True)
|
||||
path1 = force_unix_path(str(path1))
|
||||
@ -48,6 +49,7 @@ def test_images_directories(tmpdir):
|
||||
|
||||
|
||||
def test_md5sum(tmpdir):
|
||||
|
||||
fake_img = str(tmpdir / 'hello载')
|
||||
|
||||
with open(fake_img, 'w+') as f:
|
||||
@ -59,6 +61,7 @@ def test_md5sum(tmpdir):
|
||||
|
||||
|
||||
def test_md5sum_stopped_event(tmpdir):
|
||||
|
||||
fake_img = str(tmpdir / 'hello_stopped')
|
||||
with open(fake_img, 'w+') as f:
|
||||
f.write('hello')
|
||||
@ -71,6 +74,7 @@ def test_md5sum_stopped_event(tmpdir):
|
||||
|
||||
|
||||
def test_md5sum_existing_digest(tmpdir):
|
||||
|
||||
fake_img = str(tmpdir / 'hello')
|
||||
|
||||
with open(fake_img, 'w+') as f:
|
||||
@ -83,6 +87,7 @@ def test_md5sum_existing_digest(tmpdir):
|
||||
|
||||
|
||||
def test_md5sum_existing_digest_but_missing_image(tmpdir):
|
||||
|
||||
fake_img = str(tmpdir / 'hello')
|
||||
|
||||
with open(str(tmpdir / 'hello.md5sum'), 'w+') as f:
|
||||
@ -92,6 +97,7 @@ def test_md5sum_existing_digest_but_missing_image(tmpdir):
|
||||
|
||||
|
||||
def test_md5sum_none(tmpdir):
|
||||
|
||||
assert md5sum(None) is None
|
||||
|
||||
|
||||
@ -107,6 +113,7 @@ def test_remove_checksum(tmpdir):
|
||||
|
||||
|
||||
def test_list_images(tmpdir):
|
||||
|
||||
path1 = tmpdir / "images1" / "IOS" / "test1.image"
|
||||
path1.write(b'\x7fELF\x01\x02\x01', ensure=True)
|
||||
path1 = force_unix_path(str(path1))
|
||||
|
@ -21,6 +21,7 @@ from gns3server.utils.interfaces import interfaces, is_interface_up, has_netmask
|
||||
|
||||
|
||||
def test_interfaces():
|
||||
|
||||
# This test should pass on all platforms without crash
|
||||
interface_list = interfaces()
|
||||
assert isinstance(interface_list, list)
|
||||
@ -39,6 +40,7 @@ def test_interfaces():
|
||||
|
||||
|
||||
def test_has_netmask():
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
# No loopback
|
||||
pass
|
||||
@ -49,6 +51,7 @@ def test_has_netmask():
|
||||
|
||||
|
||||
def test_is_interface_up():
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
# is_interface_up() always returns True on Windows
|
||||
pass
|
||||
|
@ -24,6 +24,7 @@ from gns3server.utils.path import check_path_allowed, get_default_project_direct
|
||||
|
||||
|
||||
def test_check_path_allowed(config, tmpdir):
|
||||
|
||||
config.set("Server", "local", False)
|
||||
config.set("Server", "projects_path", str(tmpdir))
|
||||
with pytest.raises(aiohttp.web.HTTPForbidden):
|
||||
@ -37,7 +38,6 @@ def test_check_path_allowed(config, tmpdir):
|
||||
def test_get_default_project_directory(config):
|
||||
|
||||
config.clear()
|
||||
|
||||
path = os.path.normpath(os.path.expanduser("~/GNS3/projects"))
|
||||
assert get_default_project_directory() == path
|
||||
assert os.path.exists(path)
|
||||
|
@ -20,6 +20,7 @@ from gns3server.utils.picture import get_size
|
||||
|
||||
|
||||
def test_get_size():
|
||||
|
||||
with open("tests/resources/nvram_iou", "rb") as f:
|
||||
res = get_size(f.read(), default_width=100, default_height=50)
|
||||
assert res == (100, 50, None)
|
||||
|
@ -1,42 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
|
||||
from gns3server.web.documentation import Documentation
|
||||
from gns3server.handlers import *
|
||||
from gns3server.web.route import Route
|
||||
|
||||
|
||||
def test_documentation_write(tmpdir):
|
||||
os.makedirs(str(tmpdir / "api/examples"))
|
||||
with open(str(tmpdir / "api/examples/compute_post_projectsprojectidvirtualboxnodes.txt"), "w+") as f:
|
||||
f.write("curl test")
|
||||
|
||||
Documentation(Route, str(tmpdir)).write()
|
||||
|
||||
assert os.path.exists(str(tmpdir / "api"))
|
||||
assert os.path.exists(str(tmpdir / "api" / "v2" / "compute"))
|
||||
assert os.path.exists(str(tmpdir / "api" / "v2" / "compute" / "virtualbox.rst"))
|
||||
assert os.path.exists(str(tmpdir / "api" / "v2" / "compute" / "virtualbox"))
|
||||
assert os.path.exists(str(tmpdir / "api" / "v2" / "compute" / "virtualbox" / "virtualboxvms.rst"))
|
||||
with open(str(tmpdir / "api" / "v2" / "compute" / "virtualbox" / "projectsprojectidvirtualboxnodes.rst")) as f:
|
||||
content = f.read()
|
||||
assert "Sample session" in content
|
||||
assert "literalinclude:: ../../../examples/compute_post_projectsprojectidvirtualboxnodes.txt" in content
|
||||
|
||||
assert os.path.exists(str(tmpdir / "api" / "v2" / "controller" / "compute.rst"))
|
@ -17,7 +17,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
from tests.utils import AsyncioMagicMock
|
||||
from aiohttp.web import HTTPNotFound
|
||||
|
||||
from gns3server.web.response import Response
|
||||
@ -25,20 +25,22 @@ from gns3server.web.response import Response
|
||||
|
||||
@pytest.fixture()
|
||||
def response():
|
||||
request = MagicMock()
|
||||
request = AsyncioMagicMock()
|
||||
return Response(request=request)
|
||||
|
||||
|
||||
def test_response_file(async_run, tmpdir, response):
|
||||
async def test_response_file(tmpdir, response):
|
||||
|
||||
filename = str(tmpdir / 'hello')
|
||||
with open(filename, 'w+') as f:
|
||||
f.write('world')
|
||||
|
||||
async_run(response.stream_file(filename))
|
||||
await response.stream_file(filename)
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_response_file_not_found(async_run, tmpdir, response):
|
||||
filename = str(tmpdir / 'hello-not-found')
|
||||
async def test_response_file_not_found(loop, tmpdir, response):
|
||||
|
||||
pytest.raises(HTTPNotFound, lambda: async_run(response.stream_file(filename)))
|
||||
filename = str(tmpdir / 'hello-not-found')
|
||||
with pytest.raises(HTTPNotFound):
|
||||
await response.stream_file(filename)
|
||||
|
Loading…
Reference in New Issue
Block a user