Create /hypervisor and /controller namespace

This commit is contained in:
Julien Duponchelle committed 2016-03-07 15:01:35 +01:00
1 parent e4b12f49d1
commit 664cec97ba
231 files changed
+1576 -1480

No files matched your search

Whitespace-only changes.
@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from unittest.mock import MagicMock, patch
from gns3server.config import Config
def test_reload_accepted(http_hypervisor):
gns_config = MagicMock()
config = Config.instance()
config.set("Server", "local", "true")
gns_config.get_section_config.return_value = config.get_section_config("Server")
with patch("gns3server.config.Config.instance", return_value=gns_config):
response = http_hypervisor.post('/config/reload', example=True)
assert response.status == 201
assert gns_config.reload.called
def test_reload_forbidden(http_hypervisor):
config = Config.instance()
config.set("Server", "local", "false")
response = http_hypervisor.post('/config/reload')
assert response.status == 403
@@ -0,0 +1,184 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
import os
import stat
import sys
import uuid
import aiohttp
from tests.utils import asyncio_patch
from unittest.mock import patch, MagicMock, PropertyMock
from gns3server.modules.docker import Docker
@pytest.fixture
def base_params():
"""Return standard parameters"""
return {"name": "PC TEST 1", "image": "nginx", "start_command": "nginx-daemon", "adapters": 2, "environment": "YES=1\nNO=0", "console_type": "telnet"}
@pytest.yield_fixture(autouse=True)
def mock_connection():
docker = Docker.instance()
docker._connected = True
docker._connector = MagicMock()
yield
Docker._instance = None
@pytest.fixture
def vm(http_hypervisor, project, base_params):
with asyncio_patch("gns3server.modules.docker.Docker.list_images", return_value=[{"image": "nginx"}]) as mock_list:
with asyncio_patch("gns3server.modules.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}) as mock:
response = http_hypervisor.post("/projects/{project_id}/docker/vms".format(project_id=project.id), base_params)
if response.status != 201:
print(response.body)
assert response.status == 201
return response.json
def test_docker_create(http_hypervisor, project, base_params):
with asyncio_patch("gns3server.modules.docker.Docker.list_images", return_value=[{"image": "nginx"}]) as mock_list:
with asyncio_patch("gns3server.modules.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}) as mock:
response = http_hypervisor.post("/projects/{project_id}/docker/vms".format(project_id=project.id), base_params)
assert response.status == 201
assert response.route == "/projects/{project_id}/docker/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["container_id"] == "8bd8153ea8f5"
assert response.json["image"] == "nginx"
assert response.json["adapters"] == 2
assert response.json["environment"] == "YES=1\nNO=0"
def test_docker_start(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.start", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_docker_stop(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.stop", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_docker_reload(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.restart", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_docker_delete(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.delete", return_value=True) as mock:
response = http_hypervisor.delete("/projects/{project_id}/docker/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_docker_reload(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.pause", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 204
def test_docker_nio_create_udp(http_hypervisor, vm):
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/docker/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp"
def test_docker_delete_nio(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.adapter_remove_nio_binding") as mock:
response = http_hypervisor.delete("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 204
assert response.route == "/projects/{project_id}/docker/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_docker_update(http_hypervisor, vm, tmpdir, free_console_port):
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.update") as mock:
response = http_hypervisor.put("/projects/{project_id}/docker/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test",
"console": free_console_port,
"start_command": "yes",
"environment": "GNS3=1\nGNS4=0"},
example=True)
assert mock.called
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
assert response.json["start_command"] == "yes"
assert response.json["environment"] == "GNS3=1\nGNS4=0"
def test_docker_start_capture(http_hypervisor, vm, tmpdir, project):
with patch("gns3server.modules.docker.docker_vm.DockerVM.is_running", return_value=True) as mock:
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.start_capture") as start_capture:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=params, example=True)
assert response.status == 200
assert start_capture.called
assert "test.pcap" in response.json["pcap_file_path"]
def test_docker_start_capture_not_started(http_hypervisor, vm, tmpdir):
with patch("gns3server.modules.docker.docker_vm.DockerVM.is_running", return_value=False) as mock:
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.start_capture") as start_capture:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=params)
assert not start_capture.called
assert response.status == 409
def test_docker_stop_capture(http_hypervisor, vm, tmpdir, project):
with patch("gns3server.modules.docker.docker_vm.DockerVM.is_running", return_value=True) as mock:
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.stop_capture") as stop_capture:
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 204
assert stop_capture.called
def test_docker_stop_capture_not_started(http_hypervisor, vm, tmpdir):
with patch("gns3server.modules.docker.docker_vm.DockerVM.is_running", return_value=False) as mock:
with asyncio_patch("gns3server.modules.docker.docker_vm.DockerVM.stop_capture") as stop_capture:
response = http_hypervisor.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert not stop_capture.called
assert response.status == 409
@@ -0,0 +1,182 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
import os
import stat
from unittest.mock import patch
from tests.utils import asyncio_patch
# @pytest.yield_fixture(scope="module")
# def vm(http_hypervisor, project):
#
# dynamips_path = "/fake/dynamips"
# with asyncio_patch("gns3server.modules.dynamips.nodes.router.Router.create", return_value=True) as mock:
# response = http_hypervisor.post("/projects/{project_id}/dynamips/vms".format(project_id=project.id), {"name": "My router",
# "platform": "c3745",
# "image": "somewhere",
# "ram": 128})
# assert mock.called
# assert response.status == 201
#
# with asyncio_patch("gns3server.modules.dynamips.Dynamips.find_dynamips", return_value=dynamips_path):
# yield response.json
#
#
# def test_dynamips_vm_create(http_hypervisor, project):
#
# with asyncio_patch("gns3server.modules.dynamips.nodes.router.Router.create", return_value=True):
# response = http_hypervisor.post("/projects/{project_id}/dynamips/vms".format(project_id=project.id), {"name": "My router",
# "platform": "c3745",
# "image": "somewhere",
# "ram": 128},
# example=True)
# assert response.status == 201
# assert response.json["name"] == "My router"
# assert response.json["project_id"] == project.id
# assert response.json["dynamips_id"]
#
#
# def test_dynamips_vm_get(http_hypervisor, project, vm):
# response = http_hypervisor.get("/projects/{project_id}/dynamips/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
# assert response.status == 200
# assert response.route == "/projects/{project_id}/dynamips/vms/{vm_id}"
# assert response.json["name"] == "My router"
# assert response.json["project_id"] == project.id
#
#
# def test_dynamips_vm_start(http_hypervisor, vm):
# with asyncio_patch("gns3server.modules.dynamips.nodes.router.Router.start", return_value=True) as mock:
# response = http_hypervisor.post("/projects/{project_id}/dynamips/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
# assert mock.called
# assert response.status == 204
#
#
# def test_dynamips_vm_stop(http_hypervisor, vm):
# with asyncio_patch("gns3server.modules.dynamips.nodes.router.Router.stop", return_value=True) as mock:
# response = http_hypervisor.post("/projects/{project_id}/dynamips/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
# assert mock.called
# assert response.status == 204
#
#
# def test_dynamips_vm_suspend(http_hypervisor, vm):
# with asyncio_patch("gns3server.modules.dynamips.nodes.router.Router.suspend", return_value=True) as mock:
# response = http_hypervisor.post("/projects/{project_id}/dynamips/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
# assert mock.called
# assert response.status == 204
#
#
# def test_dynamips_vm_resume(http_hypervisor, vm):
# with asyncio_patch("gns3server.modules.dynamips.nodes.router.Router.resume", return_value=True) as mock:
# response = http_hypervisor.post("/projects/{project_id}/dynamips/vms/{vm_id}/resume".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
# assert mock.called
# assert response.status == 204
# def test_vbox_nio_create_udp(http_hypervisor, vm):
#
# with asyncio_patch('gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
# response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/0/nio".format(project_id=vm["project_id"],
# vm_id=vm["vm_id"]), {"type": "nio_udp",
# "lport": 4242,
# "rport": 4343,
# "rhost": "127.0.0.1"},
# example=True)
#
# assert mock.called
# args, kwgars = mock.call_args
# assert args[0] == 0
#
# assert response.status == 201
# assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio"
# assert response.json["type"] == "nio_udp"
#
#
# def test_vbox_delete_nio(http_hypervisor, vm):
#
# with asyncio_patch('gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
# response = http_hypervisor.delete("/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
#
# assert mock.called
# args, kwgars = mock.call_args
# assert args[0] == 0
#
# assert response.status == 204
# assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio"
#
#
# def test_vbox_update(http_hypervisor, vm, free_console_port):
# response = http_hypervisor.put("/projects/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test",
# "console": free_console_port})
# assert response.status == 200
# assert response.json["name"] == "test"
# assert response.json["console"] == free_console_port
@pytest.fixture
def fake_dynamips(tmpdir):
"""Create a fake Dynamips image on disk"""
path = str(tmpdir / "7200.bin")
with open(path, "wb+") as f:
f.write(b'\x7fELF\x01\x02\x01')
os.chmod(path, stat.S_IREAD)
return path
@pytest.fixture
def fake_file(tmpdir):
"""Create a fake file disk"""
path = str(tmpdir / "7200.txt")
with open(path, "w+") as f:
f.write('1')
os.chmod(path, stat.S_IREAD)
return path
def test_vms(http_hypervisor, tmpdir, fake_dynamips, fake_file):
with patch("gns3server.modules.Dynamips.get_images_directory", return_value=str(tmpdir), example=True):
response = http_hypervisor.get("/dynamips/vms")
assert response.status == 200
assert response.json == [{"filename": "7200.bin", "path": "7200.bin"}]
def test_upload_vm(http_hypervisor, tmpdir):
with patch("gns3server.modules.Dynamips.get_images_directory", return_value=str(tmpdir),):
response = http_hypervisor.post("/dynamips/vms/test2", body="TEST", raw=True)
assert response.status == 204
with open(str(tmpdir / "test2")) as f:
assert f.read() == "TEST"
with open(str(tmpdir / "test2.md5sum")) as f:
checksum = f.read()
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
def test_upload_vm_permission_denied(http_hypervisor, tmpdir):
with open(str(tmpdir / "test2"), "w+") as f:
f.write("")
os.chmod(str(tmpdir / "test2"), 0)
with patch("gns3server.modules.Dynamips.get_images_directory", return_value=str(tmpdir),):
response = http_hypervisor.post("/dynamips/vms/test2", body="TEST", raw=True)
assert response.status == 409
@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
This test suite check /files endpoint
"""
import json
import asyncio
import aiohttp
from gns3server.version import __version__
def test_stream(http_hypervisor, tmpdir, loop):
with open(str(tmpdir / "test"), 'w+') as f:
f.write("hello")
def go(future):
query = json.dumps({"location": str(tmpdir / "test")})
headers = {'content-type': 'application/json'}
response = yield from aiohttp.request("GET", http_hypervisor.get_url("/files/stream"), data=query, headers=headers)
response.body = yield from response.content.read(5)
with open(str(tmpdir / "test"), 'a') as f:
f.write("world")
response.body += yield from response.content.read(5)
response.close()
future.set_result(response)
future = asyncio.Future()
asyncio.async(go(future))
response = loop.run_until_complete(future)
assert response.status == 200
assert response.body == b'helloworld'
def test_stream_file_not_found(http_hypervisor, tmpdir, loop):
def go(future):
query = json.dumps({"location": str(tmpdir / "test")})
headers = {'content-type': 'application/json'}
response = yield from aiohttp.request("GET", http_hypervisor.get_url("/files/stream"), data=query, headers=headers)
response.close()
future.set_result(response)
future = asyncio.Future()
asyncio.async(go(future))
response = loop.run_until_complete(future)
assert response.status == 404
+359
View File
@@ -0,0 +1,359 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
import os
import stat
import sys
import uuid
import aiohttp
from tests.utils import asyncio_patch
from unittest.mock import patch, MagicMock, PropertyMock
pytestmark = pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
@pytest.fixture
def fake_iou_bin(tmpdir):
"""Create a fake IOU image on disk"""
path = str(tmpdir / "iou.bin")
with open(path, "w+") as f:
f.write('\x7fELF\x01\x01\x01')
os.chmod(path, stat.S_IREAD | stat.S_IEXEC)
return path
@pytest.fixture
def base_params(tmpdir, fake_iou_bin):
"""Return standard parameters"""
return {"name": "PC TEST 1", "path": "iou.bin"}
@pytest.fixture
def vm(http_hypervisor, project, base_params):
response = http_hypervisor.post("/projects/{project_id}/iou/vms".format(project_id=project.id), base_params)
assert response.status == 201
return response.json
def startup_config_file(project, vm):
directory = os.path.join(project.path, "project-files", "iou", vm["vm_id"])
os.makedirs(directory, exist_ok=True)
return os.path.join(directory, "startup-config.cfg")
def test_iou_create(http_hypervisor, project, base_params):
response = http_hypervisor.post("/projects/{project_id}/iou/vms".format(project_id=project.id), base_params)
assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["serial_adapters"] == 2
assert response.json["ethernet_adapters"] == 2
assert response.json["ram"] == 256
assert response.json["nvram"] == 128
assert response.json["l1_keepalives"] is False
def test_iou_create_with_params(http_hypervisor, project, base_params):
params = base_params
params["ram"] = 1024
params["nvram"] = 512
params["serial_adapters"] = 4
params["ethernet_adapters"] = 0
params["l1_keepalives"] = True
params["startup_config_content"] = "hostname test"
params["use_default_iou_values"] = True
params["iourc_content"] = "test"
response = http_hypervisor.post("/projects/{project_id}/iou/vms".format(project_id=project.id), params, example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["serial_adapters"] == 4
assert response.json["ethernet_adapters"] == 0
assert response.json["ram"] == 1024
assert response.json["nvram"] == 512
assert response.json["l1_keepalives"] is True
assert response.json["use_default_iou_values"] is True
assert "startup-config.cfg" in response.json["startup_config"]
with open(startup_config_file(project, response.json)) as f:
assert f.read() == "hostname test"
assert "iourc" in response.json["iourc_path"]
def test_iou_create_startup_config_already_exist(http_hypervisor, project, base_params):
"""We don't erase a startup-config if already exist at project creation"""
vm_id = str(uuid.uuid4())
startup_config_file_path = startup_config_file(project, {'vm_id': vm_id})
with open(startup_config_file_path, 'w+') as f:
f.write("echo hello")
params = base_params
params["vm_id"] = vm_id
params["startup_config_content"] = "hostname test"
response = http_hypervisor.post("/projects/{project_id}/iou/vms".format(project_id=project.id), params, example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms"
assert "startup-config.cfg" in response.json["startup_config"]
with open(startup_config_file(project, response.json)) as f:
assert f.read() == "echo hello"
def test_iou_get(http_hypervisor, project, vm):
response = http_hypervisor.get("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 200
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["serial_adapters"] == 2
assert response.json["ethernet_adapters"] == 2
assert response.json["ram"] == 256
assert response.json["nvram"] == 128
assert response.json["l1_keepalives"] is False
def test_iou_start(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.start", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert mock.called
assert response.status == 200
assert response.json["name"] == "PC TEST 1"
def test_iou_start_with_iourc(http_hypervisor, vm, tmpdir):
body = {"iourc_content": "test"}
with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.start", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=body, example=True)
assert mock.called
assert response.status == 200
response = http_hypervisor.get("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert response.status == 200
with open(response.json["iourc_path"]) as f:
assert f.read() == "test"
def test_iou_stop(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.stop", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_iou_reload(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.reload", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_iou_delete(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.iou.IOU.delete_vm", return_value=True) as mock:
response = http_hypervisor.delete("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_iou_update(http_hypervisor, vm, tmpdir, free_console_port, project):
params = {
"name": "test",
"console": free_console_port,
"ram": 512,
"nvram": 2048,
"ethernet_adapters": 4,
"serial_adapters": 0,
"l1_keepalives": True,
"startup_config_content": "hostname test",
"use_default_iou_values": True,
"iourc_content": "test"
}
response = http_hypervisor.put("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), params, example=True)
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
assert response.json["ethernet_adapters"] == 4
assert response.json["serial_adapters"] == 0
assert response.json["ram"] == 512
assert response.json["nvram"] == 2048
assert response.json["l1_keepalives"] is True
assert response.json["use_default_iou_values"] is True
assert "startup-config.cfg" in response.json["startup_config"]
with open(startup_config_file(project, response.json)) as f:
assert f.read() == "hostname test"
assert "iourc" in response.json["iourc_path"]
def test_iou_nio_create_udp(http_hypervisor, vm):
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp"
def test_iou_nio_create_ethernet(http_hypervisor, vm, ethernet_device):
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_generic_ethernet",
"ethernet_device": ethernet_device,
},
example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_generic_ethernet"
assert response.json["ethernet_device"] == ethernet_device
def test_iou_nio_create_ethernet_different_port(http_hypervisor, vm, ethernet_device):
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/3/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_generic_ethernet",
"ethernet_device": ethernet_device,
},
example=False)
assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_generic_ethernet"
assert response.json["ethernet_device"] == ethernet_device
def test_iou_nio_create_tap(http_hypervisor, vm, ethernet_device):
with patch("gns3server.modules.base_manager.BaseManager.has_privileged_access", return_value=True):
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_tap",
"tap_device": ethernet_device})
assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_tap"
def test_iou_delete_nio(http_hypervisor, vm):
http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"})
response = http_hypervisor.delete("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 204
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_iou_start_capture(http_hypervisor, vm, tmpdir, project):
with patch("gns3server.modules.iou.iou_vm.IOUVM.is_running", return_value=True) as mock:
with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.start_capture") as start_capture:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=params, example=True)
assert response.status == 200
assert start_capture.called
assert "test.pcap" in response.json["pcap_file_path"]
def test_iou_start_capture_not_started(http_hypervisor, vm, tmpdir):
with patch("gns3server.modules.iou.iou_vm.IOUVM.is_running", return_value=False) as mock:
with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.start_capture") as start_capture:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=params)
assert not start_capture.called
assert response.status == 409
def test_iou_stop_capture(http_hypervisor, vm, tmpdir, project):
with patch("gns3server.modules.iou.iou_vm.IOUVM.is_running", return_value=True) as mock:
with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.stop_capture") as stop_capture:
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 204
assert stop_capture.called
def test_iou_stop_capture_not_started(http_hypervisor, vm, tmpdir):
with patch("gns3server.modules.iou.iou_vm.IOUVM.is_running", return_value=False) as mock:
with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.stop_capture") as stop_capture:
response = http_hypervisor.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]))
assert not stop_capture.called
assert response.status == 409
def test_get_configs_without_configs_file(http_hypervisor, vm):
response = http_hypervisor.get("/projects/{project_id}/iou/vms/{vm_id}/configs".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 200
assert "startup_config" not in response.json
assert "private_config" not in response.json
def test_get_configs_with_startup_config_file(http_hypervisor, project, vm):
path = startup_config_file(project, vm)
with open(path, "w+") as f:
f.write("TEST")
response = http_hypervisor.get("/projects/{project_id}/iou/vms/{vm_id}/configs".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 200
assert response.json["startup_config_content"] == "TEST"
def test_vms(http_hypervisor, tmpdir, fake_iou_bin):
with patch("gns3server.modules.IOU.get_images_directory", return_value=str(tmpdir)):
response = http_hypervisor.get("/iou/vms", example=True)
assert response.status == 200
assert response.json == [{"filename": "iou.bin", "path": "iou.bin"}]
def test_upload_vm(http_hypervisor, tmpdir):
with patch("gns3server.modules.IOU.get_images_directory", return_value=str(tmpdir),):
response = http_hypervisor.post("/iou/vms/test2", body="TEST", raw=True)
assert response.status == 204
with open(str(tmpdir / "test2")) as f:
assert f.read() == "TEST"
with open(str(tmpdir / "test2.md5sum")) as f:
checksum = f.read()
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
def test_upload_vm_permission_denied(http_hypervisor, tmpdir):
with open(str(tmpdir / "test2"), "w+") as f:
f.write("")
os.chmod(str(tmpdir / "test2"), 0)
with patch("gns3server.modules.IOU.get_images_directory", return_value=str(tmpdir),):
response = http_hypervisor.post("/iou/vms/test2", body="TEST", raw=True)
assert response.status == 409
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import pytest
def test_udp_allocation(http_hypervisor, project):
response = http_hypervisor.post('/projects/{}/ports/udp'.format(project.id), {}, example=True)
assert response.status == 201
assert response.json == {'udp_port': 10000}
# Netfifaces is not available on Travis
@pytest.mark.skipif(os.environ.get("TRAVIS", False) is not False, reason="Not supported on Travis")
def test_interfaces(http_hypervisor):
response = http_hypervisor.get('/interfaces', example=True)
assert response.status == 200
assert isinstance(response.json, list)
@@ -0,0 +1,263 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
This test suite check /project endpoint
"""
import uuid
import os
import asyncio
import aiohttp
from unittest.mock import patch
from tests.utils import asyncio_patch
from gns3server.handlers.api.hypervisor.project_handler import ProjectHandler
from gns3server.modules.project_manager import ProjectManager
def test_create_project_with_path(http_hypervisor, tmpdir):
with patch("gns3server.modules.project.Project.is_local", return_value=True):
response = http_hypervisor.post("/projects", {"name": "test", "path": str(tmpdir)})
assert response.status == 201
assert response.json["path"] == str(tmpdir)
assert response.json["name"] == "test"
def test_create_project_without_dir(http_hypervisor):
query = {"name": "test"}
response = http_hypervisor.post("/projects", query, example=True)
assert response.status == 201
assert response.json["project_id"] is not None
assert response.json["temporary"] is False
assert response.json["name"] == "test"
def test_create_temporary_project(http_hypervisor):
query = {"name": "test", "temporary": True}
response = http_hypervisor.post("/projects", query)
assert response.status == 201
assert response.json["project_id"] is not None
assert response.json["temporary"] is True
assert response.json["name"] == "test"
def test_create_project_with_uuid(http_hypervisor):
query = {"name": "test", "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"}
response = http_hypervisor.post("/projects", query)
assert response.status == 201
assert response.json["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0f"
assert response.json["name"] == "test"
def test_show_project(http_hypervisor):
query = {"name": "test", "project_id": "00010203-0405-0607-0809-0a0b0c0d0e02", "temporary": False}
response = http_hypervisor.post("/projects", query)
assert response.status == 201
response = http_hypervisor.get("/projects/00010203-0405-0607-0809-0a0b0c0d0e02", example=True)
assert len(response.json.keys()) == 5
assert len(response.json["location"]) > 0
assert response.json["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e02"
assert response.json["temporary"] is False
assert response.json["name"] == "test"
def test_show_project_invalid_uuid(http_hypervisor):
response = http_hypervisor.get("/projects/00010203-0405-0607-0809-0a0b0c0d0e42")
assert response.status == 404
def test_list_projects(http_hypervisor):
ProjectManager.instance()._projects = {}
query = {"name": "test", "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"}
response = http_hypervisor.post("/projects", query)
assert response.status == 201
query = {"name": "test", "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0b"}
response = http_hypervisor.post("/projects", query)
assert response.status == 201
response = http_hypervisor.get("/projects", example=True)
assert response.status == 200
print(response.json)
assert len(response.json) == 2
assert response.json[0]["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0b" or response.json[1]["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0b"
def test_update_temporary_project(http_hypervisor):
query = {"name": "test", "temporary": True}
response = http_hypervisor.post("/projects", query)
assert response.status == 201
query = {"name": "test", "temporary": False}
response = http_hypervisor.put("/projects/{project_id}".format(project_id=response.json["project_id"]), query, example=True)
assert response.status == 200
assert response.json["temporary"] is False
def test_update_path_project_temporary(http_hypervisor, tmpdir):
os.makedirs(str(tmpdir / "a"))
os.makedirs(str(tmpdir / "b"))
with patch("gns3server.modules.project.Project.is_local", return_value=True):
response = http_hypervisor.post("/projects", {"name": "first_name", "path": str(tmpdir / "a"), "temporary": True})
assert response.status == 201
assert response.json["name"] == "first_name"
query = {"name": "second_name", "path": str(tmpdir / "b")}
response = http_hypervisor.put("/projects/{project_id}".format(project_id=response.json["project_id"]), query, example=True)
assert response.status == 200
assert response.json["path"] == str(tmpdir / "b")
assert response.json["name"] == "second_name"
assert not os.path.exists(str(tmpdir / "a"))
assert os.path.exists(str(tmpdir / "b"))
def test_update_path_project_non_temporary(http_hypervisor, tmpdir):
os.makedirs(str(tmpdir / "a"))
os.makedirs(str(tmpdir / "b"))
with patch("gns3server.modules.project.Project.is_local", return_value=True):
response = http_hypervisor.post("/projects", {"name": "first_name", "path": str(tmpdir / "a")})
assert response.status == 201
assert response.json["name"] == "first_name"
query = {"name": "second_name", "path": str(tmpdir / "b")}
response = http_hypervisor.put("/projects/{project_id}".format(project_id=response.json["project_id"]), query, example=True)
assert response.status == 200
assert response.json["path"] == str(tmpdir / "b")
assert response.json["name"] == "second_name"
assert os.path.exists(str(tmpdir / "a"))
assert os.path.exists(str(tmpdir / "b"))
def test_update_path_project_non_local(http_hypervisor, tmpdir):
with patch("gns3server.modules.project.Project.is_local", return_value=False):
response = http_hypervisor.post("/projects", {"name": "first_name"})
assert response.status == 201
query = {"name": "second_name", "path": str(tmpdir)}
response = http_hypervisor.put("/projects/{project_id}".format(project_id=response.json["project_id"]), query, example=True)
assert response.status == 403
def test_commit_project(http_hypervisor, project):
with asyncio_patch("gns3server.modules.project.Project.commit", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/commit".format(project_id=project.id), example=True)
assert response.status == 204
assert mock.called
def test_commit_project_invalid_uuid(http_hypervisor):
response = http_hypervisor.post("/projects/{project_id}/commit".format(project_id=uuid.uuid4()))
assert response.status == 404
def test_delete_project(http_hypervisor, project):
with asyncio_patch("gns3server.modules.project.Project.delete", return_value=True) as mock:
response = http_hypervisor.delete("/projects/{project_id}".format(project_id=project.id), example=True)
assert response.status == 204
assert mock.called
def test_delete_project_invalid_uuid(http_hypervisor):
response = http_hypervisor.delete("/projects/{project_id}".format(project_id=uuid.uuid4()))
assert response.status == 404
def test_close_project(http_hypervisor, project):
with asyncio_patch("gns3server.modules.project.Project.close", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/close".format(project_id=project.id), example=True)
assert response.status == 204
assert mock.called
def test_close_project_two_client_connected(http_hypervisor, project):
ProjectHandler._notifications_listening = {project.id: 2}
with asyncio_patch("gns3server.modules.project.Project.close", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/close".format(project_id=project.id), example=True)
assert response.status == 204
assert not mock.called
def test_close_project_invalid_uuid(http_hypervisor):
response = http_hypervisor.post("/projects/{project_id}/close".format(project_id=uuid.uuid4()))
assert response.status == 404
def test_notification(http_hypervisor, project, loop):
@asyncio.coroutine
def go(future):
response = yield from aiohttp.request("GET", http_hypervisor.get_url("/projects/{project_id}/notifications".format(project_id=project.id)))
response.body = yield from response.content.read(200)
project.emit("vm.created", {"a": "b"})
response.body += yield from response.content.read(50)
response.close()
future.set_result(response)
future = asyncio.Future()
asyncio.async(go(future))
response = loop.run_until_complete(future)
assert response.status == 200
assert b'"action": "ping"' in response.body
assert b'"cpu_usage_percent"' in response.body
assert b'{"action": "vm.created", "event": {"a": "b"}}\n' in response.body
def test_notification_invalid_id(http_hypervisor):
response = http_hypervisor.get("/projects/{project_id}/notifications".format(project_id=uuid.uuid4()))
assert response.status == 404
def test_list_files(http_hypervisor, project):
files = [
{
"path": "test.txt",
"md5sum": "ad0234829205b9033196ba818f7a872b"
},
{
"path": "vm-1/dynamips/test.bin",
"md5sum": "098f6bcd4621d373cade4e832627b4f6"
}
]
with asyncio_patch("gns3server.modules.project.Project.list_files", return_value=files) as mock:
response = http_hypervisor.get("/projects/{project_id}/files".format(project_id=project.id), example=True)
assert response.status == 200
assert response.json == files
def test_get_file(http_hypervisor, tmpdir):
with patch("gns3server.config.Config.get_section_config", return_value={"project_directory": str(tmpdir)}):
project = ProjectManager.instance().create_project()
with open(os.path.join(project.path, "hello"), "w+") as f:
f.write("world")
response = http_hypervisor.get("/projects/{project_id}/files/hello".format(project_id=project.id), raw=True)
assert response.status == 200
assert response.body == b"world"
response = http_hypervisor.get("/projects/{project_id}/files/false".format(project_id=project.id), raw=True)
assert response.status == 404
response = http_hypervisor.get("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
assert response.status == 403
+338
View File
@@ -0,0 +1,338 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
import os
import sys
import stat
from tests.utils import asyncio_patch
from unittest.mock import patch
from gns3server.config import Config
@pytest.fixture
def fake_qemu_bin():
if sys.platform.startswith("win"):
bin_path = os.path.join(os.environ["PATH"], "qemu-system-x86_64w.exe")
else:
bin_path = os.path.join(os.environ["PATH"], "qemu-system-x86_64")
with open(bin_path, "w+") as f:
f.write("1")
os.chmod(bin_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
return bin_path
@pytest.fixture
def fake_qemu_vm(tmpdir):
img_dir = Config.instance().get_section_config("Server").get("images_path")
img_dir = os.path.join(img_dir, "QEMU")
os.makedirs(img_dir)
bin_path = os.path.join(img_dir, "linux载.img")
with open(bin_path, "w+") as f:
f.write("1")
os.chmod(bin_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
return bin_path
@pytest.fixture
def base_params(tmpdir, fake_qemu_bin):
"""Return standard parameters"""
return {"name": "PC TEST 1", "qemu_path": fake_qemu_bin}
@pytest.fixture
def vm(http_hypervisor, project, base_params):
response = http_hypervisor.post("/projects/{project_id}/qemu/vms".format(project_id=project.id), base_params)
assert response.status == 201
return response.json
def test_qemu_create(http_hypervisor, project, base_params, fake_qemu_bin):
response = http_hypervisor.post("/projects/{project_id}/qemu/vms".format(project_id=project.id), base_params)
assert response.status == 201
assert response.route == "/projects/{project_id}/qemu/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["qemu_path"] == fake_qemu_bin
assert response.json["platform"] == "x86_64"
def test_qemu_create_platform(http_hypervisor, project, base_params, fake_qemu_bin):
base_params["qemu_path"] = None
base_params["platform"] = "x86_64"
response = http_hypervisor.post("/projects/{project_id}/qemu/vms".format(project_id=project.id), base_params)
assert response.status == 201
assert response.route == "/projects/{project_id}/qemu/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["qemu_path"] == fake_qemu_bin
assert response.json["platform"] == "x86_64"
def test_qemu_create_with_params(http_hypervisor, project, base_params, fake_qemu_vm):
params = base_params
params["ram"] = 1024
params["hda_disk_image"] = "linux载.img"
response = http_hypervisor.post("/projects/{project_id}/qemu/vms".format(project_id=project.id), params, example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/qemu/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["ram"] == 1024
assert response.json["hda_disk_image"] == "linux载.img"
assert response.json["hda_disk_image_md5sum"] == "c4ca4238a0b923820dcc509a6f75849b"
def test_qemu_get(http_hypervisor, project, vm):
response = http_hypervisor.get("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 200
assert response.route == "/projects/{project_id}/qemu/vms/{vm_id}"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["vm_directory"] == os.path.join(project.path, "project-files", "qemu", vm["vm_id"])
def test_qemu_start(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.qemu.qemu_vm.QemuVM.start", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/qemu/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 200
assert response.json["name"] == "PC TEST 1"
def test_qemu_stop(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.qemu.qemu_vm.QemuVM.stop", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/qemu/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_qemu_reload(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.qemu.qemu_vm.QemuVM.reload", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/qemu/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_qemu_suspend(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.qemu.qemu_vm.QemuVM.suspend", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/qemu/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_qemu_resume(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.qemu.qemu_vm.QemuVM.resume", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/qemu/vms/{vm_id}/resume".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_qemu_delete(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.qemu.Qemu.delete_vm", return_value=True) as mock:
response = http_hypervisor.delete("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_qemu_update(http_hypervisor, vm, tmpdir, free_console_port, project, fake_qemu_vm):
params = {
"name": "test",
"console": free_console_port,
"ram": 1024,
"hdb_disk_image": "linux.img"
}
response = http_hypervisor.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), params, example=True)
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
assert response.json["hdb_disk_image"] == "linux.img"
assert response.json["ram"] == 1024
def test_qemu_nio_create_udp(http_hypervisor, vm):
http_hypervisor.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"adapters": 2})
response = http_hypervisor.post("/projects/{project_id}/qemu/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/qemu/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp"
def test_qemu_nio_create_ethernet(http_hypervisor, vm):
http_hypervisor.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"adapters": 2})
response = http_hypervisor.post("/projects/{project_id}/qemu/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_generic_ethernet",
"ethernet_device": "eth0",
},
example=True)
assert response.status == 409
def test_qemu_delete_nio(http_hypervisor, vm):
http_hypervisor.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"adapters": 2})
http_hypervisor.post("/projects/{project_id}/qemu/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"})
response = http_hypervisor.delete("/projects/{project_id}/qemu/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 204
assert response.route == "/projects/{project_id}/qemu/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_qemu_list_binaries(http_hypervisor, vm):
ret = [{"path": "/tmp/1", "version": "2.2.0"},
{"path": "/tmp/2", "version": "2.1.0"}]
with asyncio_patch("gns3server.modules.qemu.Qemu.binary_list", return_value=ret) as mock:
response = http_hypervisor.get("/qemu/binaries".format(project_id=vm["project_id"]), example=True)
assert mock.called_with(None)
assert response.status == 200
assert response.json == ret
def test_qemu_list_binaries_filter(http_hypervisor, vm):
ret = [
{"path": "/tmp/x86_64", "version": "2.2.0"},
{"path": "/tmp/alpha", "version": "2.1.0"},
{"path": "/tmp/i386", "version": "2.1.0"}
]
with asyncio_patch("gns3server.modules.qemu.Qemu.binary_list", return_value=ret) as mock:
response = http_hypervisor.get("/qemu/binaries".format(project_id=vm["project_id"]), body={"archs": ["i386"]}, example=True)
assert response.status == 200
assert mock.called_with(["i386"])
assert response.json == ret
def test_vms(http_hypervisor, tmpdir, fake_qemu_vm):
response = http_hypervisor.get("/qemu/vms")
assert response.status == 200
assert response.json == [{"filename": "linux载.img", "path": "linux载.img"}]
def test_upload_vm(http_hypervisor, tmpdir):
with patch("gns3server.modules.Qemu.get_images_directory", return_value=str(tmpdir),):
response = http_hypervisor.post("/qemu/vms/test2", body="TEST", raw=True)
assert response.status == 204
with open(str(tmpdir / "test2")) as f:
assert f.read() == "TEST"
with open(str(tmpdir / "test2.md5sum")) as f:
checksum = f.read()
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
def test_upload_vm_ova(http_hypervisor, tmpdir):
with patch("gns3server.modules.Qemu.get_images_directory", return_value=str(tmpdir),):
response = http_hypervisor.post("/qemu/vms/test2.ova/test2.vmdk", body="TEST", raw=True)
assert response.status == 204
with open(str(tmpdir / "test2.ova" / "test2.vmdk")) as f:
assert f.read() == "TEST"
with open(str(tmpdir / "test2.ova" / "test2.vmdk.md5sum")) as f:
checksum = f.read()
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
def test_upload_vm_forbiden_location(http_hypervisor, tmpdir):
with patch("gns3server.modules.Qemu.get_images_directory", return_value=str(tmpdir),):
response = http_hypervisor.post("/qemu/vms/../../test2", body="TEST", raw=True)
assert response.status == 403
def test_upload_vm_permission_denied(http_hypervisor, tmpdir):
with open(str(tmpdir / "test2"), "w+") as f:
f.write("")
os.chmod(str(tmpdir / "test2"), 0)
with patch("gns3server.modules.Qemu.get_images_directory", return_value=str(tmpdir),):
response = http_hypervisor.post("/qemu/vms/test2", body="TEST", raw=True)
assert response.status == 409
def test_create_img_relative(http_hypervisor):
body = {
"qemu_img": "/tmp/qemu-img",
"path": "hda.qcow2",
"format": "qcow2",
"preallocation": "metadata",
"cluster_size": 64,
"refcount_bits": 12,
"lazy_refcounts": "off",
"size": 100
}
with asyncio_patch("gns3server.modules.Qemu.create_disk"):
response = http_hypervisor.post("/qemu/img", body=body, example=True)
assert response.status == 201
def test_create_img_absolute_non_local(http_hypervisor):
config = Config.instance()
config.set("Server", "local", "false")
body = {
"qemu_img": "/tmp/qemu-img",
"path": "/tmp/hda.qcow2",
"format": "qcow2",
"preallocation": "metadata",
"cluster_size": 64,
"refcount_bits": 12,
"lazy_refcounts": "off",
"size": 100
}
with asyncio_patch("gns3server.modules.Qemu.create_disk"):
response = http_hypervisor.post("/qemu/img", body=body, example=True)
assert response.status == 403
def test_create_img_absolute_local(http_hypervisor):
config = Config.instance()
config.set("Server", "local", "true")
body = {
"qemu_img": "/tmp/qemu-img",
"path": "/tmp/hda.qcow2",
"format": "qcow2",
"preallocation": "metadata",
"cluster_size": 64,
"refcount_bits": 12,
"lazy_refcounts": "off",
"size": 100
}
with asyncio_patch("gns3server.modules.Qemu.create_disk"):
response = http_hypervisor.post("/qemu/img", body=body, example=True)
assert response.status == 201
def test_capabilities(http_hypervisor):
with asyncio_patch("gns3server.modules.Qemu.get_kvm_archs", return_value=["x86_64"]):
response = http_hypervisor.get("/qemu/capabilities", example=True)
assert response.json["kvm"] == ["x86_64"]
@@ -0,0 +1,133 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
from tests.utils import asyncio_patch
from unittest.mock import patch
@pytest.yield_fixture(scope="function")
def vm(http_hypervisor, project, monkeypatch):
vboxmanage_path = "/fake/VboxManage"
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms".format(project_id=project.id), {"name": "VMTEST",
"vmname": "VMTEST",
"linked_clone": False})
assert mock.called
assert response.status == 201
with patch("gns3server.modules.virtualbox.VirtualBox.find_vboxmanage", return_value=vboxmanage_path):
yield response.json
def test_vbox_create(http_hypervisor, project):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True):
response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms".format(project_id=project.id), {"name": "VM1",
"vmname": "VM1",
"linked_clone": False},
example=True)
assert response.status == 201
assert response.json["name"] == "VM1"
assert response.json["project_id"] == project.id
def test_vbox_get(http_hypervisor, project, vm):
response = http_hypervisor.get("/projects/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 200
assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}"
assert response.json["name"] == "VMTEST"
assert response.json["project_id"] == project.id
def test_vbox_start(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.check_hw_virtualization", return_value=True) as mock:
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.start", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_vbox_stop(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.stop", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_vbox_suspend(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.suspend", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_vbox_resume(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.resume", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms/{vm_id}/resume".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_vbox_reload(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.reload", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_vbox_nio_create_udp(http_hypervisor, vm):
with asyncio_patch('gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
response = http_hypervisor.post("/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"],
vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
example=True)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status == 201
assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp"
def test_vbox_delete_nio(http_hypervisor, vm):
with asyncio_patch('gns3server.modules.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
response = http_hypervisor.delete("/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status == 204
assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_vbox_update(http_hypervisor, vm, free_console_port):
response = http_hypervisor.put("/projects/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test",
"console": free_console_port},
example=True)
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
+138
View File
@@ -0,0 +1,138 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
import sys
import os
from tests.utils import asyncio_patch
from unittest.mock import patch
@pytest.fixture(scope="function")
def vm(http_hypervisor, project):
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1"})
assert response.status == 201
return response.json
def test_vpcs_create(http_hypervisor, project):
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1"}, example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
def test_vpcs_get(http_hypervisor, project, vm):
response = http_hypervisor.get("/projects/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 200
assert response.route == "/projects/{project_id}/vpcs/vms/{vm_id}"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["startup_script_path"] is None
assert response.json["status"] == "stopped"
def test_vpcs_create_startup_script(http_hypervisor, project):
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1", "startup_script": "ip 192.168.1.2\necho TEST"})
assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["startup_script"] == os.linesep.join(["ip 192.168.1.2", "echo TEST"])
assert response.json["startup_script_path"] == "startup.vpc"
def test_vpcs_create_port(http_hypervisor, project, free_console_port):
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1", "console": free_console_port})
assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms"
assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id
assert response.json["console"] == free_console_port
def test_vpcs_nio_create_udp(http_hypervisor, vm):
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"},
example=True)
assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp"
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
def test_vpcs_nio_create_tap(http_hypervisor, vm, ethernet_device):
with patch("gns3server.modules.base_manager.BaseManager.has_privileged_access", return_value=True):
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_tap",
"tap_device": ethernet_device})
assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_tap"
def test_vpcs_delete_nio(http_hypervisor, vm):
http_hypervisor.post("/projects/{project_id}/vpcs/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"})
response = http_hypervisor.delete("/projects/{project_id}/vpcs/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert response.status == 204
assert response.route == "/projects/{project_id}/vpcs/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_vpcs_start(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.vpcs.vpcs_vm.VPCSVM.start", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 200
assert response.json["name"] == "PC TEST 1"
def test_vpcs_stop(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.vpcs.vpcs_vm.VPCSVM.stop", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_vpcs_reload(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.vpcs.vpcs_vm.VPCSVM.reload", return_value=True) as mock:
response = http_hypervisor.post("/projects/{project_id}/vpcs/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_vpcs_delete(http_hypervisor, vm):
with asyncio_patch("gns3server.modules.vpcs.VPCS.delete_vm", return_value=True) as mock:
response = http_hypervisor.delete("/projects/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True)
assert mock.called
assert response.status == 204
def test_vpcs_update(http_hypervisor, vm, tmpdir, free_console_port):
response = http_hypervisor.put("/projects/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test",
"console": free_console_port,
"startup_script": "ip 192.168.1.1"},
example=True)
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
assert response.json["startup_script"] == "ip 192.168.1.1"