Refactor tests

* Use pytest-aiohttp
* Use the async def / await syntax.
* Fix tests to run with Python 3.8
This commit is contained in:
grossmj committed 2020-06-16 13:59:03 +09:30
1 parent f498ab06b4
commit d3ea67da24
87 files changed
+3697 -3528

No files matched your search

+22 -17
View File
@@ -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([
+10 -9
View File
@@ -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"
}
]
}
}
+26 -21
View File
@@ -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
+20 -20
View File
@@ -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()
+16 -14
View File
@@ -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 = {}
+68 -64
View File
@@ -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
+8 -4
View File
@@ -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")
+27 -23
View File
@@ -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 == []
+140 -134
View File
@@ -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", "")
+41 -32
View File
@@ -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\"")
+59 -44
View File
@@ -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)
+17 -13
View File
@@ -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
+12 -5
View File
@@ -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"
+44 -36
View File
@@ -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
+4 -1
View File
@@ -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')
+40 -33
View File
@@ -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}
+30 -19
View File
@@ -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>
"""
+5 -11
View File
@@ -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"')
+17 -16
View File
@@ -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
+15 -12
View File
@@ -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
+64 -48
View File
@@ -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