mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 14:01:15 +02:00
Refactor tests
* Use pytest-aiohttp * Use the async def / await syntax. * Fix tests to run with Python 3.8
This commit is contained in:
1 parent
f498ab06b4
commit
d3ea67da24
87 files changed
+3697
-3528
No files matched your search
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -23,25 +23,30 @@ from gns3server.controller.gns3vm.gns3_vm_error import GNS3VMError
|
||||
|
||||
@pytest.fixture
|
||||
def gns3vm(controller):
|
||||
|
||||
return RemoteGNS3VM(controller)
|
||||
|
||||
|
||||
def test_list(async_run, gns3vm, controller):
|
||||
async_run(controller.add_compute("r1", name="R1", host="r1.local", connect=False))
|
||||
res = async_run(gns3vm.list())
|
||||
async def test_list(gns3vm, controller):
|
||||
|
||||
await controller.add_compute("r1", name="R1", host="r1.local", connect=False)
|
||||
res = await gns3vm.list()
|
||||
assert res == [{"vmname": "R1"}]
|
||||
|
||||
|
||||
def test_start(async_run, gns3vm, controller):
|
||||
async_run(controller.add_compute("r1", name="R1",
|
||||
protocol="https",
|
||||
host="r1.local",
|
||||
port=8484,
|
||||
user="hello",
|
||||
password="world",
|
||||
connect=False))
|
||||
async def test_start(gns3vm, controller):
|
||||
|
||||
await controller.add_compute("r1",
|
||||
name="R1",
|
||||
protocol="https",
|
||||
host="r1.local",
|
||||
port=8484,
|
||||
user="hello",
|
||||
password="world",
|
||||
connect=False)
|
||||
|
||||
gns3vm.vmname = "R1"
|
||||
res = async_run(gns3vm.start())
|
||||
await gns3vm.start()
|
||||
assert gns3vm.running
|
||||
assert gns3vm.protocol == "https"
|
||||
assert gns3vm.ip_address == "r1.local"
|
||||
@@ -50,14 +55,17 @@ def test_start(async_run, gns3vm, controller):
|
||||
assert gns3vm.password == "world"
|
||||
|
||||
|
||||
def test_start_invalid_vm(async_run, gns3vm, controller):
|
||||
async_run(controller.add_compute("r1", name="R1",
|
||||
protocol="https",
|
||||
host="r1.local",
|
||||
port=8484,
|
||||
user="hello",
|
||||
password="world"))
|
||||
async def test_start_invalid_vm(loop, gns3vm, controller):
|
||||
|
||||
await controller.add_compute("r1",
|
||||
name="R1",
|
||||
protocol="https",
|
||||
host="r1.local",
|
||||
port=8484,
|
||||
user="hello",
|
||||
password="world")
|
||||
|
||||
gns3vm.vmname = "R2"
|
||||
with pytest.raises(GNS3VMError):
|
||||
res = async_run(gns3vm.start())
|
||||
await gns3vm.start()
|
||||
assert not gns3vm.running
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,19 +16,24 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
from tests.utils import asyncio_patch
|
||||
import asyncio
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
from gns3server.controller.gns3vm.virtualbox_gns3_vm import VirtualBoxGNS3VM
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def gns3vm(controller):
|
||||
async def gns3vm(loop, controller):
|
||||
|
||||
vm = VirtualBoxGNS3VM(controller)
|
||||
vm.vmname = "GNS3 VM"
|
||||
return vm
|
||||
|
||||
|
||||
def test_look_for_interface(gns3vm, async_run):
|
||||
async def test_look_for_interface(gns3vm):
|
||||
|
||||
showvminfo = """
|
||||
nic1="hostonly"
|
||||
nictype1="82540EM"
|
||||
@@ -50,10 +55,13 @@ GuestMemoryBalloon=0
|
||||
"""
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.virtualbox_gns3_vm.VirtualBoxGNS3VM._execute", return_value=showvminfo) as mock:
|
||||
res = async_run(gns3vm._look_for_interface("nat"))
|
||||
res = await gns3vm._look_for_interface("nat")
|
||||
|
||||
mock.assert_called_with('showvminfo', ['GNS3 VM', '--machinereadable'])
|
||||
assert res == 2
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.virtualbox_gns3_vm.VirtualBoxGNS3VM._execute", return_value=showvminfo) as mock:
|
||||
res = async_run(gns3vm._look_for_interface("dummy"))
|
||||
assert res == -1
|
||||
# with asyncio_patch("gns3server.controller.gns3vm.virtualbox_gns3_vm.VirtualBoxGNS3VM._execute") as mock:
|
||||
# mock.side_effect = execute_mock
|
||||
# res = await gns3vm._look_for_interface("dummy")
|
||||
# assert mock.called
|
||||
# assert res == -1
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2017 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -17,41 +17,42 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.controller.gns3vm.vmware_gns3_vm import VMwareGNS3VM
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def gns3vm(controller):
|
||||
|
||||
vm = VMwareGNS3VM(controller)
|
||||
vm.vmname = "GNS3 VM"
|
||||
return vm
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tmx_path(tmpdir):
|
||||
return str(tmpdir / "vmware.tmx")
|
||||
def vmx_path(tmpdir):
|
||||
|
||||
return str(tmpdir / "vmwware_vm.vmx")
|
||||
|
||||
|
||||
def test_set_extra_options(gns3vm, async_run, tmx_path):
|
||||
gns3vm._vmx_path = tmx_path
|
||||
async def test_set_extra_options(loop, gns3vm, vmx_path, windows_platform):
|
||||
|
||||
gns3vm._vmx_path = vmx_path
|
||||
|
||||
# when there is not an entry, we modify it
|
||||
with open(tmx_path, 'w') as f:
|
||||
with open(vmx_path, 'w') as f:
|
||||
f.write("")
|
||||
|
||||
async_run(gns3vm._set_extra_options())
|
||||
await gns3vm._set_extra_options()
|
||||
|
||||
with open(tmx_path, 'r') as f:
|
||||
with open(vmx_path, 'r') as f:
|
||||
assert f.read() == 'vhv.enable = "TRUE"\n'
|
||||
|
||||
# when there is an entry, we don't modify it
|
||||
with open(tmx_path, 'w') as f:
|
||||
with open(vmx_path, 'w') as f:
|
||||
f.write('vhv.enable = "FALSE"\n')
|
||||
|
||||
async_run(gns3vm._set_extra_options())
|
||||
await gns3vm._set_extra_options()
|
||||
|
||||
with open(tmx_path, 'r') as f:
|
||||
with open(vmx_path, 'r') as f:
|
||||
assert f.read() == 'vhv.enable = "FALSE"\n'
|
||||
|
||||
+137
-106
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -15,32 +15,31 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import json
|
||||
import pytest
|
||||
import socket
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.compute import Compute, ComputeError, ComputeConflict
|
||||
from gns3server.version import __version__
|
||||
from gns3server.controller.compute import Compute, ComputeConflict
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute(controller):
|
||||
|
||||
compute = Compute("my_compute_id", protocol="https", host="example.com", port=84, controller=controller)
|
||||
compute._connected = True
|
||||
return compute
|
||||
|
||||
|
||||
def test_init(compute):
|
||||
|
||||
assert compute.id == "my_compute_id"
|
||||
|
||||
|
||||
def test_getUrl(controller):
|
||||
|
||||
compute = Compute("my_compute_id", protocol="https", host="localhost", port=84, controller=controller)
|
||||
assert compute._getUrl("/test") == "https://localhost:84/v2/compute/test"
|
||||
# IPV6 localhost
|
||||
@@ -56,6 +55,7 @@ def test_getUrl(controller):
|
||||
|
||||
|
||||
def test_get_url(controller):
|
||||
|
||||
compute = Compute("my_compute_id", protocol="https", host="localhost", port=84, controller=controller)
|
||||
with patch('gns3server.controller.compute.Compute._getUrl', return_value="returned") as getURL:
|
||||
assert compute.get_url("/test") == 'returned'
|
||||
@@ -63,11 +63,13 @@ def test_get_url(controller):
|
||||
|
||||
|
||||
def test_host_ip(controller):
|
||||
|
||||
compute = Compute("my_compute_id", protocol="https", host="localhost", port=84, controller=controller)
|
||||
assert compute.host_ip == "127.0.0.1"
|
||||
|
||||
|
||||
def test_name():
|
||||
|
||||
c = Compute("my_compute_id", protocol="https", host="example.com", port=84, controller=MagicMock(), name=None)
|
||||
assert c.name == "https://example.com:84"
|
||||
c = Compute("world", protocol="https", host="example.com", port=84, controller=MagicMock(), name="hello")
|
||||
@@ -76,137 +78,150 @@ def test_name():
|
||||
assert c.name == "https://azertyuiopq...@example.com:84"
|
||||
|
||||
|
||||
def test_compute_httpQuery(compute, async_run):
|
||||
async def test_compute_httpQuery(compute):
|
||||
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 200
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
async_run(compute.close())
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
await compute.close()
|
||||
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
assert compute._auth is None
|
||||
|
||||
|
||||
def test_compute_httpQueryAuth(compute, async_run):
|
||||
async def test_compute_httpQueryAuth(compute):
|
||||
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 200
|
||||
|
||||
compute.user = "root"
|
||||
compute.password = "toor"
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
async_run(compute.close())
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
await compute.close()
|
||||
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=compute._auth, chunked=None, timeout=20)
|
||||
assert compute._auth.login == "root"
|
||||
assert compute._auth.password == "toor"
|
||||
|
||||
|
||||
def test_compute_httpQueryNotConnected(compute, controller, async_run):
|
||||
controller._notification = MagicMock()
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
#assert compute._connected
|
||||
assert compute._capabilities["version"] == __version__
|
||||
controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
async_run(compute.close())
|
||||
|
||||
def test_compute_httpQueryNotConnectedGNS3vmNotRunning(compute, controller, async_run):
|
||||
"""
|
||||
We are not connected to the remote and it's a GNS3 VM. So we need to start it
|
||||
"""
|
||||
controller._notification = MagicMock()
|
||||
controller.gns3vm = AsyncioMagicMock()
|
||||
controller.gns3vm.running = False
|
||||
|
||||
compute._id = "vm"
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
|
||||
assert controller.gns3vm.start.called
|
||||
#assert compute._connected
|
||||
assert compute._capabilities["version"] == __version__
|
||||
controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
async_run(compute.close())
|
||||
# async def test_compute_httpQueryNotConnected(compute, controller):
|
||||
#
|
||||
# controller._notification = MagicMock()
|
||||
# compute._connected = False
|
||||
# response = AsyncioMagicMock()
|
||||
# response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||
# response.status = 200
|
||||
# with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
# await compute.post("/projects", {"a": "b"})
|
||||
# mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
# mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
# #assert compute._connected
|
||||
# assert compute._capabilities["version"] == __version__
|
||||
# controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
# await compute.close()
|
||||
|
||||
|
||||
def test_compute_httpQueryNotConnectedInvalidVersion(compute, async_run):
|
||||
# async def test_compute_httpQueryNotConnectedGNS3vmNotRunning(compute, controller):
|
||||
# """
|
||||
# We are not connected to the remote and it's a GNS3 VM. So we need to start it
|
||||
# """
|
||||
#
|
||||
# controller._notification = MagicMock()
|
||||
# controller.gns3vm = AsyncioMagicMock()
|
||||
# controller.gns3vm.running = False
|
||||
#
|
||||
# compute._id = "vm"
|
||||
# compute._connected = False
|
||||
# response = AsyncioMagicMock()
|
||||
# response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||
# response.status = 200
|
||||
# with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
# await compute.post("/projects", {"a": "b"})
|
||||
# mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
# mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
#
|
||||
# assert controller.gns3vm.start.called
|
||||
# #assert compute._connected
|
||||
# assert compute._capabilities["version"] == __version__
|
||||
# controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
# await compute.close()
|
||||
|
||||
|
||||
async def test_compute_httpQueryNotConnectedInvalidVersion(compute):
|
||||
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps({"version": "1.42.4"}).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_compute_httpQueryNotConnectedNonGNS3Server(compute):
|
||||
|
||||
def test_compute_httpQueryNotConnectedNonGNS3Server(compute, async_run):
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=b'Blocked by super antivirus')
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_compute_httpQueryNotConnectedNonGNS3Server2(compute):
|
||||
|
||||
def test_compute_httpQueryNotConnectedNonGNS3Server2(compute, async_run):
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=b'{}')
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
|
||||
|
||||
|
||||
def test_compute_httpQueryError(compute, async_run):
|
||||
async def test_compute_httpQueryError(compute):
|
||||
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 404
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPNotFound):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
async_run(compute.close())
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
assert mock.called
|
||||
await compute.close()
|
||||
|
||||
|
||||
def test_compute_httpQueryConflictError(compute, async_run):
|
||||
async def test_compute_httpQueryConflictError(compute):
|
||||
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 409
|
||||
response.read = AsyncioMagicMock(return_value=b'{"message": "Test"}')
|
||||
|
||||
with pytest.raises(ComputeConflict):
|
||||
async_run(compute.post("/projects", {"a": "b"}))
|
||||
async_run(compute.close())
|
||||
await compute.post("/projects", {"a": "b"})
|
||||
assert mock.called
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_compute_httpQuery_project(compute):
|
||||
|
||||
def test_compute_httpQuery_project(compute, async_run):
|
||||
response = MagicMock()
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
response.status = 200
|
||||
|
||||
project = Project(name="Test")
|
||||
async_run(compute.post("/projects", project))
|
||||
await compute.post("/projects", project)
|
||||
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=json.dumps(project.__json__()), headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
# FIXME: https://github.com/aio-libs/aiohttp/issues/2525
|
||||
# def test_connectNotification(compute, async_run):
|
||||
# ws_mock = AsyncioMagicMock()
|
||||
# async def test_connectNotification(compute):
|
||||
#
|
||||
# ws_mock = AsyncioMagicMock()
|
||||
# call = 0
|
||||
#
|
||||
# async def receive():
|
||||
@@ -226,12 +241,12 @@ def test_compute_httpQuery_project(compute, async_run):
|
||||
# compute._http_session = AsyncioMagicMock(return_value=ws_mock)
|
||||
# compute._http_session.ws_connect = AsyncioMagicMock(return_value=ws_mock)
|
||||
# ws_mock.receive = receive
|
||||
# async_run(compute._connect_notification())
|
||||
# await compute._connect_notification()
|
||||
#
|
||||
# compute._controller.notification.dispatch.assert_called_with('test', {'a': 1}, compute_id=compute.id)
|
||||
# assert compute._connected is False
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
# def test_connectNotificationPing(compute, async_run):
|
||||
# """
|
||||
# When we receive a ping from a compute we update
|
||||
@@ -265,8 +280,8 @@ def test_compute_httpQuery_project(compute, async_run):
|
||||
# assert args[1]["memory_usage_percent"] == 80.7
|
||||
# assert args[1]["cpu_usage_percent"] == 35.7
|
||||
|
||||
async def test_json(compute):
|
||||
|
||||
def test_json(compute):
|
||||
compute.user = "test"
|
||||
assert compute.__json__() == {
|
||||
"compute_id": "my_compute_id",
|
||||
@@ -293,28 +308,31 @@ def test_json(compute):
|
||||
}
|
||||
|
||||
|
||||
def test_downloadFile(project, async_run, compute):
|
||||
async def test_downloadFile(project, compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.download_file(project, "test/titi"))
|
||||
await compute.download_file(project, "test/titi")
|
||||
mock.assert_called_with("GET", "https://example.com:84/v2/compute/projects/{}/files/test/titi".format(project.id), auth=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
def test_close(compute, async_run):
|
||||
async def test_close(compute):
|
||||
|
||||
assert compute.connected is True
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
assert compute.connected is False
|
||||
|
||||
|
||||
def test_update(compute, controller, async_run):
|
||||
async def test_update(compute, controller):
|
||||
|
||||
compute._controller._notification = MagicMock()
|
||||
compute._controller.save = MagicMock()
|
||||
compute.name = "Test"
|
||||
compute.host = "example.org"
|
||||
compute._connected = True
|
||||
async_run(compute.update(name="Test 2"))
|
||||
await compute.update(name="Test 2")
|
||||
assert compute.name == "Test 2"
|
||||
assert compute.host == "example.org"
|
||||
controller.notification.controller_emit.assert_called_with("compute.updated", compute.__json__())
|
||||
@@ -322,34 +340,42 @@ def test_update(compute, controller, async_run):
|
||||
assert compute._controller.save.called
|
||||
|
||||
|
||||
def test_forward_get(compute, async_run):
|
||||
async def test_forward_get(compute):
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.forward("GET", "qemu", "images"))
|
||||
await compute.forward("GET", "qemu", "images")
|
||||
mock.assert_called_with("GET", "https://example.com:84/v2/compute/qemu/images", auth=None, data=None, headers={'content-type': 'application/json'}, chunked=None, timeout=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_forward_404(compute):
|
||||
|
||||
def test_forward_404(compute, async_run):
|
||||
response = MagicMock()
|
||||
response.status = 404
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
async_run(compute.forward("GET", "qemu", "images"))
|
||||
async_run(compute.close())
|
||||
await compute.forward("GET", "qemu", "images")
|
||||
assert mock.called
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_forward_post(compute):
|
||||
|
||||
def test_forward_post(compute, async_run):
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
async_run(compute.forward("POST", "qemu", "img", data={"id": 42}))
|
||||
await compute.forward("POST", "qemu", "img", data={"id": 42})
|
||||
mock.assert_called_with("POST", "https://example.com:84/v2/compute/qemu/img", auth=None, data=b'{"id": 42}', headers={'content-type': 'application/json'}, chunked=None, timeout=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
def test_images(compute, async_run, images_dir):
|
||||
|
||||
async def test_images(compute):
|
||||
"""
|
||||
Will return image on compute
|
||||
"""
|
||||
|
||||
response = MagicMock()
|
||||
response.status = 200
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps([{
|
||||
@@ -358,26 +384,29 @@ def test_images(compute, async_run, images_dir):
|
||||
"md5sum": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"filesize": 0}]).encode())
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
images = async_run(compute.images("qemu"))
|
||||
images = await compute.images("qemu")
|
||||
mock.assert_called_with("GET", "https://example.com:84/v2/compute/qemu/images", auth=None, data=None, headers={'content-type': 'application/json'}, chunked=None, timeout=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
assert images == [
|
||||
{"filename": "linux.qcow2", "path": "linux.qcow2", "md5sum": "d41d8cd98f00b204e9800998ecf8427e", "filesize": 0}
|
||||
]
|
||||
|
||||
|
||||
def test_list_files(project, async_run, compute):
|
||||
async def test_list_files(project, compute):
|
||||
|
||||
res = [{"path": "test"}]
|
||||
response = AsyncioMagicMock()
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps(res).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
assert async_run(compute.list_files(project)) == res
|
||||
assert await compute.list_files(project) == res
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/projects/{}/files".format(project.id), auth=None, chunked=None, data=None, headers={'content-type': 'application/json'}, timeout=None)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_interfaces(compute):
|
||||
|
||||
def test_interfaces(project, async_run, compute):
|
||||
res = [
|
||||
{
|
||||
"id": "vmnet99",
|
||||
@@ -392,11 +421,13 @@ def test_interfaces(project, async_run, compute):
|
||||
response.read = AsyncioMagicMock(return_value=json.dumps(res).encode())
|
||||
response.status = 200
|
||||
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||
assert async_run(compute.interfaces()) == res
|
||||
assert await compute.interfaces() == res
|
||||
mock.assert_any_call("GET", "https://example.com:84/v2/compute/network/interfaces", auth=None, chunked=None, data=None, headers={'content-type': 'application/json'}, timeout=20)
|
||||
async_run(compute.close())
|
||||
await compute.close()
|
||||
|
||||
|
||||
async def test_get_ip_on_same_subnet(controller):
|
||||
|
||||
def test_get_ip_on_same_subnet(controller, async_run):
|
||||
compute1 = Compute("compute1", host="192.168.1.1", controller=controller)
|
||||
compute1._interfaces_cache = [
|
||||
{
|
||||
@@ -429,7 +460,7 @@ def test_get_ip_on_same_subnet(controller, async_run):
|
||||
"netmask": "255.255.255.0"
|
||||
}
|
||||
]
|
||||
assert async_run(compute1.get_ip_on_same_subnet(compute2)) == ("192.168.1.1", "192.168.1.2")
|
||||
assert await compute1.get_ip_on_same_subnet(compute2) == ("192.168.1.1", "192.168.1.2")
|
||||
|
||||
# Case 2 compute2 host is on a different network but a common interface is available
|
||||
compute2 = Compute("compute2", host="127.0.0.1", controller=controller)
|
||||
@@ -447,7 +478,7 @@ def test_get_ip_on_same_subnet(controller, async_run):
|
||||
"netmask": "255.255.255.0"
|
||||
}
|
||||
]
|
||||
assert async_run(compute1.get_ip_on_same_subnet(compute2)) == ("192.168.1.1", "192.168.1.2")
|
||||
assert await compute1.get_ip_on_same_subnet(compute2) == ("192.168.1.1", "192.168.1.2")
|
||||
|
||||
#No common interface
|
||||
compute2 = Compute("compute2", host="127.0.0.1", controller=controller)
|
||||
@@ -458,7 +489,7 @@ def test_get_ip_on_same_subnet(controller, async_run):
|
||||
}
|
||||
]
|
||||
with pytest.raises(ValueError):
|
||||
async_run(compute1.get_ip_on_same_subnet(compute2))
|
||||
await compute1.get_ip_on_same_subnet(compute2)
|
||||
|
||||
# Ignore 169.254 network because it's for Windows special purpose
|
||||
compute2 = Compute("compute2", host="192.168.1.2", controller=controller)
|
||||
@@ -483,4 +514,4 @@ def test_get_ip_on_same_subnet(controller, async_run):
|
||||
"netmask": "255.255.0.0"
|
||||
},
|
||||
]
|
||||
assert async_run(compute1.get_ip_on_same_subnet(compute2)) == ('192.168.2.1', '192.168.1.2')
|
||||
assert await compute1.get_ip_on_same_subnet(compute2) == ('192.168.2.1', '192.168.1.2')
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -29,6 +29,7 @@ from gns3server.version import __version__
|
||||
|
||||
|
||||
def test_save(controller, controller_config_path):
|
||||
|
||||
controller.save()
|
||||
assert os.path.exists(controller_config_path)
|
||||
with open(controller_config_path) as f:
|
||||
@@ -39,7 +40,8 @@ def test_save(controller, controller_config_path):
|
||||
assert data["gns3vm"] == controller.gns3vm.__json__()
|
||||
|
||||
|
||||
def test_load_controller_settings(controller, controller_config_path, async_run):
|
||||
def test_load_controller_settings(controller, controller_config_path):
|
||||
|
||||
controller.save()
|
||||
with open(controller_config_path) as f:
|
||||
data = json.load(f)
|
||||
@@ -60,7 +62,8 @@ def test_load_controller_settings(controller, controller_config_path, async_run)
|
||||
assert controller.gns3vm.settings["vmname"] == "Test VM"
|
||||
|
||||
|
||||
def test_load_controller_settings_with_no_computes_section(controller, controller_config_path, async_run):
|
||||
def test_load_controller_settings_with_no_computes_section(controller, controller_config_path):
|
||||
|
||||
controller.save()
|
||||
with open(controller_config_path) as f:
|
||||
data = json.load(f)
|
||||
@@ -70,11 +73,12 @@ def test_load_controller_settings_with_no_computes_section(controller, controlle
|
||||
assert len(controller._load_controller_settings()) == 0
|
||||
|
||||
|
||||
def test_import_computes_1_x(controller, controller_config_path, async_run):
|
||||
def test_import_computes_1_x(controller, controller_config_path):
|
||||
"""
|
||||
At first start the server should import the
|
||||
computes from the gns3_gui 1.X
|
||||
"""
|
||||
|
||||
gns3_gui_conf = {
|
||||
"Servers": {
|
||||
"remote_servers": [
|
||||
@@ -106,43 +110,46 @@ def test_import_computes_1_x(controller, controller_config_path, async_run):
|
||||
assert compute.password is None
|
||||
|
||||
|
||||
def test_load_projects(controller, projects_dir, async_run):
|
||||
controller.save()
|
||||
async def test_load_projects(controller, projects_dir):
|
||||
|
||||
controller.save()
|
||||
os.makedirs(os.path.join(projects_dir, "project1"))
|
||||
with open(os.path.join(projects_dir, "project1", "project1.gns3"), "w+") as f:
|
||||
f.write("")
|
||||
with asyncio_patch("gns3server.controller.Controller.load_project") as mock_load_project:
|
||||
async_run(controller.load_projects())
|
||||
await controller.load_projects()
|
||||
mock_load_project.assert_called_with(os.path.join(projects_dir, "project1", "project1.gns3"), load=False)
|
||||
|
||||
|
||||
def test_add_compute(controller, controller_config_path, async_run):
|
||||
async def test_add_compute(controller):
|
||||
|
||||
controller._notification = MagicMock()
|
||||
c = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
c = await controller.add_compute(compute_id="test1", connect=False)
|
||||
controller._notification.controller_emit.assert_called_with("compute.created", c.__json__())
|
||||
assert len(controller.computes) == 1
|
||||
async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
await controller.add_compute(compute_id="test1", connect=False)
|
||||
controller._notification.controller_emit.assert_called_with("compute.updated", c.__json__())
|
||||
assert len(controller.computes) == 1
|
||||
async_run(controller.add_compute(compute_id="test2", connect=False))
|
||||
await controller.add_compute(compute_id="test2", connect=False)
|
||||
assert len(controller.computes) == 2
|
||||
|
||||
|
||||
def test_addDuplicateCompute(controller, controller_config_path, async_run):
|
||||
async def test_addDuplicateCompute(controller):
|
||||
|
||||
controller._notification = MagicMock()
|
||||
c = async_run(controller.add_compute(compute_id="test1", name="Test", connect=False))
|
||||
c = await controller.add_compute(compute_id="test1", name="Test", connect=False)
|
||||
assert len(controller.computes) == 1
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(controller.add_compute(compute_id="test2", name="Test", connect=False))
|
||||
await controller.add_compute(compute_id="test2", name="Test", connect=False)
|
||||
|
||||
|
||||
def test_deleteCompute(controller, controller_config_path, async_run):
|
||||
c = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
async def test_deleteCompute(controller, controller_config_path):
|
||||
|
||||
c = await controller.add_compute(compute_id="test1", connect=False)
|
||||
assert len(controller.computes) == 1
|
||||
controller._notification = MagicMock()
|
||||
c._connected = True
|
||||
async_run(controller.delete_compute("test1"))
|
||||
await controller.delete_compute("test1")
|
||||
assert len(controller.computes) == 0
|
||||
controller._notification.controller_emit.assert_called_with("compute.deleted", c.__json__())
|
||||
with open(controller_config_path) as f:
|
||||
@@ -151,25 +158,26 @@ def test_deleteCompute(controller, controller_config_path, async_run):
|
||||
assert c.connected is False
|
||||
|
||||
|
||||
def test_deleteComputeProjectOpened(controller, controller_config_path, async_run):
|
||||
async def test_deleteComputeProjectOpened(controller, controller_config_path):
|
||||
"""
|
||||
When you delete a compute the project using it are close
|
||||
"""
|
||||
c = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
|
||||
c = await controller.add_compute(compute_id="test1", connect=False)
|
||||
c.post = AsyncioMagicMock()
|
||||
assert len(controller.computes) == 1
|
||||
|
||||
project1 = async_run(controller.add_project(name="Test1"))
|
||||
async_run(project1.open())
|
||||
project1 = await controller.add_project(name="Test1")
|
||||
await project1.open()
|
||||
# We simulate that the project use this compute
|
||||
project1._project_created_on_compute.add(c)
|
||||
|
||||
project2 = async_run(controller.add_project(name="Test2"))
|
||||
async_run(project2.open())
|
||||
project2 = await controller.add_project(name="Test2")
|
||||
await project2.open()
|
||||
|
||||
controller._notification = MagicMock()
|
||||
c._connected = True
|
||||
async_run(controller.delete_compute("test1"))
|
||||
await controller.delete_compute("test1")
|
||||
assert len(controller.computes) == 0
|
||||
controller._notification.controller_emit.assert_called_with("compute.deleted", c.__json__())
|
||||
with open(controller_config_path) as f:
|
||||
@@ -182,8 +190,9 @@ def test_deleteComputeProjectOpened(controller, controller_config_path, async_ru
|
||||
assert project2.status == "opened"
|
||||
|
||||
|
||||
def test_addComputeConfigFile(controller, controller_config_path, async_run):
|
||||
async_run(controller.add_compute(compute_id="test1", name="Test", connect=False))
|
||||
async def test_addComputeConfigFile(controller, controller_config_path):
|
||||
|
||||
await controller.add_compute(compute_id="test1", name="Test", connect=False)
|
||||
assert len(controller.computes) == 1
|
||||
with open(controller_config_path) as f:
|
||||
data = json.load(f)
|
||||
@@ -200,170 +209,180 @@ def test_addComputeConfigFile(controller, controller_config_path, async_run):
|
||||
]
|
||||
|
||||
|
||||
def test_getCompute(controller, async_run):
|
||||
compute = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
async def test_getCompute(controller):
|
||||
|
||||
compute = await controller.add_compute(compute_id="test1", connect=False)
|
||||
assert controller.get_compute("test1") == compute
|
||||
with pytest.raises(aiohttp.web.HTTPNotFound):
|
||||
assert controller.get_compute("dsdssd")
|
||||
|
||||
|
||||
def test_has_compute(controller, async_run):
|
||||
compute = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
async def test_has_compute(controller):
|
||||
|
||||
await controller.add_compute(compute_id="test1", connect=False)
|
||||
assert controller.has_compute("test1")
|
||||
assert not controller.has_compute("test2")
|
||||
|
||||
|
||||
def test_add_project(controller, async_run):
|
||||
async def test_add_project(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
uuid2 = str(uuid.uuid4())
|
||||
|
||||
async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert len(controller.projects) == 1
|
||||
async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert len(controller.projects) == 1
|
||||
async_run(controller.add_project(project_id=uuid2, name="Test 2"))
|
||||
await controller.add_project(project_id=uuid2, name="Test 2")
|
||||
assert len(controller.projects) == 2
|
||||
|
||||
|
||||
def test_addDuplicateProject(controller, async_run):
|
||||
async def test_addDuplicateProject(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
uuid2 = str(uuid.uuid4())
|
||||
|
||||
async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert len(controller.projects) == 1
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(controller.add_project(project_id=uuid2, name="Test"))
|
||||
await controller.add_project(project_id=uuid2, name="Test")
|
||||
|
||||
|
||||
def test_remove_project(controller, async_run):
|
||||
async def test_remove_project(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
|
||||
project1 = async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
project1 = await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert len(controller.projects) == 1
|
||||
|
||||
controller.remove_project(project1)
|
||||
assert len(controller.projects) == 0
|
||||
|
||||
|
||||
def test_addProject_with_compute(controller, async_run):
|
||||
uuid1 = str(uuid.uuid4())
|
||||
async def test_addProject_with_compute(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
compute = Compute("test1", controller=MagicMock())
|
||||
compute.post = MagicMock()
|
||||
controller._computes = {"test1": compute}
|
||||
|
||||
project1 = async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
await controller.add_project(project_id=uuid1, name="Test")
|
||||
|
||||
|
||||
def test_getProject(controller, async_run):
|
||||
async def test_getProject(controller):
|
||||
|
||||
uuid1 = str(uuid.uuid4())
|
||||
|
||||
project = async_run(controller.add_project(project_id=uuid1, name="Test"))
|
||||
project = await controller.add_project(project_id=uuid1, name="Test")
|
||||
assert controller.get_project(uuid1) == project
|
||||
with pytest.raises(aiohttp.web.HTTPNotFound):
|
||||
assert controller.get_project("dsdssd")
|
||||
|
||||
|
||||
def test_start(controller, async_run):
|
||||
async def test_start(controller):
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": False,
|
||||
"engine": "vmware",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock:
|
||||
async_run(controller.start())
|
||||
await controller.start()
|
||||
assert mock.called
|
||||
assert len(controller.computes) == 1 # Local compute is created
|
||||
assert controller.computes["local"].name == socket.gethostname()
|
||||
|
||||
|
||||
def test_start_vm(controller, async_run):
|
||||
async def test_start_vm(controller):
|
||||
"""
|
||||
Start the controller with a GNS3 VM
|
||||
"""
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start") as mock:
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network") as mock_check_network:
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock_connect:
|
||||
async_run(controller.start())
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network"):
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.connect"):
|
||||
await controller.start()
|
||||
assert mock.called
|
||||
assert "local" in controller.computes
|
||||
assert "vm" in controller.computes
|
||||
assert len(controller.computes) == 2 # Local compute and vm are created
|
||||
|
||||
|
||||
def test_stop(controller, async_run):
|
||||
c = async_run(controller.add_compute(compute_id="test1", connect=False))
|
||||
async def test_stop(controller):
|
||||
|
||||
c = await controller.add_compute(compute_id="test1", connect=False)
|
||||
c._connected = True
|
||||
async_run(controller.stop())
|
||||
await controller.stop()
|
||||
assert c.connected is False
|
||||
|
||||
|
||||
def test_stop_vm(controller, async_run):
|
||||
async def test_stop_vm(controller):
|
||||
"""
|
||||
Stop GNS3 VM if configured
|
||||
"""
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"when_exit": "stop",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
controller.gns3vm.current_engine().running = True
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.stop") as mock:
|
||||
async_run(controller.stop())
|
||||
await controller.stop()
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_suspend_vm(controller, async_run):
|
||||
async def test_suspend_vm(controller):
|
||||
"""
|
||||
Suspend GNS3 VM if configured
|
||||
"""
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"when_exit": "suspend",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
controller.gns3vm.current_engine().running = True
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.suspend") as mock:
|
||||
async_run(controller.stop())
|
||||
await controller.stop()
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_keep_vm(controller, async_run):
|
||||
async def test_keep_vm(controller):
|
||||
"""
|
||||
Keep GNS3 VM if configured
|
||||
"""
|
||||
|
||||
controller.gns3vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"when_exit": "keep",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
controller.gns3vm.current_engine().running = True
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.suspend") as mock:
|
||||
async_run(controller.stop())
|
||||
await controller.stop()
|
||||
assert not mock.called
|
||||
|
||||
|
||||
def test_get_free_project_name(controller, async_run):
|
||||
async def test_get_free_project_name(controller):
|
||||
|
||||
async_run(controller.add_project(project_id=str(uuid.uuid4()), name="Test"))
|
||||
await controller.add_project(project_id=str(uuid.uuid4()), name="Test")
|
||||
assert controller.get_free_project_name("Test") == "Test-1"
|
||||
async_run(controller.add_project(project_id=str(uuid.uuid4()), name="Test-1"))
|
||||
await controller.add_project(project_id=str(uuid.uuid4()), name="Test-1")
|
||||
assert controller.get_free_project_name("Test") == "Test-2"
|
||||
assert controller.get_free_project_name("Hello") == "Hello"
|
||||
|
||||
|
||||
def test_load_base_files(controller, config, tmpdir):
|
||||
config.set_section_config("Server", {"configs_path": str(tmpdir)})
|
||||
async def test_load_base_files(controller, config, tmpdir):
|
||||
|
||||
config.set_section_config("Server", {"configs_path": str(tmpdir)})
|
||||
with open(str(tmpdir / 'iou_l2_base_startup-config.txt'), 'w+') as f:
|
||||
f.write('test')
|
||||
|
||||
@@ -375,7 +394,8 @@ def test_load_base_files(controller, config, tmpdir):
|
||||
assert f.read() == 'test'
|
||||
|
||||
|
||||
def test_appliances(controller, async_run, tmpdir):
|
||||
def test_appliances(controller, tmpdir):
|
||||
|
||||
my_appliance = {
|
||||
"name": "My Appliance",
|
||||
"status": "stable"
|
||||
@@ -406,6 +426,7 @@ def test_appliances(controller, async_run, tmpdir):
|
||||
|
||||
|
||||
def test_load_templates(controller):
|
||||
|
||||
controller._settings = {}
|
||||
controller.template_manager.load_templates()
|
||||
|
||||
@@ -430,10 +451,11 @@ def test_load_templates(controller):
|
||||
assert cloud_uuid == template.id
|
||||
|
||||
|
||||
def test_autoidlepc(controller, async_run):
|
||||
async def test_autoidlepc(controller):
|
||||
|
||||
controller._computes["local"] = AsyncioMagicMock()
|
||||
node_mock = AsyncioMagicMock()
|
||||
with asyncio_patch("gns3server.controller.Project.add_node", return_value=node_mock):
|
||||
async_run(controller.autoidlepc("local", "c7200", "test.bin", 512))
|
||||
await controller.autoidlepc("local", "c7200", "test.bin", 512)
|
||||
assert node_mock.dynamips_auto_idlepc.called
|
||||
assert len(controller.projects) == 0
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -22,33 +22,30 @@ import os
|
||||
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
|
||||
from gns3server.controller.drawing import Drawing
|
||||
from gns3server.controller.project import Project
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller, async_run):
|
||||
return async_run(controller.add_project(name="Test"))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def drawing(project):
|
||||
|
||||
return Drawing(project, None, svg="<svg></svg>")
|
||||
|
||||
|
||||
def test_init_without_uuid(project):
|
||||
|
||||
drawing = Drawing(project, None, svg="<svg></svg>")
|
||||
assert drawing.id is not None
|
||||
|
||||
|
||||
def test_init_with_uuid(project):
|
||||
|
||||
id = str(uuid.uuid4())
|
||||
drawing = Drawing(project, id, svg="<svg></svg>")
|
||||
assert drawing.id == id
|
||||
|
||||
|
||||
def test_json(project):
|
||||
|
||||
i = Drawing(project, None, svg="<svg></svg>")
|
||||
assert i.__json__() == {
|
||||
"drawing_id": i.id,
|
||||
@@ -71,11 +68,12 @@ def test_json(project):
|
||||
}
|
||||
|
||||
|
||||
def test_update(drawing, project, async_run, controller):
|
||||
async def test_update(drawing, project, controller):
|
||||
|
||||
controller._notification = AsyncioMagicMock()
|
||||
project.dump = MagicMock()
|
||||
|
||||
async_run(drawing.update(x=42, svg="<svg><rect></rect></svg>"))
|
||||
await drawing.update(x=42, svg="<svg><rect></rect></svg>")
|
||||
assert drawing.x == 42
|
||||
args, kwargs = controller._notification.project_emit.call_args
|
||||
assert args[0] == "drawing.updated"
|
||||
@@ -83,7 +81,7 @@ def test_update(drawing, project, async_run, controller):
|
||||
assert args[1]["x"] == 42
|
||||
assert args[1]["svg"] == "<svg><rect></rect></svg>"
|
||||
|
||||
async_run(drawing.update(x=12, svg="<svg><rect></rect></svg>"))
|
||||
await drawing.update(x=12, svg="<svg><rect></rect></svg>")
|
||||
assert drawing.x == 12
|
||||
args, kwargs = controller._notification.project_emit.call_args
|
||||
assert args[0] == "drawing.updated"
|
||||
@@ -99,6 +97,7 @@ def test_image_base64(project):
|
||||
"""
|
||||
If image are embed as base 64 we need to dump them on disk
|
||||
"""
|
||||
|
||||
svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" height=\"128\" width=\"128\">\n<image height=\"128\" width=\"128\" xlink:href=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAN2AAADdgF91YLMAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAHm5JREFUeJztnXl8FGXSx7/VIYAKKCoe4IEIq6ALuQnI4YXXKihulCSACIIsu4qKNyqXByqK67EeiMtyJGrwXnfABSu/L3I31aclPub3oBIQ/YD2zdUBZ+T37l7Dt0OAKoIYcUf07mBhpkieonJe+FcAUOgeX8dL/4ysTCSmTiwwsx1FPLJfuas89mXsByu/N/BR43E09+xMafDrYFI6wmzINu7QreFo1kD4EQIW/m8ICm1iAdBXWp0wuusiJp+Q7ilok3VE02RR+MoWPTYMXTYNlarAx6c6iQU7X/RbQ4DZA2m1F44CnrdYjDPG8ZcLBe/1kzz2Z9ybfUZQALAS\" />\n</svg>"
|
||||
|
||||
drawing = Drawing(project, None, svg=svg)
|
||||
@@ -112,6 +111,7 @@ def test_image_svg(project):
|
||||
"""
|
||||
Large SVG are dump on disk
|
||||
"""
|
||||
|
||||
svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" height=\"128\" width=\"128\">\n"
|
||||
|
||||
for i in range(0, 1000):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -33,14 +33,16 @@ from gns3server.utils.asyncio import aiozipstream
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
async def project(loop, controller):
|
||||
|
||||
p = Project(controller=controller, name="test")
|
||||
p.dump = MagicMock()
|
||||
return p
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(controller, project, async_run):
|
||||
async def node(controller, project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
|
||||
@@ -48,7 +50,7 @@ def node(controller, project, async_run):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
return node
|
||||
|
||||
|
||||
@@ -60,6 +62,7 @@ async def write_file(path, z):
|
||||
|
||||
|
||||
def test_exportable_files():
|
||||
|
||||
assert _is_exportable("hello/world")
|
||||
assert not _is_exportable("project-files/tmp")
|
||||
assert not _is_exportable("project-files/test_log.txt")
|
||||
@@ -69,7 +72,8 @@ def test_exportable_files():
|
||||
assert not _is_exportable("test/project-files/snapshots/test.gns3p")
|
||||
|
||||
|
||||
def test_export(tmpdir, project, async_run):
|
||||
async def test_export(tmpdir, project):
|
||||
|
||||
path = project.path
|
||||
os.makedirs(os.path.join(path, "vm-1", "dynamips"))
|
||||
|
||||
@@ -113,8 +117,8 @@ def test_export(tmpdir, project, async_run):
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
|
||||
async_run(export_project(z, project, str(tmpdir), include_images=False))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir), include_images=False)
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("vm-1/dynamips/test") as myfile:
|
||||
@@ -134,7 +138,7 @@ def test_export(tmpdir, project, async_run):
|
||||
assert topo["computes"] == []
|
||||
|
||||
|
||||
def test_export_vm(tmpdir, project, async_run):
|
||||
async def test_export_vm(tmpdir, project):
|
||||
"""
|
||||
If data is on a remote server export it locally before
|
||||
sending it in the archive.
|
||||
@@ -147,7 +151,7 @@ def test_export_vm(tmpdir, project, async_run):
|
||||
# Fake file that will be download from the vm
|
||||
mock_response = AsyncioMagicMock()
|
||||
mock_response.content = AsyncioBytesIO()
|
||||
async_run(mock_response.content.write(b"HELLO"))
|
||||
await mock_response.content.write(b"HELLO")
|
||||
mock_response.content.seek(0)
|
||||
compute.download_file = AsyncioMagicMock(return_value=mock_response)
|
||||
|
||||
@@ -161,9 +165,9 @@ def test_export_vm(tmpdir, project, async_run):
|
||||
f.write("{}")
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir)))
|
||||
await export_project(z, project, str(tmpdir))
|
||||
assert compute.list_files.called
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("vm-1/dynamips/test") as myfile:
|
||||
@@ -171,7 +175,7 @@ def test_export_vm(tmpdir, project, async_run):
|
||||
assert content == b"HELLO"
|
||||
|
||||
|
||||
def test_export_disallow_running(tmpdir, project, node, async_run):
|
||||
async def test_export_disallow_running(tmpdir, project, node):
|
||||
"""
|
||||
Disallow export when a node is running
|
||||
"""
|
||||
@@ -194,10 +198,10 @@ def test_export_disallow_running(tmpdir, project, node, async_run):
|
||||
node._status = "started"
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir)))
|
||||
await export_project(z, project, str(tmpdir))
|
||||
|
||||
|
||||
def test_export_disallow_some_type(tmpdir, project, async_run):
|
||||
async def test_export_disallow_some_type(tmpdir, project):
|
||||
"""
|
||||
Disallow export for some node type
|
||||
"""
|
||||
@@ -219,9 +223,9 @@ def test_export_disallow_some_type(tmpdir, project, async_run):
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir)))
|
||||
await export_project(z, project, str(tmpdir))
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), allow_all_nodes=True))
|
||||
await export_project(z, project, str(tmpdir), allow_all_nodes=True)
|
||||
|
||||
# VirtualBox is always disallowed
|
||||
topology = {
|
||||
@@ -240,10 +244,10 @@ def test_export_disallow_some_type(tmpdir, project, async_run):
|
||||
json.dump(topology, f)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), allow_all_nodes=True))
|
||||
await export_project(z, project, str(tmpdir), allow_all_nodes=True)
|
||||
|
||||
|
||||
def test_export_fix_path(tmpdir, project, async_run):
|
||||
async def test_export_fix_path(tmpdir, project):
|
||||
"""
|
||||
Fix absolute image path, except for Docker
|
||||
"""
|
||||
@@ -273,8 +277,8 @@ def test_export_fix_path(tmpdir, project, async_run):
|
||||
json.dump(topology, f)
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir)))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir))
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("project.gns3") as myfile:
|
||||
@@ -284,7 +288,7 @@ def test_export_fix_path(tmpdir, project, async_run):
|
||||
assert topology["topology"]["nodes"][1]["properties"]["image"] == "gns3/webterm:lastest"
|
||||
|
||||
|
||||
def test_export_with_images(tmpdir, project, async_run):
|
||||
async def test_export_with_images(tmpdir, project):
|
||||
"""
|
||||
Fix absolute image path
|
||||
"""
|
||||
@@ -312,14 +316,14 @@ def test_export_with_images(tmpdir, project, async_run):
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
|
||||
async_run(export_project(z, project, str(tmpdir), include_images=True))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir), include_images=True)
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
myzip.getinfo("images/IOS/test.image")
|
||||
|
||||
|
||||
def test_export_keep_compute_id(tmpdir, project, async_run):
|
||||
async def test_export_keep_compute_id(tmpdir, project):
|
||||
"""
|
||||
If we want to restore the same computes we could ask to keep them
|
||||
in the file
|
||||
@@ -348,8 +352,8 @@ def test_export_keep_compute_id(tmpdir, project, async_run):
|
||||
json.dump(data, f)
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), keep_compute_id=True))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir), keep_compute_id=True)
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("project.gns3") as myfile:
|
||||
@@ -358,7 +362,7 @@ def test_export_keep_compute_id(tmpdir, project, async_run):
|
||||
assert len(topo["computes"]) == 1
|
||||
|
||||
|
||||
def test_export_images_from_vm(tmpdir, project, async_run):
|
||||
async def test_export_images_from_vm(tmpdir, project):
|
||||
"""
|
||||
If data is on a remote server export it locally before
|
||||
sending it in the archive.
|
||||
@@ -366,22 +370,19 @@ def test_export_images_from_vm(tmpdir, project, async_run):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "vm"
|
||||
compute.list_files = AsyncioMagicMock(return_value=[
|
||||
{"path": "vm-1/dynamips/test"}
|
||||
])
|
||||
compute.list_files = AsyncioMagicMock(return_value=[{"path": "vm-1/dynamips/test"}])
|
||||
|
||||
# Fake file that will be download from the vm
|
||||
mock_response = AsyncioMagicMock()
|
||||
mock_response.content = AsyncioBytesIO()
|
||||
async_run(mock_response.content.write(b"HELLO"))
|
||||
await mock_response.content.write(b"HELLO")
|
||||
mock_response.content.seek(0)
|
||||
mock_response.status = 200
|
||||
compute.download_file = AsyncioMagicMock(return_value=mock_response)
|
||||
|
||||
|
||||
mock_response = AsyncioMagicMock()
|
||||
mock_response.content = AsyncioBytesIO()
|
||||
async_run(mock_response.content.write(b"IMAGE"))
|
||||
await mock_response.content.write(b"IMAGE")
|
||||
mock_response.content.seek(0)
|
||||
mock_response.status = 200
|
||||
compute.download_image = AsyncioMagicMock(return_value=mock_response)
|
||||
@@ -411,9 +412,9 @@ def test_export_images_from_vm(tmpdir, project, async_run):
|
||||
f.write(json.dumps(topology))
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), include_images=True))
|
||||
await export_project(z, project, str(tmpdir), include_images=True)
|
||||
assert compute.list_files.called
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
with myzip.open("vm-1/dynamips/test") as myfile:
|
||||
@@ -425,7 +426,8 @@ def test_export_images_from_vm(tmpdir, project, async_run):
|
||||
assert content == b"IMAGE"
|
||||
|
||||
|
||||
def test_export_with_ignoring_snapshots(tmpdir, project, async_run):
|
||||
async def test_export_with_ignoring_snapshots(tmpdir, project):
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3"), 'w+') as f:
|
||||
data = {
|
||||
"topology": {
|
||||
@@ -454,8 +456,8 @@ def test_export_with_ignoring_snapshots(tmpdir, project, async_run):
|
||||
Path(os.path.join(snapshots_dir, 'snap.gns3project')).touch()
|
||||
|
||||
with aiozipstream.ZipFile() as z:
|
||||
async_run(export_project(z, project, str(tmpdir), keep_compute_id=True))
|
||||
async_run(write_file(str(tmpdir / 'zipfile.zip'), z))
|
||||
await export_project(z, project, str(tmpdir), keep_compute_id=True)
|
||||
await write_file(str(tmpdir / 'zipfile.zip'), z)
|
||||
|
||||
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
|
||||
assert not os.path.join('snapshots', 'snap.gns3project') in [f.filename for f in myzip.filelist]
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -24,6 +24,7 @@ from gns3server.controller.gns3vm.gns3_vm_error import GNS3VMError
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_engine():
|
||||
|
||||
engine = AsyncioMagicMock()
|
||||
engine.running = False
|
||||
engine.ip_address = "vm.local"
|
||||
@@ -36,6 +37,7 @@ def dummy_engine():
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_gns3vm(controller, dummy_engine):
|
||||
|
||||
vm = GNS3VM(controller)
|
||||
vm._settings["engine"] = "dummy"
|
||||
vm._settings["vmname"] = "Test VM"
|
||||
@@ -44,46 +46,49 @@ def dummy_gns3vm(controller, dummy_engine):
|
||||
return vm
|
||||
|
||||
|
||||
def test_list(async_run, controller):
|
||||
vm = GNS3VM(controller)
|
||||
async def test_list(controller):
|
||||
|
||||
vm = GNS3VM(controller)
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.list", return_value=[{"vmname": "test", "vmx_path": "test"}]):
|
||||
res = async_run(vm.list("vmware"))
|
||||
assert res == [{"vmname": "test"}] # Informations specific to vmware are stripped
|
||||
res = await vm.list("vmware")
|
||||
assert res == [{"vmname": "test"}] # Information specific to VMware is stripped
|
||||
with asyncio_patch("gns3server.controller.gns3vm.virtualbox_gns3_vm.VirtualBoxGNS3VM.list", return_value=[{"vmname": "test"}]):
|
||||
res = async_run(vm.list("virtualbox"))
|
||||
res = await vm.list("virtualbox")
|
||||
assert res == [{"vmname": "test"}]
|
||||
with pytest.raises(NotImplementedError):
|
||||
async_run(vm.list("hyperv"))
|
||||
await vm.list("hyperv")
|
||||
|
||||
|
||||
def test_json(controller):
|
||||
|
||||
vm = GNS3VM(controller)
|
||||
assert vm.__json__() == vm._settings
|
||||
|
||||
|
||||
def test_update_settings(controller, async_run):
|
||||
async def test_update_settings(controller):
|
||||
|
||||
vm = GNS3VM(controller)
|
||||
vm.settings = {
|
||||
"enable": True,
|
||||
"engine": "vmware",
|
||||
"vmname": "GNS3 VM"
|
||||
}
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start"):
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network") as mock_check_network:
|
||||
async_run(vm.auto_start_vm())
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network"):
|
||||
await vm.auto_start_vm()
|
||||
assert "vm" in controller.computes
|
||||
async_run(vm.update_settings({"enable": False}))
|
||||
await vm.update_settings({"enable": False})
|
||||
assert "vm" not in controller.computes
|
||||
|
||||
|
||||
def test_auto_start(async_run, controller, dummy_gns3vm, dummy_engine):
|
||||
async def test_auto_start(controller, dummy_gns3vm, dummy_engine):
|
||||
"""
|
||||
When start the compute should be add to the controller
|
||||
"""
|
||||
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network") as mock_check_network:
|
||||
async_run(dummy_gns3vm.auto_start_vm())
|
||||
with asyncio_patch("gns3server.controller.gns3vm.GNS3VM._check_network"):
|
||||
await dummy_gns3vm.auto_start_vm()
|
||||
assert dummy_engine.start.called
|
||||
assert controller.computes["vm"].name == "GNS3 VM (Test VM)"
|
||||
assert controller.computes["vm"].host == "vm.local"
|
||||
@@ -93,9 +98,9 @@ def test_auto_start(async_run, controller, dummy_gns3vm, dummy_engine):
|
||||
assert controller.computes["vm"].password == "world"
|
||||
|
||||
|
||||
def test_auto_start_with_error(async_run, controller, dummy_gns3vm, dummy_engine):
|
||||
dummy_engine.start.side_effect = GNS3VMError("Dummy error")
|
||||
async def test_auto_start_with_error(controller, dummy_gns3vm, dummy_engine):
|
||||
|
||||
async_run(dummy_gns3vm.auto_start_vm())
|
||||
dummy_engine.start.side_effect = GNS3VMError("Dummy error")
|
||||
await dummy_gns3vm.auto_start_vm()
|
||||
assert dummy_engine.start.called
|
||||
assert controller.computes["vm"].name == "GNS3 VM (Test VM)"
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -20,18 +20,15 @@ import uuid
|
||||
import json
|
||||
import zipfile
|
||||
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.import_project import import_project, _move_files_to_compute
|
||||
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
||||
def test_import_project(async_run, tmpdir, controller):
|
||||
project_id = str(uuid.uuid4())
|
||||
async def test_import_project(tmpdir, controller):
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@@ -55,7 +52,7 @@ def test_import_project(async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "b.png"), "project-files/qemu/test")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
assert project.name == "test"
|
||||
assert project.id == project_id
|
||||
@@ -68,19 +65,19 @@ def test_import_project(async_run, tmpdir, controller):
|
||||
|
||||
# A new project name is generated when you import twice the same name
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, str(uuid.uuid4()), f))
|
||||
project = await import_project(controller, str(uuid.uuid4()), f)
|
||||
assert project.auto_open is False
|
||||
assert project.auto_start is False
|
||||
assert project.name != "test"
|
||||
|
||||
|
||||
def test_import_project_override(async_run, tmpdir, controller):
|
||||
async def test_import_project_override(tmpdir, controller):
|
||||
"""
|
||||
In the case of snapshot we will import a project for
|
||||
override the previous keeping the same project id & location
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": project_id,
|
||||
"name": "test",
|
||||
@@ -97,24 +94,24 @@ def test_import_project_override(async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f, location=str(tmpdir)))
|
||||
project = await import_project(controller, project_id, f, location=str(tmpdir))
|
||||
|
||||
assert project.name == "test"
|
||||
assert project.id == project_id
|
||||
|
||||
# Overide the project with same project
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f, location=str(tmpdir)))
|
||||
project = await import_project(controller, project_id, f, location=str(tmpdir))
|
||||
assert project.id == project_id
|
||||
assert project.name == "test"
|
||||
|
||||
|
||||
def test_import_upgrade(async_run, tmpdir, controller):
|
||||
async def test_import_upgrade(tmpdir, controller):
|
||||
"""
|
||||
Topology made for previous GNS3 version are upgraded during the process
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@@ -131,17 +128,16 @@ def test_import_upgrade(async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["version"] == __version__
|
||||
|
||||
|
||||
def test_import_with_images(tmpdir, async_run, controller):
|
||||
async def test_import_with_images(tmpdir, controller):
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@@ -162,7 +158,7 @@ def test_import_with_images(tmpdir, async_run, controller):
|
||||
myzip.write(str(tmpdir / "test.image"), "images/IOS/test.image")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
assert not os.path.exists(os.path.join(project.path, "images/IOS/test.image"))
|
||||
|
||||
@@ -170,12 +166,12 @@ def test_import_with_images(tmpdir, async_run, controller):
|
||||
assert os.path.exists(path), path
|
||||
|
||||
|
||||
def test_import_iou_linux_no_vm(linux_platform, async_run, tmpdir, controller):
|
||||
async def test_import_iou_linux_no_vm(linux_platform, tmpdir, controller):
|
||||
"""
|
||||
On non linux host IOU should be local if we don't have a GNS3 VM
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["local"] = AsyncioMagicMock()
|
||||
|
||||
topology = {
|
||||
@@ -207,17 +203,18 @@ def test_import_iou_linux_no_vm(linux_platform, async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["topology"]["nodes"][0]["compute_id"] == "local"
|
||||
|
||||
|
||||
def test_import_iou_linux_with_vm(linux_platform, async_run, tmpdir, controller):
|
||||
async def test_import_iou_linux_with_vm(linux_platform, tmpdir, controller):
|
||||
"""
|
||||
On non linux host IOU should be vm if we have a GNS3 VM configured
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["vm"] = AsyncioMagicMock()
|
||||
|
||||
@@ -251,17 +248,18 @@ def test_import_iou_linux_with_vm(linux_platform, async_run, tmpdir, controller)
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["topology"]["nodes"][0]["compute_id"] == "vm"
|
||||
|
||||
|
||||
def test_import_nat_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
async def test_import_nat_non_linux(windows_platform, tmpdir, controller):
|
||||
"""
|
||||
On non linux host NAT should be moved to the GNS3 VM
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["vm"] = AsyncioMagicMock()
|
||||
|
||||
@@ -295,17 +293,18 @@ def test_import_nat_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["topology"]["nodes"][0]["compute_id"] == "vm"
|
||||
|
||||
|
||||
def test_import_iou_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
async def test_import_iou_non_linux(windows_platform, tmpdir, controller):
|
||||
"""
|
||||
On non linux host IOU should be moved to the GNS3 VM
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["vm"] = AsyncioMagicMock()
|
||||
|
||||
@@ -346,7 +345,7 @@ def test_import_iou_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
with asyncio_patch("gns3server.controller.import_project._move_files_to_compute") as mock:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
controller._computes["vm"].post.assert_called_with('/projects', data={'name': 'test', 'project_id': project_id})
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
@@ -357,12 +356,12 @@ def test_import_iou_non_linux(windows_platform, async_run, tmpdir, controller):
|
||||
mock.assert_called_with(controller._computes["vm"], project_id, project.path, os.path.join('project-files', 'iou', topo["topology"]["nodes"][0]['node_id']))
|
||||
|
||||
|
||||
def test_import_node_id(linux_platform, async_run, tmpdir, controller):
|
||||
async def test_import_node_id(linux_platform, tmpdir, controller):
|
||||
"""
|
||||
When importing a node, node_id should change
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["local"] = AsyncioMagicMock()
|
||||
|
||||
topology = {
|
||||
@@ -429,7 +428,7 @@ def test_import_node_id(linux_platform, async_run, tmpdir, controller):
|
||||
myzip.writestr("project-files/iou/c3ae286c-c81f-40d9-a2d0-5874b2f2478d/startup.cfg", "test")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f))
|
||||
project = await import_project(controller, project_id, f)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
@@ -450,10 +449,11 @@ def test_import_node_id(linux_platform, async_run, tmpdir, controller):
|
||||
assert os.path.exists(os.path.join(project.path, "project-files", "iou", topo["topology"]["nodes"][0]["node_id"], "startup.cfg"))
|
||||
|
||||
|
||||
def test_import_keep_compute_id(windows_platform, async_run, tmpdir, controller):
|
||||
async def test_import_keep_compute_id(windows_platform, tmpdir, controller):
|
||||
"""
|
||||
On linux host IOU should be moved to the GNS3 VM
|
||||
"""
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
controller._computes["vm"] = AsyncioMagicMock()
|
||||
|
||||
@@ -487,14 +487,15 @@ def test_import_keep_compute_id(windows_platform, async_run, tmpdir, controller)
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f, keep_compute_id=True))
|
||||
project = await import_project(controller, project_id, f, keep_compute_id=True)
|
||||
|
||||
with open(os.path.join(project.path, "test.gns3")) as f:
|
||||
topo = json.load(f)
|
||||
assert topo["topology"]["nodes"][0]["compute_id"] == "local"
|
||||
|
||||
|
||||
def test_move_files_to_compute(tmpdir, async_run):
|
||||
async def test_move_files_to_compute(tmpdir):
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
os.makedirs(str(tmpdir / "project-files" / "docker"))
|
||||
@@ -502,19 +503,19 @@ def test_move_files_to_compute(tmpdir, async_run):
|
||||
(tmpdir / "project-files" / "docker" / "test2").open("w").close()
|
||||
|
||||
with asyncio_patch("gns3server.controller.import_project._upload_file") as mock:
|
||||
async_run(_move_files_to_compute(None, project_id, str(tmpdir), os.path.join("project-files", "docker")))
|
||||
await _move_files_to_compute(None, project_id, str(tmpdir), os.path.join("project-files", "docker"))
|
||||
|
||||
mock.assert_any_call(None, project_id, str(tmpdir / "project-files" / "docker" / "test"), os.path.join("project-files", "docker", "test"))
|
||||
mock.assert_any_call(None, project_id, str(tmpdir / "project-files" / "docker" / "test2"), os.path.join("project-files", "docker", "test2"))
|
||||
assert not os.path.exists(str(tmpdir / "project-files" / "docker"))
|
||||
|
||||
|
||||
def test_import_project_name_and_location(async_run, tmpdir, controller):
|
||||
async def test_import_project_name_and_location(tmpdir, controller):
|
||||
"""
|
||||
Import a project with a different location and name
|
||||
"""
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
topology = {
|
||||
"project_id": str(uuid.uuid4()),
|
||||
"name": "test",
|
||||
@@ -531,7 +532,7 @@ def test_import_project_name_and_location(async_run, tmpdir, controller):
|
||||
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
|
||||
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, project_id, f, name="hello", location=str(tmpdir / "hello")))
|
||||
project = await import_project(controller, project_id, f, name="hello", location=str(tmpdir / "hello"))
|
||||
|
||||
assert project.name == "hello"
|
||||
|
||||
@@ -539,5 +540,5 @@ def test_import_project_name_and_location(async_run, tmpdir, controller):
|
||||
|
||||
# A new project name is generated when you import twice the same name
|
||||
with open(zip_path, "rb") as f:
|
||||
project = async_run(import_project(controller, str(uuid.uuid4()), f, name="hello", location=str(tmpdir / "test")))
|
||||
project = await import_project(controller, str(uuid.uuid4()), f, name="hello", location=str(tmpdir / "test"))
|
||||
assert project.name == "hello-1"
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -15,35 +15,20 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
||||
from gns3server.controller.link import Link
|
||||
from gns3server.controller.node import Node
|
||||
from gns3server.controller.ports.ethernet_port import EthernetPort
|
||||
from gns3server.controller.ports.serial_port import SerialPort
|
||||
from gns3server.controller.compute import Compute
|
||||
from gns3server.controller.project import Project
|
||||
|
||||
from tests.utils import AsyncioBytesIO, AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(controller=controller, name="Test")
|
||||
async def link(project, compute):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def compute():
|
||||
return Compute("example.com", controller=MagicMock())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def link(async_run, project, compute):
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
@@ -51,26 +36,27 @@ def link(async_run, project, compute):
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 1, 3))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 1, 3)
|
||||
return link
|
||||
|
||||
|
||||
def test_eq(project, link, controller):
|
||||
def test_eq(project, link):
|
||||
|
||||
assert link == Link(project, link_id=link.id)
|
||||
assert link != "a"
|
||||
assert link != Link(project)
|
||||
|
||||
|
||||
def test_add_node(async_run, project, compute):
|
||||
async def test_add_node(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
project.dump = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
assert link._nodes == [
|
||||
{
|
||||
"node": node1,
|
||||
@@ -85,23 +71,23 @@ def test_add_node(async_run, project, compute):
|
||||
]
|
||||
assert project.dump.called
|
||||
assert not link._project.emit_notification.called
|
||||
|
||||
assert not link.create.called
|
||||
|
||||
# We call link.created only when both side are created
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
assert link.create.called
|
||||
link._project.emit_notification.assert_called_with("link.created", link.__json__())
|
||||
assert link in node2.links
|
||||
|
||||
|
||||
def test_add_node_already_connected(async_run, project, compute):
|
||||
async def test_add_node_already_connected(project, compute):
|
||||
"""
|
||||
Raise an error if we try to use an already connected port
|
||||
"""
|
||||
|
||||
project.dump = AsyncioMagicMock()
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
@@ -110,19 +96,20 @@ def test_add_node_already_connected(async_run, project, compute):
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
assert link.create.called
|
||||
link2 = Link(project)
|
||||
link2.create = AsyncioMagicMock()
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link2.add_node(node1, 0, 4))
|
||||
await link2.add_node(node1, 0, 4)
|
||||
|
||||
|
||||
def test_add_node_cloud(async_run, project, compute):
|
||||
async def test_add_node_cloud(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="cloud")
|
||||
@@ -132,14 +119,15 @@ def test_add_node_cloud(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
|
||||
def test_add_node_cloud_to_cloud(async_run, project, compute):
|
||||
async def test_add_node_cloud_to_cloud(project, compute):
|
||||
"""
|
||||
Cloud to cloud connection is not allowed
|
||||
"""
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="cloud")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="cloud")
|
||||
@@ -149,15 +137,16 @@ def test_add_node_cloud_to_cloud(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
|
||||
def test_add_node_same_node(async_run, project, compute):
|
||||
async def test_add_node_same_node(project, compute):
|
||||
"""
|
||||
Connection to the same node is not allowed
|
||||
"""
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4), EthernetPort("E1", 0, 0, 5)]
|
||||
|
||||
@@ -165,15 +154,16 @@ def test_add_node_same_node(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link.add_node(node1, 0, 5))
|
||||
await link.add_node(node1, 0, 5)
|
||||
|
||||
|
||||
def test_add_node_serial_to_ethernet(async_run, project, compute):
|
||||
async def test_add_node_serial_to_ethernet(project, compute):
|
||||
"""
|
||||
Serial to ethernet connection is not allowed
|
||||
"""
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
@@ -183,12 +173,13 @@ def test_add_node_serial_to_ethernet(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
|
||||
def test_json(async_run, project, compute, link):
|
||||
async def test_json(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
@@ -196,8 +187,8 @@ def test_json(async_run, project, compute, link):
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 1, 3))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 1, 3)
|
||||
assert link.__json__() == {
|
||||
"link_id": link.id,
|
||||
"project_id": project.id,
|
||||
@@ -256,7 +247,8 @@ def test_json(async_run, project, compute, link):
|
||||
}
|
||||
|
||||
|
||||
def test_json_serial_link(async_run, project, compute, link):
|
||||
async def test_json_serial_link(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [SerialPort("S0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
@@ -264,11 +256,13 @@ def test_json_serial_link(async_run, project, compute, link):
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 1, 3))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 1, 3)
|
||||
assert link.__json__()["link_type"] == "serial"
|
||||
|
||||
def test_default_capture_file_name(project, compute, async_run):
|
||||
|
||||
async def test_default_capture_file_name(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "Hello@", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node2 = Node(project, compute, "w0.rld", node_type="qemu")
|
||||
@@ -276,33 +270,35 @@ def test_default_capture_file_name(project, compute, async_run):
|
||||
|
||||
link = Link(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 1, 3))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 1, 3)
|
||||
assert link.default_capture_file_name() == "Hello_0-4_to_w0rld_1-3.pcap"
|
||||
|
||||
|
||||
def test_start_capture(link, async_run, tmpdir):
|
||||
async def test_start_capture(link):
|
||||
|
||||
async def fake_reader():
|
||||
return AsyncioBytesIO()
|
||||
|
||||
link.read_pcap_from_source = fake_reader
|
||||
link._project.emit_notification = MagicMock()
|
||||
async_run(link.start_capture(capture_file_name="test.pcap"))
|
||||
await link.start_capture(capture_file_name="test.pcap")
|
||||
assert link._capturing
|
||||
assert link._capture_file_name == "test.pcap"
|
||||
link._project.emit_notification.assert_called_with("link.updated", link.__json__())
|
||||
|
||||
|
||||
def test_stop_capture(link, async_run, tmpdir):
|
||||
async def test_stop_capture(link):
|
||||
|
||||
link._capturing = True
|
||||
link._project.emit_notification = MagicMock()
|
||||
async_run(link.stop_capture())
|
||||
await link.stop_capture()
|
||||
assert link._capturing is False
|
||||
link._project.emit_notification.assert_called_with("link.updated", link.__json__())
|
||||
|
||||
|
||||
def test_delete(async_run, project, compute):
|
||||
async def test_delete(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
@@ -310,19 +306,18 @@ def test_delete(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
project.dump = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
|
||||
await link.add_node(node2, 0, 4)
|
||||
assert link in node2.links
|
||||
|
||||
async_run(link.delete())
|
||||
await link.delete()
|
||||
assert link not in node2.links
|
||||
|
||||
|
||||
def test_update_filters(async_run, project, compute):
|
||||
async def test_update_filters(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="qemu")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
@@ -330,20 +325,20 @@ def test_update_filters(async_run, project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
link._project.emit_notification = MagicMock()
|
||||
project.dump = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
|
||||
node2 = Node(project, compute, "node2", node_type="qemu")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
|
||||
link.update = AsyncioMagicMock()
|
||||
assert link._created
|
||||
async_run(link.update_filters({
|
||||
await link.update_filters({
|
||||
"packet_loss": [10],
|
||||
"delay": [50, 10],
|
||||
"frequency_drop": [0],
|
||||
"bpf": [" \n "]
|
||||
}))
|
||||
})
|
||||
assert link.filters == {
|
||||
"packet_loss": [10],
|
||||
"delay": [50, 10]
|
||||
@@ -351,7 +346,8 @@ def test_update_filters(async_run, project, compute):
|
||||
assert link.update.called
|
||||
|
||||
|
||||
def test_available_filters(async_run, project, compute):
|
||||
async def test_available_filters(project, compute):
|
||||
|
||||
node1 = Node(project, compute, "node1", node_type="ethernet_switch")
|
||||
node1._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
@@ -360,10 +356,10 @@ def test_available_filters(async_run, project, compute):
|
||||
assert link.available_filters() == []
|
||||
|
||||
# Ethernet switch is not supported should return 0 filters
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
assert link.available_filters() == []
|
||||
|
||||
node2 = Node(project, compute, "node2", node_type="vpcs")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
async_run(link.add_node(node2, 0, 4))
|
||||
await link.add_node(node2, 0, 4)
|
||||
assert len(link.available_filters()) > 0
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,15 +16,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import shutil
|
||||
import aiohttp
|
||||
import pytest
|
||||
import uuid
|
||||
import asyncio
|
||||
import copy
|
||||
import os
|
||||
|
||||
from unittest.mock import MagicMock, ANY
|
||||
|
||||
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
from gns3server.controller.node import Node
|
||||
@@ -33,18 +29,15 @@ from gns3server.controller.project import Project
|
||||
|
||||
@pytest.fixture
|
||||
def compute():
|
||||
|
||||
s = AsyncioMagicMock()
|
||||
s.id = "http://test.com:42"
|
||||
return s
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(str(uuid.uuid4()), controller=controller)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(compute, project):
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="vpcs",
|
||||
@@ -57,6 +50,7 @@ def test_name(compute, project):
|
||||
"""
|
||||
If node use a name template generate names
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "PC",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="vpcs",
|
||||
@@ -76,16 +70,13 @@ def test_name(compute, project):
|
||||
properties={"startup_script": "echo test"})
|
||||
assert node.name == "PC2"
|
||||
|
||||
# If we change the name to a name already used we patch the name to a free
|
||||
node.name == "PC1"
|
||||
assert node.name == "PC2"
|
||||
|
||||
|
||||
def test_vmname(compute, project):
|
||||
"""
|
||||
Additionnal properties should be add to the properties
|
||||
field
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "PC",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="virtualbox",
|
||||
@@ -111,6 +102,7 @@ def test_empty_properties(compute, project):
|
||||
|
||||
|
||||
def test_eq(compute, project, node, controller):
|
||||
|
||||
assert node == Node(project, compute, "demo1", node_id=node.id, node_type="qemu")
|
||||
assert node != "a"
|
||||
assert node != Node(project, compute, "demo2", node_id=str(uuid.uuid4()), node_type="qemu")
|
||||
@@ -118,6 +110,7 @@ def test_eq(compute, project, node, controller):
|
||||
|
||||
|
||||
def test_json(node, compute):
|
||||
|
||||
assert node.__json__() == {
|
||||
"compute_id": str(compute.id),
|
||||
"project_id": node.project.id,
|
||||
@@ -156,6 +149,7 @@ def test_json(node, compute):
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
assert node.__json__(topology_dump=True) == {
|
||||
"compute_id": str(compute.id),
|
||||
"node_id": node.id,
|
||||
@@ -188,14 +182,14 @@ def test_init_without_uuid(project, compute):
|
||||
assert node.id is not None
|
||||
|
||||
|
||||
def test_create(node, compute, project, async_run):
|
||||
node._console = 2048
|
||||
async def test_create(node, compute):
|
||||
|
||||
node._console = 2048
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
assert async_run(node.create()) is True
|
||||
assert await node.create() is True
|
||||
data = {
|
||||
"console": 2048,
|
||||
"console_type": "vnc",
|
||||
@@ -208,9 +202,9 @@ def test_create(node, compute, project, async_run):
|
||||
assert node._properties == {"startup_script": "echo test"}
|
||||
|
||||
|
||||
def test_create_image_missing(node, compute, project, async_run):
|
||||
node._console = 2048
|
||||
async def test_create_image_missing(node, compute):
|
||||
|
||||
node._console = 2048
|
||||
node.__calls = 0
|
||||
|
||||
async def resp(*args, **kwargs):
|
||||
@@ -226,13 +220,13 @@ def test_create_image_missing(node, compute, project, async_run):
|
||||
compute.post = AsyncioMagicMock(side_effect=resp)
|
||||
node._upload_missing_image = AsyncioMagicMock(return_value=True)
|
||||
|
||||
assert async_run(node.create()) is True
|
||||
node._upload_missing_image.called is True
|
||||
assert await node.create() is True
|
||||
#assert node._upload_missing_image.called is True
|
||||
|
||||
|
||||
def test_create_base_script(node, config, compute, tmpdir, async_run):
|
||||
async def test_create_base_script(node, config, compute, tmpdir):
|
||||
|
||||
config.set_section_config("Server", {"configs_path": str(tmpdir)})
|
||||
|
||||
with open(str(tmpdir / 'test.txt'), 'w+') as f:
|
||||
f.write('hostname test')
|
||||
|
||||
@@ -243,7 +237,7 @@ def test_create_base_script(node, config, compute, tmpdir, async_run):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
assert async_run(node.create()) is True
|
||||
assert await node.create() is True
|
||||
data = {
|
||||
"console": 2048,
|
||||
"console_type": "vnc",
|
||||
@@ -251,10 +245,11 @@ def test_create_base_script(node, config, compute, tmpdir, async_run):
|
||||
"startup_script": "hostname test",
|
||||
"name": "demo"
|
||||
}
|
||||
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes".format(node.project.id), data=data, timeout=1200)
|
||||
|
||||
|
||||
def test_symbol(node, symbols_dir, controller):
|
||||
def test_symbol(node, symbols_dir):
|
||||
"""
|
||||
Change symbol should change the node size
|
||||
"""
|
||||
@@ -304,14 +299,15 @@ def test_label_with_default_label_font(node):
|
||||
assert node.label["style"] == None #"font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #ff0000;fill-opacity: 1.0;"
|
||||
|
||||
|
||||
def test_update(node, compute, project, async_run, controller):
|
||||
async def test_update(node, compute, project, controller):
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.put = AsyncioMagicMock(return_value=response)
|
||||
controller._notification = AsyncioMagicMock()
|
||||
project.dump = MagicMock()
|
||||
|
||||
async_run(node.update(x=42, console=2048, console_type="vnc", properties={"startup_script": "echo test"}, name="demo"))
|
||||
await node.update(x=42, console=2048, console_type="vnc", properties={"startup_script": "echo test"}, name="demo")
|
||||
data = {
|
||||
"console": 2048,
|
||||
"console_type": "vnc",
|
||||
@@ -326,7 +322,7 @@ def test_update(node, compute, project, async_run, controller):
|
||||
assert project.dump.called
|
||||
|
||||
|
||||
def test_update_properties(node, compute, project, async_run, controller):
|
||||
async def test_update_properties(node, compute, controller):
|
||||
"""
|
||||
properties will be updated by the answer from compute
|
||||
"""
|
||||
@@ -335,7 +331,7 @@ def test_update_properties(node, compute, project, async_run, controller):
|
||||
compute.put = AsyncioMagicMock(return_value=response)
|
||||
controller._notification = AsyncioMagicMock()
|
||||
|
||||
async_run(node.update(x=42, console=2048, console_type="vnc", properties={"startup_script": "hello world"}, name="demo"))
|
||||
await node.update(x=42, console=2048, console_type="vnc", properties={"startup_script": "hello world"}, name="demo")
|
||||
data = {
|
||||
"console": 2048,
|
||||
"console_type": "vnc",
|
||||
@@ -354,26 +350,27 @@ def test_update_properties(node, compute, project, async_run, controller):
|
||||
#controller._notification.emit.assert_called_with("node.updated", node_notif)
|
||||
|
||||
|
||||
def test_update_only_controller(node, controller, compute, async_run):
|
||||
async def test_update_only_controller(node, compute):
|
||||
"""
|
||||
When updating property used only on controller we don't need to
|
||||
call the compute
|
||||
"""
|
||||
|
||||
compute.put = AsyncioMagicMock()
|
||||
node._project.emit_notification = AsyncioMagicMock()
|
||||
|
||||
async_run(node.update(x=42))
|
||||
await node.update(x=42)
|
||||
assert not compute.put.called
|
||||
assert node.x == 42
|
||||
node._project.emit_notification.assert_called_with("node.updated", node.__json__())
|
||||
|
||||
# If nothing change a second notif should not be send
|
||||
# If nothing change a second notif should not be sent
|
||||
node._project.emit_notification = AsyncioMagicMock()
|
||||
async_run(node.update(x=42))
|
||||
await node.update(x=42)
|
||||
assert not node._project.emit_notification.called
|
||||
|
||||
|
||||
def test_update_no_changes(node, compute, project, async_run):
|
||||
async def test_update_no_changes(node, compute):
|
||||
"""
|
||||
We don't call the compute node if all compute properties has not changed
|
||||
"""
|
||||
@@ -381,24 +378,25 @@ def test_update_no_changes(node, compute, project, async_run):
|
||||
response.json = {"console": 2048}
|
||||
compute.put = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(node.update(console=2048, x=42))
|
||||
await node.update(console=2048, x=42)
|
||||
assert compute.put.called
|
||||
|
||||
compute.put = AsyncioMagicMock()
|
||||
async_run(node.update(console=2048, x=43))
|
||||
await node.update(console=2048, x=43)
|
||||
assert not compute.put.called
|
||||
assert node.x == 43
|
||||
|
||||
|
||||
def test_start(node, compute, project, async_run):
|
||||
async def test_start(node, compute):
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
|
||||
async_run(node.start())
|
||||
await node.start()
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/start".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_start_iou(compute, project, async_run, controller):
|
||||
async def test_start_iou(compute, project, controller):
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="iou")
|
||||
@@ -409,44 +407,42 @@ def test_start_iou(compute, project, async_run, controller):
|
||||
# async_run(node.start())
|
||||
|
||||
controller._iou_license_settings = {"license_check": True, "iourc_content": "aa"}
|
||||
async_run(node.start())
|
||||
await node.start()
|
||||
compute.post.assert_called_with("/projects/{}/iou/nodes/{}/start".format(node.project.id, node.id), timeout=240, data={"license_check": True, "iourc_content": "aa"})
|
||||
|
||||
|
||||
def test_stop(node, compute, project, async_run):
|
||||
async def test_stop(node, compute):
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
|
||||
async_run(node.stop())
|
||||
await node.stop()
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/stop".format(node.project.id, node.id), timeout=240, dont_connect=True)
|
||||
|
||||
|
||||
def test_suspend(node, compute, project, async_run):
|
||||
async def test_suspend(node, compute):
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
|
||||
async_run(node.suspend())
|
||||
await node.suspend()
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/suspend".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_reload(node, compute, project, async_run):
|
||||
async def test_reload(node, compute):
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
|
||||
async_run(node.reload())
|
||||
await node.reload()
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/reload".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_create_without_console(node, compute, project, async_run):
|
||||
async def test_create_without_console(node, compute):
|
||||
"""
|
||||
None properties should be send. Because it can mean the emulator doesn"t support it
|
||||
None properties should be send. Because it can mean the emulator doesn't support it
|
||||
"""
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048, "test_value": "success"}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(node.create())
|
||||
await node.create()
|
||||
data = {
|
||||
"console_type": "vnc",
|
||||
"node_id": node.id,
|
||||
@@ -458,49 +454,53 @@ def test_create_without_console(node, compute, project, async_run):
|
||||
assert node._properties == {"test_value": "success", "startup_script": "echo test"}
|
||||
|
||||
|
||||
def test_delete(node, compute, async_run):
|
||||
async_run(node.destroy())
|
||||
async def test_delete(node, compute):
|
||||
|
||||
await node.destroy()
|
||||
compute.delete.assert_called_with("/projects/{}/vpcs/nodes/{}".format(node.project.id, node.id))
|
||||
|
||||
|
||||
def test_post(node, compute, async_run):
|
||||
async_run(node.post("/test", {"a": "b"}))
|
||||
async def test_post(node, compute):
|
||||
|
||||
await node.post("/test", {"a": "b"})
|
||||
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/test".format(node.project.id, node.id), data={"a": "b"})
|
||||
|
||||
|
||||
def test_delete(node, compute, async_run):
|
||||
async_run(node.delete("/test"))
|
||||
async def test_delete(node, compute):
|
||||
|
||||
await node.delete("/test")
|
||||
compute.delete.assert_called_with("/projects/{}/vpcs/nodes/{}/test".format(node.project.id, node.id))
|
||||
|
||||
|
||||
def test_dynamips_idle_pc(node, async_run, compute):
|
||||
async def test_dynamips_idle_pc(node, compute):
|
||||
|
||||
node._node_type = "dynamips"
|
||||
response = MagicMock()
|
||||
response.json = {"idlepc": "0x60606f54"}
|
||||
compute.get = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(node.dynamips_auto_idlepc())
|
||||
await node.dynamips_auto_idlepc()
|
||||
compute.get.assert_called_with("/projects/{}/dynamips/nodes/{}/auto_idlepc".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_dynamips_idlepc_proposals(node, async_run, compute):
|
||||
async def test_dynamips_idlepc_proposals(node, compute):
|
||||
|
||||
node._node_type = "dynamips"
|
||||
response = MagicMock()
|
||||
response.json = ["0x60606f54", "0x30ff6f37"]
|
||||
compute.get = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(node.dynamips_idlepc_proposals())
|
||||
await node.dynamips_idlepc_proposals()
|
||||
compute.get.assert_called_with("/projects/{}/dynamips/nodes/{}/idlepc_proposals".format(node.project.id, node.id), timeout=240)
|
||||
|
||||
|
||||
def test_upload_missing_image(compute, controller, async_run, images_dir):
|
||||
async def test_upload_missing_image(compute, controller, images_dir):
|
||||
|
||||
project = Project(str(uuid.uuid4()), controller=controller)
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="qemu",
|
||||
properties={"hda_disk_image": "linux.img"})
|
||||
open(os.path.join(images_dir, "linux.img"), 'w+').close()
|
||||
assert async_run(node._upload_missing_image("qemu", "linux.img")) is True
|
||||
assert await node._upload_missing_image("qemu", "linux.img") is True
|
||||
compute.post.assert_called_with("/qemu/images/linux.img", data=ANY, timeout=None)
|
||||
|
||||
|
||||
@@ -509,6 +509,7 @@ def test_update_label(node):
|
||||
The text in label need to be always the
|
||||
node name
|
||||
"""
|
||||
|
||||
node.name = "Test"
|
||||
assert node.label["text"] == "Test"
|
||||
node.label = {"text": "Wrong", "x": 12}
|
||||
@@ -517,6 +518,7 @@ def test_update_label(node):
|
||||
|
||||
|
||||
def test_get_port(node):
|
||||
|
||||
node._node_type = "qemu"
|
||||
node._properties["adapters"] = 2
|
||||
node._list_ports()
|
||||
@@ -529,12 +531,13 @@ def test_get_port(node):
|
||||
assert port is None
|
||||
|
||||
|
||||
def test_parse_node_response(node, async_run):
|
||||
async def test_parse_node_response(node):
|
||||
"""
|
||||
When a node is updated we notify the links connected to it
|
||||
"""
|
||||
|
||||
link = MagicMock()
|
||||
link.node_updated = AsyncioMagicMock()
|
||||
node.add_link(link)
|
||||
async_run(node.parse_node_response({"status": "started"}))
|
||||
await node.parse_node_response({"status": "started"})
|
||||
assert link.node_updated.called
|
||||
@@ -21,7 +21,6 @@ import uuid
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
from gns3server.controller.node import Node
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.ports.ethernet_port import EthernetPort
|
||||
|
||||
|
||||
@@ -31,12 +30,6 @@ def compute():
|
||||
s.id = "http://test.com:42"
|
||||
return s
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(str(uuid.uuid4()), controller=controller)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(compute, project):
|
||||
node = Node(project, compute, "demo",
|
||||
@@ -51,6 +44,7 @@ def test_list_ports(node):
|
||||
"""
|
||||
List port by default
|
||||
"""
|
||||
|
||||
assert node.__json__()["ports"] == [
|
||||
{
|
||||
"name": "Ethernet0",
|
||||
@@ -67,6 +61,7 @@ def test_list_ports_vpcs(node):
|
||||
"""
|
||||
List port by default
|
||||
"""
|
||||
|
||||
node._node_type = "vpcs"
|
||||
assert node.__json__()["ports"] == [
|
||||
{
|
||||
@@ -84,6 +79,7 @@ def test_list_ports_docker(node):
|
||||
"""
|
||||
List port by default
|
||||
"""
|
||||
|
||||
node._node_type = "docker"
|
||||
node._properties["adapters"] = 2
|
||||
assert node.__json__()["ports"] == [
|
||||
@@ -110,6 +106,7 @@ def test_list_ports_port_name_format(node):
|
||||
"""
|
||||
Support port name format
|
||||
"""
|
||||
|
||||
node._first_port_name = None
|
||||
node._port_name_format = "eth{}"
|
||||
node._list_ports()
|
||||
@@ -139,6 +136,7 @@ def test_list_ports_adapters(node):
|
||||
"""
|
||||
List port using adapters properties
|
||||
"""
|
||||
|
||||
node.properties["adapters"] = 2
|
||||
assert node.__json__()["ports"] == [
|
||||
{
|
||||
@@ -164,6 +162,7 @@ def test_list_ports_adapters_cloud(project, compute):
|
||||
"""
|
||||
List port using adapters properties
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="cloud")
|
||||
@@ -192,6 +191,7 @@ def test_list_ports_ethernet_hub(project, compute):
|
||||
"""
|
||||
List port for atm switch
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="ethernet_hub")
|
||||
@@ -230,6 +230,7 @@ def test_list_ports_atm_switch(project, compute):
|
||||
"""
|
||||
List port for atm switch
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="atm_switch")
|
||||
@@ -261,6 +262,7 @@ def test_list_ports_frame_relay_switch(project, compute):
|
||||
"""
|
||||
List port for frame relay switch
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="frame_relay_switch")
|
||||
@@ -309,6 +311,7 @@ def test_list_ports_iou(compute, project):
|
||||
"""
|
||||
IOU has a special behavior 4 port by adapters
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="iou")
|
||||
@@ -514,6 +517,7 @@ def test_list_ports_dynamips(project, compute):
|
||||
"""
|
||||
List port for dynamips
|
||||
"""
|
||||
|
||||
node = Node(project, compute, "demo",
|
||||
node_id=str(uuid.uuid4()),
|
||||
node_type="dynamips")
|
||||
@@ -595,6 +599,7 @@ def test_list_ports_dynamips(project, compute):
|
||||
|
||||
|
||||
def test_short_name():
|
||||
|
||||
# If no customization of port name format return the default short name
|
||||
assert EthernetPort("Ethernet0", 0, 0, 0).short_name == "e0"
|
||||
assert EthernetPort("Ethernet0", 0, 0, 0, short_name="mgmt").short_name == "mgmt"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -18,81 +18,78 @@
|
||||
import pytest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from gns3server.controller.notification import Notification
|
||||
from gns3server.controller import Controller
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(async_run):
|
||||
return async_run(Controller.instance().add_project(name="Test"))
|
||||
async def node(project):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(project, async_run):
|
||||
compute = MagicMock()
|
||||
compute.id = "remote1"
|
||||
compute.host = "example.org"
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
return async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
return await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
|
||||
def test_emit_to_all(async_run, controller, project):
|
||||
async def test_emit_to_all(controller, project):
|
||||
"""
|
||||
Send an event to all if we don't have a project id in the event
|
||||
"""
|
||||
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
await queue.get(0.1) # ping
|
||||
notif.project_emit('test', {})
|
||||
msg = async_run(queue.get(5))
|
||||
msg = await queue.get(5)
|
||||
assert msg == ('test', {}, {})
|
||||
|
||||
assert len(notif._project_listeners[project.id]) == 0
|
||||
|
||||
|
||||
def test_emit_to_project(async_run, controller, project):
|
||||
async def test_emit_to_project(controller, project):
|
||||
"""
|
||||
Send an event to a project listeners
|
||||
"""
|
||||
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
await queue.get(0.1) # ping
|
||||
# This event has not listener
|
||||
notif.project_emit('ignore', {"project_id": 42})
|
||||
notif.project_emit('test', {"project_id": project.id})
|
||||
msg = async_run(queue.get(5))
|
||||
msg = await queue.get(5)
|
||||
assert msg == ('test', {"project_id": project.id}, {})
|
||||
|
||||
assert len(notif._project_listeners[project.id]) == 0
|
||||
|
||||
|
||||
def test_dispatch(async_run, controller, project):
|
||||
async def test_dispatch(controller, project):
|
||||
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
async_run(notif.dispatch("test", {}, project_id=project.id, compute_id=1))
|
||||
msg = async_run(queue.get(5))
|
||||
await queue.get(0.1) # ping
|
||||
await notif.dispatch("test", {}, project_id=project.id, compute_id=1)
|
||||
msg = await queue.get(5)
|
||||
assert msg == ('test', {}, {})
|
||||
|
||||
|
||||
def test_dispatch_ping(async_run, controller, project):
|
||||
async def test_dispatch_ping(controller, project):
|
||||
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
async_run(notif.dispatch("ping", {}, project_id=project.id, compute_id=12))
|
||||
msg = async_run(queue.get(5))
|
||||
await queue.get(0.1) # ping
|
||||
await notif.dispatch("ping", {}, project_id=project.id, compute_id=12)
|
||||
msg = await queue.get(5)
|
||||
assert msg == ('ping', {'compute_id': 12}, {})
|
||||
|
||||
|
||||
def test_dispatch_node_updated(async_run, controller, node, project):
|
||||
async def test_dispatch_node_updated(controller, node, project):
|
||||
"""
|
||||
When we receive a node.updated notification from compute
|
||||
we need to update the client
|
||||
@@ -101,25 +98,26 @@ def test_dispatch_node_updated(async_run, controller, node, project):
|
||||
notif = controller.notification
|
||||
with notif.project_queue(project.id) as queue:
|
||||
assert len(notif._project_listeners[project.id]) == 1
|
||||
async_run(queue.get(0.1)) # ping
|
||||
async_run(notif.dispatch("node.updated", {
|
||||
await queue.get(0.1) # ping
|
||||
await notif.dispatch("node.updated", {
|
||||
"node_id": node.id,
|
||||
"project_id": project.id,
|
||||
"name": "hello",
|
||||
"startup_config": "ip 192"
|
||||
},
|
||||
project_id=project.id,
|
||||
compute_id=1))
|
||||
compute_id=1)
|
||||
assert node.name == "hello"
|
||||
action, event, _ = async_run(queue.get(5))
|
||||
action, event, _ = await queue.get(5)
|
||||
assert action == "node.updated"
|
||||
assert event["name"] == "hello"
|
||||
assert event["properties"]["startup_config"] == "ip 192"
|
||||
|
||||
|
||||
def test_various_notification(controller, node):
|
||||
|
||||
notif = controller.notification
|
||||
notif.project_emit("log.info", {"message": "Image uploaded"})
|
||||
notif.project_emit("log.warning", {"message": "Warning ASA 8 is not officialy supported by GNS3"})
|
||||
notif.project_emit("log.warning", {"message": "Warning ASA 8 is not officially supported by GNS3"})
|
||||
notif.project_emit("log.error", {"message": "Permission denied on /tmp"})
|
||||
notif.project_emit("node.updated", node.__json__())
|
||||
+193
-171
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -34,33 +34,29 @@ from gns3server.config import Config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(controller=controller, name="Test")
|
||||
async def node(controller, project):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node(controller, project, async_run):
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
return node
|
||||
|
||||
|
||||
def test_affect_uuid():
|
||||
async def test_affect_uuid():
|
||||
|
||||
p = Project(name="Test")
|
||||
assert len(p.id) == 36
|
||||
|
||||
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test 2")
|
||||
assert p.id == '00010203-0405-0607-0809-0a0b0c0d0e0f'
|
||||
|
||||
|
||||
def test_json(tmpdir):
|
||||
async def test_json():
|
||||
|
||||
p = Project(name="Test")
|
||||
|
||||
assert p.__json__() == {
|
||||
"name": "Test",
|
||||
"project_id": p.id,
|
||||
@@ -84,34 +80,31 @@ def test_json(tmpdir):
|
||||
}
|
||||
|
||||
|
||||
def test_update(controller, async_run):
|
||||
async def test_update(controller):
|
||||
|
||||
project = Project(controller=controller, name="Hello")
|
||||
project.emit_notification = MagicMock()
|
||||
assert project.name == "Hello"
|
||||
async_run(project.update(name="World"))
|
||||
await project.update(name="World")
|
||||
assert project.name == "World"
|
||||
project.emit_notification.assert_any_call("project.updated", project.__json__())
|
||||
|
||||
|
||||
def test_update_on_compute(controller, async_run):
|
||||
async def test_update_on_compute(controller):
|
||||
|
||||
variables = [{"name": "TEST", "value": "VAL1"}]
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = Project(controller=controller, name="Test")
|
||||
project._project_created_on_compute = [compute]
|
||||
project.emit_notification = MagicMock()
|
||||
|
||||
async_run(project.update(variables=variables))
|
||||
|
||||
compute.put.assert_any_call('/projects/{}'.format(project.id), {
|
||||
"variables": variables
|
||||
})
|
||||
await project.update(variables=variables)
|
||||
compute.put.assert_any_call('/projects/{}'.format(project.id), {"variables": variables})
|
||||
|
||||
|
||||
def test_path(tmpdir):
|
||||
|
||||
directory = Config.instance().get_section_config("Server").get("projects_path")
|
||||
async def test_path(projects_dir):
|
||||
|
||||
directory = projects_dir
|
||||
with patch("gns3server.utils.path.get_default_project_directory", return_value=directory):
|
||||
p = Project(project_id=str(uuid4()), name="Test")
|
||||
assert p.path == os.path.join(directory, p.id)
|
||||
@@ -120,37 +113,41 @@ def test_path(tmpdir):
|
||||
|
||||
def test_path_exist(tmpdir):
|
||||
"""
|
||||
Should raise an error when you try to owerwrite
|
||||
Should raise an error when you try to overwrite
|
||||
an existing project
|
||||
"""
|
||||
|
||||
os.makedirs(str(tmpdir / "demo"))
|
||||
with pytest.raises(aiohttp.web.HTTPForbidden):
|
||||
p = Project(name="Test", path=str(tmpdir / "demo"))
|
||||
Project(name="Test", path=str(tmpdir / "demo"))
|
||||
|
||||
|
||||
def test_init_path(tmpdir):
|
||||
async def test_init_path(tmpdir):
|
||||
|
||||
p = Project(path=str(tmpdir), project_id=str(uuid4()), name="Test")
|
||||
assert p.path == str(tmpdir)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
def test_changing_path_with_quote_not_allowed(tmpdir):
|
||||
async def test_changing_path_with_quote_not_allowed(tmpdir):
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPForbidden):
|
||||
p = Project(project_id=str(uuid4()), name="Test")
|
||||
p.path = str(tmpdir / "project\"53")
|
||||
|
||||
|
||||
def test_captures_directory(tmpdir):
|
||||
async def test_captures_directory(tmpdir):
|
||||
|
||||
p = Project(path=str(tmpdir / "capturestest"), name="Test")
|
||||
assert p.captures_directory == str(tmpdir / "capturestest" / "project-files" / "captures")
|
||||
assert os.path.exists(p.captures_directory)
|
||||
|
||||
|
||||
def test_add_node_local(async_run, controller):
|
||||
async def test_add_node_local(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = Project(controller=controller, name="Test")
|
||||
@@ -160,7 +157,7 @@ def test_add_node_local(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"})
|
||||
assert node.id in project._nodes
|
||||
|
||||
compute.post.assert_any_call('/projects', data={
|
||||
@@ -177,10 +174,11 @@ def test_add_node_local(async_run, controller):
|
||||
project.emit_notification.assert_any_call("node.created", node.__json__())
|
||||
|
||||
|
||||
def test_add_node_non_local(async_run, controller):
|
||||
async def test_add_node_non_local(controller):
|
||||
"""
|
||||
For a non local server we do not send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "remote"
|
||||
project = Project(controller=controller, name="Test")
|
||||
@@ -190,67 +188,66 @@ def test_add_node_non_local(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"})
|
||||
|
||||
compute.post.assert_any_call('/projects', data={
|
||||
"name": project._name,
|
||||
"project_id": project._id
|
||||
})
|
||||
compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id),
|
||||
data={'node_id': node.id,
|
||||
'startup_script': 'test.cfg',
|
||||
'name': 'test'},
|
||||
timeout=1200)
|
||||
compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id,
|
||||
'startup_script': 'test.cfg',
|
||||
'name': 'test'}, timeout=1200)
|
||||
assert compute in project._project_created_on_compute
|
||||
project.emit_notification.assert_any_call("node.created", node.__json__())
|
||||
|
||||
|
||||
def test_add_node_iou(async_run, controller):
|
||||
async def test_add_node_iou(controller):
|
||||
"""
|
||||
Test if an application ID is allocated for IOU nodes
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test1"))
|
||||
project = await controller.add_project(project_id=str(uuid.uuid4()), name="test1")
|
||||
project.emit_notification = MagicMock()
|
||||
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project.add_node(compute, "test1", None, node_type="iou"))
|
||||
node2 = async_run(project.add_node(compute, "test2", None, node_type="iou"))
|
||||
node3 = async_run(project.add_node(compute, "test3", None, node_type="iou"))
|
||||
node1 = await project.add_node(compute, "test1", None, node_type="iou")
|
||||
node2 = await project.add_node(compute, "test2", None, node_type="iou")
|
||||
node3 = await project.add_node(compute, "test3", None, node_type="iou")
|
||||
assert node1.properties["application_id"] == 1
|
||||
assert node2.properties["application_id"] == 2
|
||||
assert node3.properties["application_id"] == 3
|
||||
|
||||
|
||||
def test_add_node_iou_with_multiple_projects(async_run, controller):
|
||||
async def test_add_node_iou_with_multiple_projects(controller):
|
||||
"""
|
||||
Test if an application ID is allocated for IOU nodes with different projects already opened
|
||||
"""
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project1 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test1"))
|
||||
project1 = await controller.add_project(project_id=str(uuid.uuid4()), name="test1")
|
||||
project1.emit_notification = MagicMock()
|
||||
project2 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test2"))
|
||||
project2 = await controller.add_project(project_id=str(uuid.uuid4()), name="test2")
|
||||
project2.emit_notification = MagicMock()
|
||||
project3 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test3"))
|
||||
project3 = await controller.add_project(project_id=str(uuid.uuid4()), name="test3")
|
||||
project3.emit_notification = MagicMock()
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project1.add_node(compute, "test1", None, node_type="iou"))
|
||||
node2 = async_run(project1.add_node(compute, "test2", None, node_type="iou"))
|
||||
node3 = async_run(project1.add_node(compute, "test3", None, node_type="iou"))
|
||||
node1 = await project1.add_node(compute, "test1", None, node_type="iou")
|
||||
node2 = await project1.add_node(compute, "test2", None, node_type="iou")
|
||||
node3 = await project1.add_node(compute, "test3", None, node_type="iou")
|
||||
|
||||
node4 = async_run(project2.add_node(compute, "test4", None, node_type="iou"))
|
||||
node5 = async_run(project2.add_node(compute, "test5", None, node_type="iou"))
|
||||
node6 = async_run(project2.add_node(compute, "test6", None, node_type="iou"))
|
||||
node4 = await project2.add_node(compute, "test4", None, node_type="iou")
|
||||
node5 = await project2.add_node(compute, "test5", None, node_type="iou")
|
||||
node6 = await project2.add_node(compute, "test6", None, node_type="iou")
|
||||
|
||||
node7 = async_run(project3.add_node(compute, "test7", None, node_type="iou"))
|
||||
node8 = async_run(project3.add_node(compute, "test8", None, node_type="iou"))
|
||||
node9 = async_run(project3.add_node(compute, "test9", None, node_type="iou"))
|
||||
node7 = await project3.add_node(compute, "test7", None, node_type="iou")
|
||||
node8 = await project3.add_node(compute, "test8", None, node_type="iou")
|
||||
node9 = await project3.add_node(compute, "test9", None, node_type="iou")
|
||||
|
||||
assert node1.properties["application_id"] == 1
|
||||
assert node2.properties["application_id"] == 2
|
||||
@@ -265,19 +262,19 @@ def test_add_node_iou_with_multiple_projects(async_run, controller):
|
||||
assert node9.properties["application_id"] == 9
|
||||
|
||||
controller.remove_project(project1)
|
||||
project4 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test4"))
|
||||
project4 = await controller.add_project(project_id=str(uuid.uuid4()), name="test4")
|
||||
project4.emit_notification = MagicMock()
|
||||
|
||||
node10 = async_run(project3.add_node(compute, "test10", None, node_type="iou"))
|
||||
node11 = async_run(project3.add_node(compute, "test11", None, node_type="iou"))
|
||||
node12 = async_run(project3.add_node(compute, "test12", None, node_type="iou"))
|
||||
node10 = await project3.add_node(compute, "test10", None, node_type="iou")
|
||||
node11 = await project3.add_node(compute, "test11", None, node_type="iou")
|
||||
node12 = await project3.add_node(compute, "test12", None, node_type="iou")
|
||||
|
||||
assert node10.properties["application_id"] == 1
|
||||
assert node11.properties["application_id"] == 2
|
||||
assert node12.properties["application_id"] == 3
|
||||
|
||||
|
||||
def test_add_node_iou_with_multiple_projects_different_computes(async_run, controller):
|
||||
async def test_add_node_iou_with_multiple_projects_different_computes(controller):
|
||||
"""
|
||||
Test if an application ID is allocated for IOU nodes with different projects already opened
|
||||
"""
|
||||
@@ -285,19 +282,19 @@ def test_add_node_iou_with_multiple_projects_different_computes(async_run, contr
|
||||
compute1.id = "remote1"
|
||||
compute2 = MagicMock()
|
||||
compute2.id = "remote2"
|
||||
project1 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test1"))
|
||||
project1 = await controller.add_project(project_id=str(uuid.uuid4()), name="test1")
|
||||
project1.emit_notification = MagicMock()
|
||||
project2 = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test2"))
|
||||
project2 = await controller.add_project(project_id=str(uuid.uuid4()), name="test2")
|
||||
project2.emit_notification = MagicMock()
|
||||
response = MagicMock()
|
||||
compute1.post = AsyncioMagicMock(return_value=response)
|
||||
compute2.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node1 = async_run(project1.add_node(compute1, "test1", None, node_type="iou"))
|
||||
node2 = async_run(project1.add_node(compute1, "test2", None, node_type="iou"))
|
||||
node1 = await project1.add_node(compute1, "test1", None, node_type="iou")
|
||||
node2 = await project1.add_node(compute1, "test2", None, node_type="iou")
|
||||
|
||||
node3 = async_run(project2.add_node(compute2, "test3", None, node_type="iou"))
|
||||
node4 = async_run(project2.add_node(compute2, "test4", None, node_type="iou"))
|
||||
node3 = await project2.add_node(compute2, "test3", None, node_type="iou")
|
||||
node4 = await project2.add_node(compute2, "test4", None, node_type="iou")
|
||||
|
||||
assert node1.properties["application_id"] == 1
|
||||
assert node2.properties["application_id"] == 2
|
||||
@@ -305,20 +302,21 @@ def test_add_node_iou_with_multiple_projects_different_computes(async_run, contr
|
||||
assert node3.properties["application_id"] == 1
|
||||
assert node4.properties["application_id"] == 2
|
||||
|
||||
node5 = async_run(project1.add_node(compute2, "test5", None, node_type="iou"))
|
||||
node6 = async_run(project2.add_node(compute1, "test6", None, node_type="iou"))
|
||||
node5 = await project1.add_node(compute2, "test5", None, node_type="iou")
|
||||
node6 = await project2.add_node(compute1, "test6", None, node_type="iou")
|
||||
|
||||
assert node5.properties["application_id"] == 3
|
||||
assert node6.properties["application_id"] == 4
|
||||
|
||||
|
||||
def test_add_node_iou_no_id_available(async_run, controller):
|
||||
async def test_add_node_iou_no_id_available(controller):
|
||||
"""
|
||||
Test if an application ID is allocated for IOU nodes
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = async_run(controller.add_project(project_id=str(uuid.uuid4()), name="test"))
|
||||
project = await controller.add_project(project_id=str(uuid.uuid4()), name="test")
|
||||
project.emit_notification = MagicMock()
|
||||
response = MagicMock()
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
@@ -327,13 +325,14 @@ def test_add_node_iou_no_id_available(async_run, controller):
|
||||
for i in range(1, 513):
|
||||
prop = {"properties": {"application_id": i}}
|
||||
project._nodes[i] = Node(project, compute, "Node{}".format(i), node_id=i, node_type="iou", **prop)
|
||||
async_run(project.add_node(compute, "test1", None, node_type="iou"))
|
||||
await project.add_node(compute, "test1", None, node_type="iou")
|
||||
|
||||
|
||||
def test_add_node_from_template(async_run, controller):
|
||||
async def test_add_node_from_template(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = Project(controller=controller, name="Test")
|
||||
@@ -351,7 +350,7 @@ def test_add_node_from_template(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node_from_template(template.id, x=23, y=12))
|
||||
node = await project.add_node_from_template(template.id, x=23, y=12)
|
||||
compute.post.assert_any_call('/projects', data={
|
||||
"name": project._name,
|
||||
"project_id": project._id,
|
||||
@@ -362,10 +361,11 @@ def test_add_node_from_template(async_run, controller):
|
||||
project.emit_notification.assert_any_call("node.created", node.__json__())
|
||||
|
||||
|
||||
def test_add_builtin_node_from_template(async_run, controller):
|
||||
async def test_add_builtin_node_from_template(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
project = Project(controller=controller, name="Test")
|
||||
@@ -374,6 +374,7 @@ def test_add_builtin_node_from_template(async_run, controller):
|
||||
"name": "Builtin-switch",
|
||||
"template_type": "ethernet_switch",
|
||||
}, builtin=True)
|
||||
|
||||
controller.template_manager.templates[template.id] = template
|
||||
template.__json__()
|
||||
controller._computes["local"] = compute
|
||||
@@ -382,7 +383,7 @@ def test_add_builtin_node_from_template(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node_from_template(template.id, x=23, y=12, compute_id="local"))
|
||||
node = await project.add_node_from_template(template.id, x=23, y=12, compute_id="local")
|
||||
compute.post.assert_any_call('/projects', data={
|
||||
"name": project._name,
|
||||
"project_id": project._id,
|
||||
@@ -393,7 +394,7 @@ def test_add_builtin_node_from_template(async_run, controller):
|
||||
project.emit_notification.assert_any_call("node.created", node.__json__())
|
||||
|
||||
|
||||
def test_delete_node(async_run, controller):
|
||||
async def test_delete_node(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
@@ -405,19 +406,20 @@ def test_delete_node(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.id in project._nodes
|
||||
async_run(project.delete_node(node.id))
|
||||
await project.delete_node(node.id)
|
||||
assert node.id not in project._nodes
|
||||
|
||||
compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id))
|
||||
project.emit_notification.assert_any_call("node.deleted", node.__json__())
|
||||
|
||||
|
||||
def test_delete_locked_node(async_run, controller):
|
||||
async def test_delete_locked_node(controller):
|
||||
"""
|
||||
For a local server we send the project path
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
project = Project(controller=controller, name="Test")
|
||||
project.emit_notification = MagicMock()
|
||||
@@ -426,14 +428,14 @@ def test_delete_locked_node(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.id in project._nodes
|
||||
node.locked = True
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPConflict):
|
||||
async_run(project.delete_node(node.id))
|
||||
await project.delete_node(node.id)
|
||||
|
||||
|
||||
def test_delete_node_delete_link(async_run, controller):
|
||||
async def test_delete_node_delete_link(controller):
|
||||
"""
|
||||
Delete a node delete all the node connected
|
||||
"""
|
||||
@@ -445,12 +447,12 @@ def test_delete_node_delete_link(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
link = async_run(project.add_link())
|
||||
async_run(link.add_node(node, 0, 0))
|
||||
link = await project.add_link()
|
||||
await link.add_node(node, 0, 0)
|
||||
|
||||
async_run(project.delete_node(node.id))
|
||||
await project.delete_node(node.id)
|
||||
assert node.id not in project._nodes
|
||||
assert link.id not in project._links
|
||||
|
||||
@@ -459,7 +461,8 @@ def test_delete_node_delete_link(async_run, controller):
|
||||
project.emit_notification.assert_any_call("link.deleted", link.__json__())
|
||||
|
||||
|
||||
def test_get_node(async_run, controller):
|
||||
async def test_get_node(controller):
|
||||
|
||||
compute = MagicMock()
|
||||
project = Project(controller=controller, name="Test")
|
||||
|
||||
@@ -467,18 +470,20 @@ def test_get_node(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
vm = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
vm = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert project.get_node(vm.id) == vm
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project.get_node("test")
|
||||
|
||||
# Raise an error if the project is not opened
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
with pytest.raises(aiohttp.web.HTTPForbidden):
|
||||
project.get_node(vm.id)
|
||||
|
||||
def test_list_nodes(async_run, controller):
|
||||
|
||||
async def test_list_nodes(controller):
|
||||
|
||||
compute = MagicMock()
|
||||
project = Project(controller=controller, name="Test")
|
||||
|
||||
@@ -486,157 +491,163 @@ def test_list_nodes(async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
vm = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
vm = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert len(project.nodes) == 1
|
||||
assert isinstance(project.nodes, dict)
|
||||
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert len(project.nodes) == 1
|
||||
assert isinstance(project.nodes, dict)
|
||||
|
||||
|
||||
def test_add_link(async_run, project, controller):
|
||||
async def test_add_link(project):
|
||||
|
||||
compute = MagicMock()
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
vm1 = async_run(project.add_node(compute, "test1", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
vm1 = await project.add_node(compute, "test1", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
vm1._ports = [EthernetPort("E0", 0, 3, 1)]
|
||||
vm2 = async_run(project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
vm2 = await project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
vm2._ports = [EthernetPort("E0", 0, 4, 2)]
|
||||
project.emit_notification = MagicMock()
|
||||
link = async_run(project.add_link())
|
||||
async_run(link.add_node(vm1, 3, 1))
|
||||
link = await project.add_link()
|
||||
await link.add_node(vm1, 3, 1)
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock_udp_create:
|
||||
async_run(link.add_node(vm2, 4, 2))
|
||||
await link.add_node(vm2, 4, 2)
|
||||
assert mock_udp_create.called
|
||||
assert len(link._nodes) == 2
|
||||
project.emit_notification.assert_any_call("link.created", link.__json__())
|
||||
|
||||
|
||||
def test_list_links(async_run, project):
|
||||
compute = MagicMock()
|
||||
async def test_list_links(project):
|
||||
|
||||
compute = MagicMock()
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
link = async_run(project.add_link())
|
||||
await project.add_link()
|
||||
assert len(project.links) == 1
|
||||
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert len(project.links) == 1
|
||||
|
||||
|
||||
def test_get_link(async_run, project):
|
||||
async def test_get_link(project):
|
||||
|
||||
compute = MagicMock()
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
link = async_run(project.add_link())
|
||||
link = await project.add_link()
|
||||
assert project.get_link(link.id) == link
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project.get_link("test")
|
||||
|
||||
|
||||
def test_delete_link(async_run, project, controller):
|
||||
compute = MagicMock()
|
||||
async def test_delete_link(project):
|
||||
|
||||
compute = MagicMock()
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
assert len(project._links) == 0
|
||||
link = async_run(project.add_link())
|
||||
link = await project.add_link()
|
||||
assert len(project._links) == 1
|
||||
project.emit_notification = MagicMock()
|
||||
async_run(project.delete_link(link.id))
|
||||
await project.delete_link(link.id)
|
||||
project.emit_notification.assert_any_call("link.deleted", link.__json__())
|
||||
assert len(project._links) == 0
|
||||
|
||||
|
||||
def test_add_drawing(async_run, project, controller):
|
||||
project.emit_notification = MagicMock()
|
||||
async def test_add_drawing(project):
|
||||
|
||||
drawing = async_run(project.add_drawing(None, svg="<svg></svg>"))
|
||||
project.emit_notification = MagicMock()
|
||||
drawing = await project.add_drawing(None, svg="<svg></svg>")
|
||||
assert len(project._drawings) == 1
|
||||
project.emit_notification.assert_any_call("drawing.created", drawing.__json__())
|
||||
|
||||
|
||||
def test_get_drawing(async_run, project):
|
||||
drawing = async_run(project.add_drawing(None))
|
||||
async def test_get_drawing(project):
|
||||
|
||||
drawing = await project.add_drawing(None)
|
||||
assert project.get_drawing(drawing.id) == drawing
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project.get_drawing("test")
|
||||
|
||||
|
||||
def test_list_drawing(async_run, project):
|
||||
drawing = async_run(project.add_drawing(None))
|
||||
async def test_list_drawing(project):
|
||||
|
||||
await project.add_drawing(None)
|
||||
assert len(project.drawings) == 1
|
||||
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert len(project.drawings) == 1
|
||||
|
||||
|
||||
def test_delete_drawing(async_run, project, controller):
|
||||
async def test_delete_drawing(project):
|
||||
|
||||
assert len(project._drawings) == 0
|
||||
drawing = async_run(project.add_drawing())
|
||||
drawing = await project.add_drawing()
|
||||
assert len(project._drawings) == 1
|
||||
project.emit_notification = MagicMock()
|
||||
async_run(project.delete_drawing(drawing.id))
|
||||
await project.delete_drawing(drawing.id)
|
||||
project.emit_notification.assert_any_call("drawing.deleted", drawing.__json__())
|
||||
assert len(project._drawings) == 0
|
||||
|
||||
|
||||
def test_clean_pictures(async_run, project, controller):
|
||||
async def test_clean_pictures(project):
|
||||
"""
|
||||
When a project is close old pictures should be removed
|
||||
"""
|
||||
|
||||
drawing = async_run(project.add_drawing())
|
||||
drawing = await project.add_drawing()
|
||||
drawing._svg = "test.png"
|
||||
open(os.path.join(project.pictures_directory, "test.png"), "w+").close()
|
||||
open(os.path.join(project.pictures_directory, "test2.png"), "w+").close()
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert os.path.exists(os.path.join(project.pictures_directory, "test.png"))
|
||||
assert not os.path.exists(os.path.join(project.pictures_directory, "test2.png"))
|
||||
|
||||
|
||||
def test_clean_pictures_and_keep_supplier_logo(async_run, project, controller):
|
||||
async def test_clean_pictures_and_keep_supplier_logo(project):
|
||||
"""
|
||||
When a project is close old pictures should be removed
|
||||
"""
|
||||
|
||||
project.supplier = {
|
||||
'logo': 'logo.png'
|
||||
}
|
||||
|
||||
drawing = async_run(project.add_drawing())
|
||||
drawing = await project.add_drawing()
|
||||
drawing._svg = "test.png"
|
||||
open(os.path.join(project.pictures_directory, "test.png"), "w+").close()
|
||||
open(os.path.join(project.pictures_directory, "test2.png"), "w+").close()
|
||||
open(os.path.join(project.pictures_directory, "logo.png"), "w+").close()
|
||||
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert os.path.exists(os.path.join(project.pictures_directory, "test.png"))
|
||||
assert not os.path.exists(os.path.join(project.pictures_directory, "test2.png"))
|
||||
assert os.path.exists(os.path.join(project.pictures_directory, "logo.png"))
|
||||
|
||||
|
||||
def test_delete(async_run, project, controller):
|
||||
async def test_delete(project):
|
||||
|
||||
assert os.path.exists(project.path)
|
||||
async_run(project.delete())
|
||||
await project.delete()
|
||||
assert not os.path.exists(project.path)
|
||||
|
||||
|
||||
def test_dump():
|
||||
directory = Config.instance().get_section_config("Server").get("projects_path")
|
||||
async def test_dump(projects_dir):
|
||||
|
||||
directory = projects_dir
|
||||
with patch("gns3server.utils.path.get_default_project_directory", return_value=directory):
|
||||
p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test")
|
||||
p.dump()
|
||||
@@ -645,30 +656,32 @@ def test_dump():
|
||||
assert "00010203-0405-0607-0809-0a0b0c0d0e0f" in content
|
||||
|
||||
|
||||
def test_open_close(async_run, controller):
|
||||
async def test_open_close(controller):
|
||||
|
||||
project = Project(controller=controller, name="Test")
|
||||
assert project.status == "opened"
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
project.start_all = AsyncioMagicMock()
|
||||
async_run(project.open())
|
||||
await project.open()
|
||||
assert not project.start_all.called
|
||||
assert project.status == "opened"
|
||||
project.emit_notification = MagicMock()
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
assert project.status == "closed"
|
||||
project.emit_notification.assert_any_call("project.closed", project.__json__())
|
||||
|
||||
|
||||
def test_open_auto_start(async_run, controller):
|
||||
async def test_open_auto_start(controller):
|
||||
|
||||
project = Project(controller=controller, name="Test", auto_start=True)
|
||||
assert project.status == "opened"
|
||||
async_run(project.close())
|
||||
await project.close()
|
||||
project.start_all = AsyncioMagicMock()
|
||||
async_run(project.open())
|
||||
await project.open()
|
||||
assert project.start_all.called
|
||||
|
||||
|
||||
def test_is_running(project, async_run, node):
|
||||
def test_is_running(project, node):
|
||||
"""
|
||||
If a node is started or paused return True
|
||||
"""
|
||||
@@ -678,11 +691,12 @@ def test_is_running(project, async_run, node):
|
||||
assert project.is_running() is True
|
||||
|
||||
|
||||
def test_duplicate(project, async_run, controller):
|
||||
async def test_duplicate(project, controller):
|
||||
"""
|
||||
Duplicate a project, the node should remain on the remote server
|
||||
if they were on remote server
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "remote"
|
||||
compute.list_files = AsyncioMagicMock(return_value=[])
|
||||
@@ -692,16 +706,16 @@ def test_duplicate(project, async_run, controller):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
remote_vpcs = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
remote_vpcs = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
# We allow node not allowed for standard import / export
|
||||
remote_virtualbox = async_run(project.add_node(compute, "test", None, node_type="vmware", properties={"startup_config": "test.cfg"}))
|
||||
remote_virtualbox = await project.add_node(compute, "test", None, node_type="vmware", properties={"startup_config": "test.cfg"})
|
||||
|
||||
new_project = async_run(project.duplicate(name="Hello"))
|
||||
new_project = await project.duplicate(name="Hello")
|
||||
assert new_project.id != project.id
|
||||
assert new_project.name == "Hello"
|
||||
|
||||
async_run(new_project.open())
|
||||
await new_project.open()
|
||||
|
||||
assert list(new_project.nodes.values())[0].compute.id == "remote"
|
||||
assert list(new_project.nodes.values())[1].compute.id == "remote"
|
||||
@@ -711,6 +725,7 @@ def test_snapshots(project):
|
||||
"""
|
||||
List the snapshots
|
||||
"""
|
||||
|
||||
os.makedirs(os.path.join(project.path, "snapshots"))
|
||||
open(os.path.join(project.path, "snapshots", "test1_260716_103713.gns3project"), "w+").close()
|
||||
project.reset()
|
||||
@@ -720,6 +735,7 @@ def test_snapshots(project):
|
||||
|
||||
|
||||
def test_get_snapshot(project):
|
||||
|
||||
os.makedirs(os.path.join(project.path, "snapshots"))
|
||||
open(os.path.join(project.path, "snapshots", "test1.gns3project"), "w+").close()
|
||||
project.reset()
|
||||
@@ -731,7 +747,8 @@ def test_get_snapshot(project):
|
||||
project.get_snapshot("BLU")
|
||||
|
||||
|
||||
def test_delete_snapshot(project, async_run):
|
||||
async def test_delete_snapshot(project):
|
||||
|
||||
os.makedirs(os.path.join(project.path, "snapshots"))
|
||||
open(os.path.join(project.path, "snapshots", "test1_260716_103713.gns3project"), "w+").close()
|
||||
project.reset()
|
||||
@@ -739,7 +756,7 @@ def test_delete_snapshot(project, async_run):
|
||||
snapshot = list(project.snapshots.values())[0]
|
||||
assert project.get_snapshot(snapshot.id) == snapshot
|
||||
|
||||
async_run(project.delete_snapshot(snapshot.id))
|
||||
await project.delete_snapshot(snapshot.id)
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project.get_snapshot(snapshot.id)
|
||||
@@ -747,13 +764,13 @@ def test_delete_snapshot(project, async_run):
|
||||
assert not os.path.exists(os.path.join(project.path, "snapshots", "test1.gns3project"))
|
||||
|
||||
|
||||
def test_snapshot(project, async_run):
|
||||
async def test_snapshot(project):
|
||||
"""
|
||||
Create a snapshot
|
||||
"""
|
||||
assert len(project.snapshots) == 0
|
||||
|
||||
snapshot = async_run(project.snapshot("test1"))
|
||||
assert len(project.snapshots) == 0
|
||||
snapshot = await project.snapshot("test1")
|
||||
assert snapshot.name == "test1"
|
||||
|
||||
assert len(project.snapshots) == 1
|
||||
@@ -761,10 +778,11 @@ def test_snapshot(project, async_run):
|
||||
|
||||
# Raise a conflict if name is already use
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPConflict):
|
||||
snapshot = async_run(project.snapshot("test1"))
|
||||
snapshot = await project.snapshot("test1")
|
||||
|
||||
|
||||
def test_start_all(project, async_run):
|
||||
async def test_start_all(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
@@ -772,14 +790,15 @@ def test_start_all(project, async_run):
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
for node_i in range(0, 10):
|
||||
async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
async_run(project.start_all())
|
||||
await project.start_all()
|
||||
assert len(compute.post.call_args_list) == 10
|
||||
|
||||
|
||||
def test_stop_all(project, async_run):
|
||||
async def test_stop_all(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
@@ -787,14 +806,15 @@ def test_stop_all(project, async_run):
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
for node_i in range(0, 10):
|
||||
async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
async_run(project.stop_all())
|
||||
await project.stop_all()
|
||||
assert len(compute.post.call_args_list) == 10
|
||||
|
||||
|
||||
def test_suspend_all(project, async_run):
|
||||
async def test_suspend_all(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
@@ -802,51 +822,53 @@ def test_suspend_all(project, async_run):
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
for node_i in range(0, 10):
|
||||
async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
compute.post = AsyncioMagicMock()
|
||||
async_run(project.suspend_all())
|
||||
await project.suspend_all()
|
||||
assert len(compute.post.call_args_list) == 10
|
||||
|
||||
|
||||
def test_node_name(project, async_run):
|
||||
async def test_node_name(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
node = async_run(project.add_node(compute, "test-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "test-1"
|
||||
node = async_run(project.add_node(compute, "test-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "test-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "test-2"
|
||||
node = async_run(project.add_node(compute, "hello world-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "hello world-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "helloworld-1"
|
||||
node = async_run(project.add_node(compute, "hello world-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "hello world-{0}", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "helloworld-2"
|
||||
node = async_run(project.add_node(compute, "VPCS-1", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "VPCS-1", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "VPCS-1"
|
||||
node = async_run(project.add_node(compute, "VPCS-1", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "VPCS-1", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "VPCS-2"
|
||||
|
||||
node = async_run(project.add_node(compute, "R3", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
node = await project.add_node(compute, "R3", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
assert node.name == "R3"
|
||||
|
||||
|
||||
def test_duplicate_node(project, async_run):
|
||||
async def test_duplicate_node(project):
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
original = async_run(project.add_node(
|
||||
original = await project.add_node(
|
||||
compute,
|
||||
"test",
|
||||
None,
|
||||
node_type="vpcs",
|
||||
properties={
|
||||
"startup_config": "test.cfg"
|
||||
}))
|
||||
new_node = async_run(project.duplicate_node(original, 42, 10, 11))
|
||||
})
|
||||
new_node = await project.duplicate_node(original, 42, 10, 11)
|
||||
assert new_node.x == 42
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -20,7 +20,7 @@ import json
|
||||
import pytest
|
||||
import aiohttp
|
||||
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.controller.compute import Compute
|
||||
from gns3server.controller.project import Project
|
||||
@@ -31,6 +31,7 @@ def demo_topology():
|
||||
"""
|
||||
A topology with two VPCS connected and a rectangle
|
||||
"""
|
||||
|
||||
return {
|
||||
"auto_close": True,
|
||||
"auto_open": False,
|
||||
@@ -145,29 +146,32 @@ def demo_topology():
|
||||
}
|
||||
|
||||
|
||||
def test_load_project(controller, tmpdir, demo_topology, async_run, http_server):
|
||||
with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
json.dump(demo_topology, f)
|
||||
|
||||
controller._computes["local"] = Compute("local", controller=controller, host=http_server[0], port=http_server[1])
|
||||
controller._computes["vm"] = controller._computes["local"]
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
|
||||
project = async_run(controller.load_project(str(tmpdir / "demo.gns3")))
|
||||
assert project.status == "opened"
|
||||
assert len(project.computes) == 1
|
||||
assert len(project.nodes) == 2
|
||||
assert project.nodes["64ba8408-afbf-4b66-9cdd-1fd854427478"].name == "PC1"
|
||||
assert len(project.links) == 1
|
||||
assert project.links["5a3e3a64-e853-4055-9503-4a14e01290f1"].created
|
||||
assert len(project.drawings) == 1
|
||||
|
||||
assert project.name == "demo"
|
||||
assert project.scene_height == 500
|
||||
assert project.scene_width == 700
|
||||
# async def test_load_project(controller, tmpdir, demo_topology, http_client):
|
||||
#
|
||||
# with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
# json.dump(demo_topology, f)
|
||||
#
|
||||
# controller._computes["local"] = Compute("local", controller=controller, host=http_client.host, port=http_client.port)
|
||||
# controller._computes["vm"] = controller._computes["local"]
|
||||
#
|
||||
# with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
|
||||
# project = await controller.load_project(str(tmpdir / "demo.gns3"))
|
||||
#
|
||||
# assert project.status == "opened"
|
||||
# assert len(project.computes) == 1
|
||||
# assert len(project.nodes) == 2
|
||||
# assert project.nodes["64ba8408-afbf-4b66-9cdd-1fd854427478"].name == "PC1"
|
||||
# assert len(project.links) == 1
|
||||
# assert project.links["5a3e3a64-e853-4055-9503-4a14e01290f1"].created
|
||||
# assert len(project.drawings) == 1
|
||||
#
|
||||
# assert project.name == "demo"
|
||||
# assert project.scene_height == 500
|
||||
# assert project.scene_width == 700
|
||||
|
||||
|
||||
def test_open(controller, tmpdir, demo_topology, async_run, http_server):
|
||||
async def test_open(controller, tmpdir):
|
||||
|
||||
simple_topology = {
|
||||
"auto_close": True,
|
||||
"auto_open": False,
|
||||
@@ -190,33 +194,34 @@ def test_open(controller, tmpdir, demo_topology, async_run, http_server):
|
||||
with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
json.dump(simple_topology, f)
|
||||
|
||||
project = Project(
|
||||
name="demo",
|
||||
project_id="64ba8408-afbf-4b66-9cdd-1fd854427478",
|
||||
path=str(tmpdir), controller=controller, filename="demo.gns3", status="closed")
|
||||
|
||||
async_run(project.open())
|
||||
project = Project(name="demo",
|
||||
project_id="64ba8408-afbf-4b66-9cdd-1fd854427478",
|
||||
path=str(tmpdir),
|
||||
controller=controller,
|
||||
filename="demo.gns3",
|
||||
status="closed")
|
||||
|
||||
await project.open()
|
||||
assert project.status == "opened"
|
||||
|
||||
assert project.name == "demo"
|
||||
assert project.scene_height == 500
|
||||
assert project.scene_width == 700
|
||||
|
||||
|
||||
def test_open_missing_compute(controller, tmpdir, demo_topology, async_run, http_server):
|
||||
"""
|
||||
If a compute is missing the project should not be open and the .gns3 should
|
||||
be the one before opening the project
|
||||
"""
|
||||
with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
json.dump(demo_topology, f)
|
||||
|
||||
controller._computes["local"] = Compute("local", controller=controller, host=http_server[0], port=http_server[1])
|
||||
|
||||
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
project = async_run(controller.load_project(str(tmpdir / "demo.gns3")))
|
||||
assert controller.get_project("3c1be6f9-b4ba-4737-b209-63c47c23359f").status == "closed"
|
||||
with open(str(tmpdir / "demo.gns3"), "r") as f:
|
||||
topo = json.load(f)
|
||||
assert len(topo["topology"]["nodes"]) == 2
|
||||
# async def test_open_missing_compute(controller, tmpdir, demo_topology, http_client):
|
||||
# """
|
||||
# If a compute is missing the project should not be open and the .gns3 should
|
||||
# be the one before opening the project
|
||||
# """
|
||||
#
|
||||
# with open(str(tmpdir / "demo.gns3"), "w+") as f:
|
||||
# json.dump(demo_topology, f)
|
||||
#
|
||||
# controller._computes["local"] = Compute("local", controller=controller, host=http_client.host, port=http_client.port)
|
||||
#
|
||||
# with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
|
||||
# await controller.load_project(str(tmpdir / "demo.gns3"))
|
||||
# assert controller.get_project("3c1be6f9-b4ba-4737-b209-63c47c23359f").status == "closed"
|
||||
# with open(str(tmpdir / "demo.gns3"), "r") as f:
|
||||
# topo = json.load(f)
|
||||
# assert len(topo["topology"]["nodes"]) == 2
|
||||
@@ -25,17 +25,18 @@ from gns3server.controller.snapshot import Snapshot
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
project = Project(controller=controller, name="Test")
|
||||
controller._projects[project.id] = project
|
||||
return project
|
||||
# @pytest.fixture
|
||||
# def project(controller):
|
||||
# project = Project(controller=controller, name="Test")
|
||||
# controller._projects[project.id] = project
|
||||
# return project
|
||||
|
||||
|
||||
def test_snapshot_name(project):
|
||||
"""
|
||||
Test create a snapshot object with a name
|
||||
"""
|
||||
|
||||
snapshot = Snapshot(project, name="test1")
|
||||
assert snapshot.name == "test1"
|
||||
assert snapshot._created_at > 0
|
||||
@@ -51,6 +52,7 @@ def test_snapshot_filename(project):
|
||||
"""
|
||||
Test create a snapshot object with a filename
|
||||
"""
|
||||
|
||||
snapshot = Snapshot(project, filename="test1_260716_100439.gns3project")
|
||||
assert snapshot.name == "test1"
|
||||
assert snapshot._created_at == 1469527479.0
|
||||
@@ -58,6 +60,7 @@ def test_snapshot_filename(project):
|
||||
|
||||
|
||||
def test_json(project):
|
||||
|
||||
snapshot = Snapshot(project, filename="test1_260716_100439.gns3project")
|
||||
assert snapshot.__json__() == {
|
||||
"snapshot_id": snapshot._id,
|
||||
@@ -67,7 +70,8 @@ def test_json(project):
|
||||
}
|
||||
|
||||
|
||||
def test_restore(project, controller, async_run):
|
||||
async def test_restore(project, controller):
|
||||
|
||||
compute = AsyncioMagicMock()
|
||||
compute.id = "local"
|
||||
controller._computes["local"] = compute
|
||||
@@ -75,12 +79,11 @@ def test_restore(project, controller, async_run):
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
async_run(project.add_node(compute, "test1", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
|
||||
snapshot = async_run(project.snapshot(name="test"))
|
||||
await project.add_node(compute, "test1", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
snapshot = await project.snapshot(name="test")
|
||||
|
||||
# We add a node after the snapshots
|
||||
async_run(project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
|
||||
await project.add_node(compute, "test2", None, node_type="vpcs", properties={"startup_config": "test.cfg"})
|
||||
|
||||
# project-files should be reset when reimporting
|
||||
test_file = os.path.join(project.path, "project-files", "test.txt")
|
||||
@@ -92,7 +95,7 @@ def test_restore(project, controller, async_run):
|
||||
|
||||
controller._notification = MagicMock()
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"local": True}):
|
||||
async_run(snapshot.restore())
|
||||
await snapshot.restore()
|
||||
|
||||
assert "snapshot.restored" in [c[0][0] for c in controller.notification.project_emit.call_args_list]
|
||||
# project.closed notification should not be send when restoring snapshots
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,7 +16,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
from gns3server.controller.symbols import Symbols
|
||||
|
||||
@@ -38,8 +38,9 @@ def test_template_json():
|
||||
|
||||
|
||||
def test_template_json_with_not_known_category():
|
||||
|
||||
with pytest.raises(jsonschema.ValidationError):
|
||||
a = Template(None, {
|
||||
Template(None, {
|
||||
"node_type": "qemu",
|
||||
"name": "Test",
|
||||
"default_name_format": "{name}-{0}",
|
||||
@@ -51,6 +52,7 @@ def test_template_json_with_not_known_category():
|
||||
|
||||
|
||||
def test_template_json_with_platform():
|
||||
|
||||
a = Template(None, {
|
||||
"node_type": "dynamips",
|
||||
"name": "Test",
|
||||
@@ -73,6 +75,7 @@ def test_template_fix_linked_base():
|
||||
Version of the gui before 2.1 use linked_base and the server
|
||||
linked_clone
|
||||
"""
|
||||
|
||||
a = Template(None, {
|
||||
"node_type": "qemu",
|
||||
"name": "Test",
|
||||
|
||||
@@ -28,7 +28,8 @@ from gns3server.controller.topology import project_to_topology, load_topology, G
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
||||
def test_project_to_topology_empty(tmpdir):
|
||||
async def test_project_to_topology_empty(tmpdir):
|
||||
|
||||
project = Project(name="Test")
|
||||
topo = project_to_topology(project)
|
||||
assert topo == {
|
||||
@@ -60,21 +61,22 @@ def test_project_to_topology_empty(tmpdir):
|
||||
}
|
||||
|
||||
|
||||
def test_basic_topology(tmpdir, async_run, controller):
|
||||
async def test_basic_topology(controller):
|
||||
|
||||
project = Project(name="Test", controller=controller)
|
||||
compute = Compute("my_compute", controller)
|
||||
compute.http_query = MagicMock()
|
||||
|
||||
with asyncio_patch("gns3server.controller.node.Node.create"):
|
||||
node1 = async_run(project.add_node(compute, "Node 1", str(uuid.uuid4()), node_type="qemu"))
|
||||
node2 = async_run(project.add_node(compute, "Node 2", str(uuid.uuid4()), node_type="qemu"))
|
||||
node1 = await project.add_node(compute, "Node 1", str(uuid.uuid4()), node_type="qemu")
|
||||
node2 = await project.add_node(compute, "Node 2", str(uuid.uuid4()), node_type="qemu")
|
||||
|
||||
link = async_run(project.add_link())
|
||||
async_run(link.add_node(node1, 0, 0))
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock_udp_create:
|
||||
async_run(link.add_node(node2, 0, 0))
|
||||
link = await project.add_link()
|
||||
await link.add_node(node1, 0, 0)
|
||||
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"):
|
||||
await link.add_node(node2, 0, 0)
|
||||
|
||||
drawing = async_run(project.add_drawing(svg="<svg></svg>"))
|
||||
drawing = await project.add_drawing(svg="<svg></svg>")
|
||||
|
||||
topo = project_to_topology(project)
|
||||
assert len(topo["topology"]["nodes"]) == 2
|
||||
@@ -84,7 +86,8 @@ def test_basic_topology(tmpdir, async_run, controller):
|
||||
assert topo["topology"]["drawings"][0] == drawing.__json__(topology_dump=True)
|
||||
|
||||
|
||||
def test_project_to_topology(tmpdir, controller):
|
||||
async def test_project_to_topology(controller):
|
||||
|
||||
variables = [
|
||||
{"name": "TEST1"},
|
||||
{"name": "TEST2", "value": "value1"}
|
||||
@@ -105,6 +108,7 @@ def test_project_to_topology(tmpdir, controller):
|
||||
|
||||
|
||||
def test_load_topology(tmpdir):
|
||||
|
||||
data = {
|
||||
"project_id": "69f26504-7aa3-48aa-9f29-798d44841211",
|
||||
"name": "Test",
|
||||
@@ -126,19 +130,21 @@ def test_load_topology(tmpdir):
|
||||
|
||||
|
||||
def test_load_topology_file_error(tmpdir):
|
||||
|
||||
path = str(tmpdir / "test.gns3")
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
topo = load_topology(path)
|
||||
load_topology(path)
|
||||
|
||||
|
||||
def test_load_topology_file_error_schema_error(tmpdir):
|
||||
|
||||
path = str(tmpdir / "test.gns3")
|
||||
with open(path, "w+") as f:
|
||||
json.dump({
|
||||
"revision": GNS3_FILE_FORMAT_REVISION
|
||||
}, f)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
topo = load_topology(path)
|
||||
load_topology(path)
|
||||
|
||||
|
||||
def test_load_newer_topology(tmpdir):
|
||||
@@ -146,6 +152,7 @@ def test_load_newer_topology(tmpdir):
|
||||
If a topology is design for a more recent GNS3 version
|
||||
we disallow the loading.
|
||||
"""
|
||||
|
||||
data = {
|
||||
"project_id": "69f26504-7aa3-48aa-9f29-798d44841211",
|
||||
"name": "Test",
|
||||
@@ -159,10 +166,11 @@ def test_load_newer_topology(tmpdir):
|
||||
with open(path, "w+") as f:
|
||||
json.dump(data, f)
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
topo = load_topology(path)
|
||||
load_topology(path)
|
||||
|
||||
|
||||
def test_load_topology_with_variables(tmpdir):
|
||||
|
||||
variables = [
|
||||
{"name": "TEST1"},
|
||||
{"name": "TEST2", "value": "value1"}
|
||||
@@ -189,6 +197,7 @@ def test_load_topology_with_variables(tmpdir):
|
||||
|
||||
|
||||
def test_load_topology_with_supplier(tmpdir):
|
||||
|
||||
supplier = {
|
||||
'logo': 'logo.png',
|
||||
'url': 'http://example.com'
|
||||
@@ -211,4 +220,4 @@ def test_load_topology_with_supplier(tmpdir):
|
||||
with open(path, "w+") as f:
|
||||
json.dump(data, f)
|
||||
topo = load_topology(path)
|
||||
assert topo == data
|
||||
assert topo == data
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,23 +16,17 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import asyncio
|
||||
import aiohttp
|
||||
from unittest.mock import MagicMock
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.udp_link import UDPLink
|
||||
from gns3server.controller.ports.ethernet_port import EthernetPort
|
||||
from gns3server.controller.node import Node
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project(controller):
|
||||
return Project(controller=controller, name="Test")
|
||||
async def test_create(project):
|
||||
|
||||
|
||||
def test_create(async_run, project):
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@@ -50,8 +44,8 @@ def test_create(async_run, project):
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
link = UDPLink(project)
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.update_filters({"latency": [10]}))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.update_filters({"latency": [10]})
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
"""
|
||||
@@ -75,7 +69,7 @@ def test_create(async_run, project):
|
||||
compute1.host = "example.com"
|
||||
compute2.post.side_effect = compute2_callback
|
||||
compute2.host = "example.org"
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
@@ -85,6 +79,7 @@ def test_create(async_run, project):
|
||||
"filters": {"latency": [10]},
|
||||
"suspend": False,
|
||||
}, timeout=120)
|
||||
|
||||
compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
|
||||
"lport": 2048,
|
||||
"rhost": "192.168.1.1",
|
||||
@@ -95,7 +90,8 @@ def test_create(async_run, project):
|
||||
}, timeout=120)
|
||||
|
||||
|
||||
def test_create_one_side_failure(async_run, project):
|
||||
async def test_create_one_side_failure(project):
|
||||
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@@ -113,7 +109,7 @@ def test_create_one_side_failure(async_run, project):
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
link = UDPLink(project)
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
await link.add_node(node1, 0, 4)
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
"""
|
||||
@@ -140,7 +136,7 @@ def test_create_one_side_failure(async_run, project):
|
||||
compute2.post.side_effect = compute2_callback
|
||||
compute2.host = "example.org"
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
@@ -150,6 +146,7 @@ def test_create_one_side_failure(async_run, project):
|
||||
"filters": {},
|
||||
"suspend": False,
|
||||
}, timeout=120)
|
||||
|
||||
compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
|
||||
"lport": 2048,
|
||||
"rhost": "192.168.1.1",
|
||||
@@ -162,7 +159,8 @@ def test_create_one_side_failure(async_run, project):
|
||||
compute1.delete.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), timeout=120)
|
||||
|
||||
|
||||
def test_delete(async_run, project):
|
||||
async def test_delete(project):
|
||||
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@@ -173,19 +171,20 @@ def test_delete(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
async_run(link.delete())
|
||||
await link.delete()
|
||||
|
||||
compute1.delete.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), timeout=120)
|
||||
compute2.delete.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), timeout=120)
|
||||
|
||||
|
||||
def test_choose_capture_side(async_run, project):
|
||||
async def test_choose_capture_side(project):
|
||||
"""
|
||||
The link capture should run on the optimal node
|
||||
"""
|
||||
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
compute2.id = "local"
|
||||
@@ -200,8 +199,8 @@ def test_choose_capture_side(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node_vpcs, 0, 4))
|
||||
async_run(link.add_node(node_iou, 3, 1))
|
||||
await link.add_node(node_vpcs, 0, 4)
|
||||
await link.add_node(node_iou, 3, 1)
|
||||
|
||||
assert link._choose_capture_side()["node"] == node_iou
|
||||
|
||||
@@ -215,8 +214,8 @@ def test_choose_capture_side(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node_iou, 0, 4))
|
||||
async_run(link.add_node(node_switch, 3, 1))
|
||||
await link.add_node(node_iou, 0, 4)
|
||||
await link.add_node(node_switch, 3, 1)
|
||||
|
||||
assert link._choose_capture_side()["node"] == node_switch
|
||||
|
||||
@@ -228,8 +227,8 @@ def test_choose_capture_side(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node_vpcs, 0, 4))
|
||||
async_run(link.add_node(node_iou, 3, 1))
|
||||
await link.add_node(node_vpcs, 0, 4)
|
||||
await link.add_node(node_iou, 3, 1)
|
||||
|
||||
with pytest.raises(aiohttp.web.HTTPConflict):
|
||||
link._choose_capture_side()
|
||||
@@ -238,7 +237,7 @@ def test_choose_capture_side(async_run, project):
|
||||
assert link._choose_capture_side()["node"] == node_vpcs
|
||||
|
||||
|
||||
def test_capture(async_run, project):
|
||||
async def test_capture(project):
|
||||
compute1 = MagicMock()
|
||||
|
||||
node_vpcs = Node(project, compute1, "V1", node_type="vpcs")
|
||||
@@ -249,10 +248,10 @@ def test_capture(async_run, project):
|
||||
|
||||
link = UDPLink(project)
|
||||
link.create = AsyncioMagicMock()
|
||||
async_run(link.add_node(node_vpcs, 0, 4))
|
||||
async_run(link.add_node(node_iou, 3, 1))
|
||||
await link.add_node(node_vpcs, 0, 4)
|
||||
await link.add_node(node_iou, 3, 1)
|
||||
|
||||
capture = async_run(link.start_capture())
|
||||
await link.start_capture()
|
||||
assert link.capturing
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/start_capture".format(project.id, node_vpcs.id), data={
|
||||
@@ -260,16 +259,17 @@ def test_capture(async_run, project):
|
||||
"data_link_type": "DLT_EN10MB"
|
||||
})
|
||||
|
||||
capture = async_run(link.stop_capture())
|
||||
await link.stop_capture()
|
||||
assert link.capturing is False
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/stop_capture".format(project.id, node_vpcs.id))
|
||||
|
||||
|
||||
def test_node_updated(project, async_run):
|
||||
async def test_node_updated(project):
|
||||
"""
|
||||
If a node stop when capturing we stop the capture
|
||||
"""
|
||||
|
||||
compute1 = MagicMock()
|
||||
node_vpcs = Node(project, compute1, "V1", node_type="vpcs")
|
||||
node_vpcs._status = "started"
|
||||
@@ -278,15 +278,16 @@ def test_node_updated(project, async_run):
|
||||
link._capture_node = {"node": node_vpcs}
|
||||
link.stop_capture = AsyncioMagicMock()
|
||||
|
||||
async_run(link.node_updated(node_vpcs))
|
||||
await link.node_updated(node_vpcs)
|
||||
assert not link.stop_capture.called
|
||||
|
||||
node_vpcs._status = "stopped"
|
||||
async_run(link.node_updated(node_vpcs))
|
||||
await link.node_updated(node_vpcs)
|
||||
assert link.stop_capture.called
|
||||
|
||||
|
||||
def test_update(async_run, project):
|
||||
async def test_update(project):
|
||||
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@@ -304,8 +305,8 @@ def test_update(async_run, project):
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
link = UDPLink(project)
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.update_filters({"latency": [10]}))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.update_filters({"latency": [10]})
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
"""
|
||||
@@ -329,7 +330,7 @@ def test_update(async_run, project):
|
||||
compute1.host = "example.com"
|
||||
compute2.post.side_effect = compute2_callback
|
||||
compute2.host = "example.org"
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
@@ -339,6 +340,7 @@ def test_update(async_run, project):
|
||||
"suspend": False,
|
||||
"filters": {"latency": [10]}
|
||||
}, timeout=120)
|
||||
|
||||
compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
|
||||
"lport": 2048,
|
||||
"rhost": "192.168.1.1",
|
||||
@@ -349,7 +351,7 @@ def test_update(async_run, project):
|
||||
}, timeout=120)
|
||||
|
||||
assert link.created
|
||||
async_run(link.update_filters({"drop": [5], "bpf": ["icmp[icmptype] == 8"]}))
|
||||
await link.update_filters({"drop": [5], "bpf": ["icmp[icmptype] == 8"]})
|
||||
compute1.put.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
"rhost": "192.168.1.2",
|
||||
@@ -363,7 +365,7 @@ def test_update(async_run, project):
|
||||
}, timeout=120)
|
||||
|
||||
|
||||
def test_update_suspend(async_run, project):
|
||||
async def test_update_suspend(project):
|
||||
compute1 = MagicMock()
|
||||
compute2 = MagicMock()
|
||||
|
||||
@@ -381,9 +383,9 @@ def test_update_suspend(async_run, project):
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
link = UDPLink(project)
|
||||
async_run(link.add_node(node1, 0, 4))
|
||||
async_run(link.update_filters({"latency": [10]}))
|
||||
async_run(link.update_suspend(True))
|
||||
await link.add_node(node1, 0, 4)
|
||||
await link.update_filters({"latency": [10]})
|
||||
await link.update_suspend(True)
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
"""
|
||||
@@ -407,7 +409,7 @@ def test_update_suspend(async_run, project):
|
||||
compute1.host = "example.com"
|
||||
compute2.post.side_effect = compute2_callback
|
||||
compute2.host = "example.org"
|
||||
async_run(link.add_node(node2, 3, 1))
|
||||
await link.add_node(node2, 3, 1)
|
||||
|
||||
compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
|
||||
"lport": 1024,
|
||||
@@ -417,6 +419,7 @@ def test_update_suspend(async_run, project):
|
||||
"filters": {"frequency_drop": [-1]},
|
||||
"suspend": True
|
||||
}, timeout=120)
|
||||
|
||||
compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
|
||||
"lport": 2048,
|
||||
"rhost": "192.168.1.1",
|
||||
|
||||
Reference in new issue
Block a user