diff --git a/gns3server/handlers/api/iou_handler.py b/gns3server/handlers/api/iou_handler.py index cd90fb2a..5769a992 100644 --- a/gns3server/handlers/api/iou_handler.py +++ b/gns3server/handlers/api/iou_handler.py @@ -16,7 +16,7 @@ # along with this program. If not, see . import os - +from aiohttp.web import HTTPConflict from ...web.route import Route from ...modules.port_manager import PortManager @@ -255,7 +255,8 @@ class IOUHandler: status_codes={ 200: "Capture started", 400: "Invalid request", - 404: "Instance doesn't exist" + 404: "Instance doesn't exist", + 409: "VM not started" }, description="Start a packet capture on a IOU VM instance", input=IOU_CAPTURE_SCHEMA) @@ -266,8 +267,11 @@ class IOUHandler: adapter_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) + + if not vm.is_running(): + raise HTTPConflict(text="You can't capture the traffic on a non started VM") yield from vm.start_capture(adapter_number, port_number, pcap_file_path, request.json["data_link_type"]) - response.json({"pcap_file_path": pcap_file_path}) + response.json({"pcap_file_path": str(pcap_file_path)}) @Route.post( r"/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture", @@ -280,13 +284,18 @@ class IOUHandler: status_codes={ 204: "Capture stopped", 400: "Invalid request", - 404: "Instance doesn't exist" + 404: "Instance doesn't exist", + 409: "VM not started" }, description="Stop a packet capture on a IOU VM instance") def stop_capture(request, response): iou_manager = IOU.instance() vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) + + if not vm.is_running(): + raise HTTPConflict(text="You can't capture the traffic on a non started VM") + adapter_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) yield from vm.stop_capture(adapter_number, port_number) diff --git a/tests/handlers/api/test_iou.py b/tests/handlers/api/test_iou.py index 5221f0eb..8aa059f5 100644 --- a/tests/handlers/api/test_iou.py +++ b/tests/handlers/api/test_iou.py @@ -18,8 +18,9 @@ import pytest import os import stat + from tests.utils import asyncio_patch -from unittest.mock import patch +from unittest.mock import patch, MagicMock, PropertyMock @pytest.fixture @@ -207,26 +208,53 @@ def test_iou_delete_nio(server, vm): assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" -def test_iou_start_capture(server, vm, tmpdir): +def test_iou_start_capture(server, vm, tmpdir, project): - with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.start_capture", return_value=True) as mock: + 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 = server.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) + params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"} + response = server.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 mock.called - assert response.status == 200 - assert "test.pcap" in response.json["pcap_file_path"] + assert response.status == 200 + + assert start_capture.called + assert "test.pcap" in response.json["pcap_file_path"] -def test_iou_stop_capture(server, vm): +def test_iou_start_capture_not_started(server, vm, tmpdir): - with asyncio_patch("gns3server.modules.iou.iou_vm.IOUVM.stop_capture", return_value=True) as mock: + 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: - response = server.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) + params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"} + response = server.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 mock.called - assert response.status == 204 + assert not start_capture.called + assert response.status == 409 + + +def test_iou_stop_capture(server, 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 = server.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(server, 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 = server.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_initial_config_without_config_file(server, vm):