def test_get_kvm_archs_kvm_ok(loop): with patch("os.path.exists", return_value=True): archs = loop.run_until_complete(asyncio.async(Qemu.get_kvm_archs())) if platform.machine() == 'x86_64': assert archs == ['x86_64', 'i386'] else: assert archs == [platform.machine()] with patch("os.path.exists", return_value=False): archs = loop.run_until_complete(asyncio.async(Qemu.get_kvm_archs())) assert archs == []
def test_get_kvm_archs_kvm_ok(loop): with patch("os.path.exists", return_value=True): archs = loop.run_until_complete(asyncio. async (Qemu.get_kvm_archs())) if platform.machine() == 'x86_64': assert archs == ['x86_64', 'i386'] else: assert archs == [platform.machine()] with patch("os.path.exists", return_value=False): archs = loop.run_until_complete(asyncio. async (Qemu.get_kvm_archs())) assert archs == []
async def stop_capture(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) await vm.stop_capture(adapter_number) response.set_status(204)
async def stream_pcap_file(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) nio = vm.get_nio(adapter_number) await qemu_manager.stream_pcap_file(nio, vm.project.id, request, response)
def test_create_image_abs_path(loop, tmpdir, fake_qemu_img_binary): options = { "format": "qcow2", "preallocation": "metadata", "cluster_size": 64, "refcount_bits": 12, "lazy_refcounts": "off", "size": 100 } with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(fake_qemu_img_binary, str(tmpdir / "hda.qcow2"), options))) args, kwargs = process.call_args assert args == ( fake_qemu_img_binary, "create", "-f", "qcow2", "-o", "cluster_size=64", "-o", "lazy_refcounts=off", "-o", "preallocation=metadata", "-o", "refcount_bits=12", str(tmpdir / "hda.qcow2"), "100M" )
def test_stop(loop, vm, running_subprocess_mock): process = running_subprocess_mock # Wait process kill success future = asyncio.Future() future.set_result(True) process.wait.return_value = future vm.manager.get_qemu_version = AsyncioMagicMock(return_value="3.1.0") with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"): with asyncio_patch("asyncio.create_subprocess_exec", return_value=process): nio = Qemu.instance().create_nio({ "type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1" }) loop.run_until_complete( asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio))) loop.run_until_complete(asyncio.ensure_future(vm.start())) assert vm.is_running() loop.run_until_complete(asyncio.ensure_future(vm.stop())) assert vm.is_running() is False process.terminate.assert_called_with()
async def delete_nio(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) await vm.adapter_remove_nio_binding(adapter_number) response.set_status(204)
async def qemu(loop, port_manager): Qemu._instance = None Qemu._init_config_disk = MagicMock() # do not create the config.img image qemu = Qemu.instance() qemu.port_manager = port_manager return qemu
async def suspend(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) await vm.suspend() response.set_status(204)
def resume(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) yield from vm.resume() response.set_status(204)
async def start_capture(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) await vm.start_capture(adapter_number, pcap_file_path) response.json({"pcap_file_path": pcap_file_path})
async def resize_disk(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) await vm.resize_disk(request.json["drive_name"], request.json["extend"]) response.set_status(201)
def duplicate(request, response): new_node = yield from Qemu.instance().duplicate_node( request.match_info["node_id"], request.json["destination_node_id"] ) response.set_status(201) response.json(new_node)
def test_get_qemu_version(loop): with asyncio_patch("gns3server.compute.qemu.subprocess_check_output", return_value="QEMU emulator version 2.2.0, Copyright (c) 2003-2008 Fabrice Bellard") as mock: version = loop.run_until_complete(asyncio.async(Qemu.get_qemu_version("/tmp/qemu-test"))) if sys.platform.startswith("win"): assert version == "" else: assert version == "2.2.0"
def update_nio(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])] if "filters" in request.json and nio: nio.filters = request.json["filters"] yield from vm.adapter_update_nio_binding(int(request.match_info["adapter_number"]), nio) response.set_status(201) response.json(request.json)
def start(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) if sys.platform.startswith("linux") and qemu_manager.config.get_section_config("Qemu").getboolean("enable_kvm", True) and "-no-kvm" not in vm.options: pm = ProjectManager.instance() if pm.check_hardware_virtualization(vm) is False: raise aiohttp.web.HTTPConflict(text="Cannot start VM with KVM enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox") yield from vm.start() response.json(vm)
def test_add_nio_binding_udp(vm, loop): nio = Qemu.instance().create_nio({ "type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1" }) loop.run_until_complete(asyncio. async (vm.adapter_add_nio_binding(0, nio))) assert nio.lport == 4242
def update(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: setattr(vm, name, value) vm.updated() response.json(vm)
def test_port_remove_nio_binding(vm, loop): nio = Qemu.instance().create_nio({ "type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1" }) loop.run_until_complete(asyncio. async (vm.adapter_add_nio_binding(0, nio))) loop.run_until_complete(asyncio. async (vm.adapter_remove_nio_binding(0))) assert vm._ethernet_adapters[0].ports[0] is None
async def download_image(request, response): filename = request.match_info["filename"] qemu_manager = Qemu.instance() image_path = qemu_manager.get_abs_image_path(filename) # Raise error if user try to escape if filename[0] == ".": raise aiohttp.web.HTTPForbidden() await response.stream_file(image_path)
def test_add_nio_binding_ethernet(vm, loop, ethernet_device): with patch( "gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True): nio = Qemu.instance().create_nio({ "type": "nio_ethernet", "ethernet_device": ethernet_device }) loop.run_until_complete(asyncio. async (vm.adapter_add_nio_binding( 0, nio))) assert nio.ethernet_device == ethernet_device
async def create_nio(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) nio_type = request.json["type"] if nio_type not in ("nio_udp"): raise aiohttp.web.HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) nio = qemu_manager.create_nio(request.json) await vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio) response.set_status(201) response.json(nio)
def test_create_image_relative_path(loop, tmpdir, fake_qemu_img_binary): options = {"format": "raw", "size": 100} with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: with patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)): loop.run_until_complete(asyncio. async ( Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options))) args, kwargs = process.call_args assert args == (fake_qemu_img_binary, "create", "-f", "raw", str(tmpdir / "hda.qcow2"), "100M")
async def test_port_remove_nio_binding(vm): nio = Qemu.instance().create_nio({ "type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {} }) await vm.adapter_add_nio_binding(0, nio) await vm.adapter_remove_nio_binding(0) assert vm._ethernet_adapters[0].ports[0] is None
def create_img(request, response): qemu_img = request.json.pop("qemu_img") path = request.json.pop("path") if os.path.isabs(path): config = Config.instance() if config.get_section_config("Server").getboolean("local", False) is False: response.set_status(403) return yield from Qemu.instance().create_disk(qemu_img, path, request.json) response.set_status(201)
async def test_add_nio_binding_udp(vm): nio = Qemu.instance().create_nio({ "type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {} }) assert nio.lport == 4242 await vm.adapter_add_nio_binding(0, nio) assert nio.lport == 4242
def test_create_image_exist(loop, tmpdir, fake_qemu_img_binary): open(str(tmpdir / "hda.qcow2"), "w+").close() options = { "format": "raw", "size": 100 } with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: with patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)): with pytest.raises(QemuError): loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options))) assert not process.called
def update(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) # update the console first to avoid issue if updating console type vm.console = request.json.pop("console", vm.console) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: setattr(vm, name, value) vm.updated() response.json(vm)
def update_nio(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])] if "filters" in request.json and nio: nio.filters = request.json["filters"] yield from vm.adapter_update_nio_binding( int(request.match_info["adapter_number"]), nio) response.set_status(201) response.json(request.json)
async def update_nio(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) nio = vm.get_nio(adapter_number) if "filters" in request.json: nio.filters = request.json["filters"] if "suspend" in request.json: nio.suspend = request.json["suspend"] await vm.adapter_update_nio_binding(adapter_number, nio) response.set_status(201) response.json(request.json)
def test_get_qemu_version(loop): with asyncio_patch( "gns3server.compute.qemu.subprocess_check_output", return_value= "QEMU emulator version 2.2.0, Copyright (c) 2003-2008 Fabrice Bellard" ) as mock: version = loop.run_until_complete(asyncio. async ( Qemu.get_qemu_version("/tmp/qemu-test"))) if sys.platform.startswith("win"): assert version == "" else: assert version == "2.2.0"
def test_create_image_exist(loop, tmpdir, fake_qemu_img_binary): open(str(tmpdir / "hda.qcow2"), "w+").close() options = {"format": "raw", "size": 100} with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: with patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)): with pytest.raises(QemuError): loop.run_until_complete(asyncio. async ( Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options))) assert not process.called
def test_binary_list(loop): files_to_create = ["qemu-system-x86", "qemu-system-x42", "qemu-kvm", "hello", "qemu-system-x86_64-spice"] for file_to_create in files_to_create: path = os.path.join(os.environ["PATH"], file_to_create) with open(path, "w+") as f: f.write("1") os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) with asyncio_patch("gns3server.compute.qemu.subprocess_check_output", return_value="QEMU emulator version 2.2.0, Copyright (c) 2003-2008 Fabrice Bellard") as mock: if sys.platform.startswith("win"): version = "" else: version = "2.2.0" qemus = loop.run_until_complete(asyncio.async(Qemu.binary_list())) assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x42"), "version": version} in qemus assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86_64-spice"), "version": version} not in qemus qemus = loop.run_until_complete(asyncio.async(Qemu.binary_list(["x86"]))) assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} not in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x42"), "version": version} not in qemus assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus qemus = loop.run_until_complete(asyncio.async(Qemu.binary_list(["x86", "x42"]))) assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} not in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x42"), "version": version} in qemus assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus
async def update(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) # update the console first to avoid issue if updating console type vm.console = request.json.pop("console", vm.console) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: setattr(vm, name, value) if name == "cdrom_image": # let the guest know about the new cdrom image await vm.update_cdrom_image() vm.updated() response.json(vm)
async def start(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) hardware_accel = qemu_manager.config.get_section_config("Qemu").getboolean("enable_hardware_acceleration", True) if sys.platform.startswith("linux"): # the enable_kvm option was used before version 2.0 and has priority enable_kvm = qemu_manager.config.get_section_config("Qemu").getboolean("enable_kvm") if enable_kvm is not None: hardware_accel = enable_kvm if hardware_accel and "-no-kvm" not in vm.options and "-no-hax" not in vm.options: pm = ProjectManager.instance() if pm.check_hardware_virtualization(vm) is False: raise aiohttp.web.HTTPConflict(text="Cannot start VM with hardware acceleration (KVM/HAX) enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox") await vm.start() response.json(vm)
def test_img_binary_list(loop): files_to_create = [ "qemu-img", "qemu-io", "qemu-system-x86", "qemu-system-x42", "qemu-kvm", "hello" ] for file_to_create in files_to_create: path = os.path.join(os.environ["PATH"], file_to_create) with open(path, "w+") as f: f.write("1") os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) with asyncio_patch( "gns3server.compute.qemu.subprocess_check_output", return_value= "qemu-img version 2.2.0, Copyright (c) 2004-2008 Fabrice Bellard" ) as mock: qemus = loop.run_until_complete(asyncio. async ( Qemu.img_binary_list())) version = "2.2.0" assert { "path": os.path.join(os.environ["PATH"], "qemu-img"), "version": version } in qemus assert { "path": os.path.join(os.environ["PATH"], "qemu-io"), "version": version } not in qemus assert { "path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version } not in qemus assert { "path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version } not in qemus assert { "path": os.path.join(os.environ["PATH"], "qemu-system-x42"), "version": version } not in qemus assert { "path": os.path.join(os.environ["PATH"], "hello"), "version": version } not in qemus
def test_stop(loop, vm, running_subprocess_mock): process = running_subprocess_mock # Wait process kill success future = asyncio.Future() future.set_result(True) process.wait.return_value = future with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"): with asyncio_patch("asyncio.create_subprocess_exec", return_value=process): nio = Qemu.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"}) vm.adapter_add_nio_binding(0, nio) loop.run_until_complete(asyncio.async(vm.start())) assert vm.is_running() loop.run_until_complete(asyncio.async(vm.stop())) assert vm.is_running() is False process.terminate.assert_called_with()
def start(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) if sys.platform.startswith( "linux") and qemu_manager.config.get_section_config( "Qemu").getboolean("enable_kvm", True) and "-no-kvm" not in vm.options: pm = ProjectManager.instance() if pm.check_hardware_virtualization(vm) is False: raise aiohttp.web.HTTPConflict( text= "Cannot start VM with KVM enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox" ) yield from vm.start() response.json(vm)
def test_create_image_with_not_supported_characters_by_filesystem( loop, tmpdir, fake_qemu_img_binary): open(str(tmpdir / "hda.qcow2"), "w+").close() options = {"format": "raw", "size": 100} # patching os.makedirs is necessary as it depends on already mocked os.path.exists with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process, \ patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)), \ patch("os.path.exists", side_effect=UnicodeEncodeError('error', u"", 1, 2, 'Emulated Unicode Err')),\ patch("os.makedirs"): with pytest.raises(QemuError): loop.run_until_complete(asyncio. async ( Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options))) assert not process.called
def test_create_image_relative_path(loop, tmpdir, fake_qemu_img_binary): options = { "format": "raw", "size": 100 } with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: with patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)): loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options))) args, kwargs = process.call_args assert args == ( fake_qemu_img_binary, "create", "-f", "raw", str(tmpdir / "hda.qcow2"), "100M" )
async def create(request, response): qemu = Qemu.instance() vm = await qemu.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.pop("node_id", None), linked_clone=request.json.get("linked_clone", True), qemu_path=request.json.pop("qemu_path", None), console=request.json.pop("console", None), console_type=request.json.pop("console_type", "telnet"), platform=request.json.pop("platform", None)) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: setattr(vm, name, value) response.set_status(201) response.json(vm)
def test_create_image_with_not_supported_characters_by_filesystem(loop, tmpdir, fake_qemu_img_binary): open(str(tmpdir / "hda.qcow2"), "w+").close() options = { "format": "raw", "size": 100 } # patching os.makedirs is necessary as it depends on already mocked os.path.exists with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process, \ patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)), \ patch("os.path.exists", side_effect=UnicodeEncodeError('error', u"", 1, 2, 'Emulated Unicode Err')),\ patch("os.makedirs"): with pytest.raises(QemuError): loop.run_until_complete(asyncio.async(Qemu.instance().create_disk( fake_qemu_img_binary, "hda.qcow2", options))) assert not process.called
def test_img_binary_list(loop): files_to_create = ["qemu-img", "qemu-io", "qemu-system-x86", "qemu-system-x42", "qemu-kvm", "hello"] for file_to_create in files_to_create: path = os.path.join(os.environ["PATH"], file_to_create) with open(path, "w+") as f: f.write("1") os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) with asyncio_patch("gns3server.compute.qemu.subprocess_check_output", return_value="qemu-img version 2.2.0, Copyright (c) 2004-2008 Fabrice Bellard") as mock: qemus = loop.run_until_complete(asyncio.async(Qemu.img_binary_list())) version = "2.2.0" assert {"path": os.path.join(os.environ["PATH"], "qemu-img"), "version": version} in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-io"), "version": version} not in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} not in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} not in qemus assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x42"), "version": version} not in qemus assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus
async def upload_image(request, response): qemu_manager = Qemu.instance() await qemu_manager.write_image(request.match_info["filename"], request.content) response.set_status(204)
async def resume(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) await vm.resume() response.set_status(204)
async def list_qemu_images(request, response): qemu_manager = Qemu.instance() images = await qemu_manager.list_images() response.set_status(200) response.json(images)
def show(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) response.json(vm)
def qemu(port_manager): Qemu._instance = None qemu = Qemu.instance() qemu.port_manager = port_manager return qemu