diff --git a/gns3server/compute/base_manager.py b/gns3server/compute/base_manager.py index be69b1d6..6574b8ca 100644 --- a/gns3server/compute/base_manager.py +++ b/gns3server/compute/base_manager.py @@ -39,7 +39,7 @@ from .nios.nio_udp import NIOUDP from .nios.nio_tap import NIOTAP from .nios.nio_ethernet import NIOEthernet from ..utils.images import md5sum, remove_checksum -from .node_error import NodeError +from .error import NodeError, ImageMissingError class BaseManager: @@ -432,18 +432,27 @@ class BaseManager: path = self._recursive_search_file_in_directory(directory, orig_path) if path: return force_unix_path(path) - # Not found we return the default directory + + # Not found we try the default directory s = os.path.split(orig_path) - return force_unix_path(os.path.join(self.get_images_directory(), *s)) + path = force_unix_path(os.path.join(self.get_images_directory(), *s)) + if os.path.exists(path): + return path + raise ImageMissingError(path) # For non local server we disallow using absolute path outside image directory if server_config.get("local", False) is True: - return force_unix_path(path) + path = force_unix_path(path) + if os.path.exists(path): + return path + raise ImageMissingError(path) path = force_unix_path(path) for directory in self.images_directories(): if os.path.commonprefix([directory, path]) == directory: - return path + if os.path.exists(path): + return path + raise ImageMissingError(path) raise NodeError("{} is not allowed on this remote server. Please use only a filename in {}.".format(path, self.get_images_directory())) def _recursive_search_file_in_directory(self, directory, searched_file): diff --git a/gns3server/compute/base_node.py b/gns3server/compute/base_node.py index 52d0681f..f1355135 100644 --- a/gns3server/compute/base_node.py +++ b/gns3server/compute/base_node.py @@ -28,7 +28,7 @@ import platform from ..utils.asyncio import wait_run_in_executor from ..ubridge.hypervisor import Hypervisor from ..ubridge.ubridge_error import UbridgeError -from .node_error import NodeError +from .error import NodeError log = logging.getLogger(__name__) diff --git a/gns3server/compute/builtin/builtin_node_factory.py b/gns3server/compute/builtin/builtin_node_factory.py index 41d0a91c..91960559 100644 --- a/gns3server/compute/builtin/builtin_node_factory.py +++ b/gns3server/compute/builtin/builtin_node_factory.py @@ -16,7 +16,7 @@ # along with this program. If not, see . -from ..node_error import NodeError +from ..error import NodeError from .nodes.cloud import Cloud from .nodes.ethernet_hub import EthernetHub from .nodes.ethernet_switch import EthernetSwitch diff --git a/gns3server/compute/builtin/nodes/cloud.py b/gns3server/compute/builtin/nodes/cloud.py index 20f8a9ac..23c554ed 100644 --- a/gns3server/compute/builtin/nodes/cloud.py +++ b/gns3server/compute/builtin/nodes/cloud.py @@ -18,7 +18,7 @@ import sys import asyncio -from ...node_error import NodeError +from ...error import NodeError from ...base_node import BaseNode from ...nios.nio_udp import NIOUDP @@ -181,7 +181,6 @@ class Cloud(BaseNode): yield from self._ubridge_send('bridge start_capture {name} "{pcap_file}"'.format(name=bridge_name, pcap_file=nio.pcap_output_file)) - yield from self._ubridge_send('bridge start {name}'.format(name=bridge_name)) @asyncio.coroutine @@ -269,7 +268,6 @@ class Cloud(BaseNode): id=self.id, port_number=port_number)) - @asyncio.coroutine def stop_capture(self, port_number): """ @@ -291,5 +289,5 @@ class Cloud(BaseNode): yield from self._ubridge_send("bridge stop_capture {name}".format(name=bridge_name)) log.info("Cloud'{name}' [{id}]: stopping packet capture on port {port_number}".format(name=self.name, - id=self.id, - port_number=port_number)) + id=self.id, + port_number=port_number)) diff --git a/gns3server/compute/builtin/nodes/ethernet_hub.py b/gns3server/compute/builtin/nodes/ethernet_hub.py index 5c167d52..32025034 100644 --- a/gns3server/compute/builtin/nodes/ethernet_hub.py +++ b/gns3server/compute/builtin/nodes/ethernet_hub.py @@ -17,7 +17,7 @@ import asyncio -from ...node_error import NodeError +from ...error import NodeError from ...base_node import BaseNode import logging diff --git a/gns3server/compute/builtin/nodes/ethernet_switch.py b/gns3server/compute/builtin/nodes/ethernet_switch.py index bb7a2fac..372e105b 100644 --- a/gns3server/compute/builtin/nodes/ethernet_switch.py +++ b/gns3server/compute/builtin/nodes/ethernet_switch.py @@ -17,7 +17,7 @@ import asyncio -from ...node_error import NodeError +from ...error import NodeError from ...base_node import BaseNode import logging diff --git a/gns3server/compute/docker/docker_error.py b/gns3server/compute/docker/docker_error.py index 5a1031f0..5d2b9b1d 100644 --- a/gns3server/compute/docker/docker_error.py +++ b/gns3server/compute/docker/docker_error.py @@ -19,7 +19,7 @@ Custom exceptions for the Docker module. """ -from ..node_error import NodeError +from ..error import NodeError class DockerError(NodeError): diff --git a/gns3server/compute/dynamips/dynamips_error.py b/gns3server/compute/dynamips/dynamips_error.py index 3d58e7f9..ff2fac00 100644 --- a/gns3server/compute/dynamips/dynamips_error.py +++ b/gns3server/compute/dynamips/dynamips_error.py @@ -19,7 +19,7 @@ Custom exceptions for the Dynamips module. """ -from ..node_error import NodeError +from ..error import NodeError class DynamipsError(NodeError): diff --git a/gns3server/compute/node_error.py b/gns3server/compute/error.py similarity index 85% rename from gns3server/compute/node_error.py rename to gns3server/compute/error.py index e95d3242..3666205c 100644 --- a/gns3server/compute/node_error.py +++ b/gns3server/compute/error.py @@ -19,7 +19,6 @@ class NodeError(Exception): def __init__(self, message, original_exception=None): - super().__init__(message) if isinstance(message, Exception): message = str(message) @@ -27,9 +26,16 @@ class NodeError(Exception): self._original_exception = original_exception def __repr__(self): - return self._message def __str__(self): - return self._message + + +class ImageMissingError(Exception): + """ + Raised when an image is missing + """ + + def __init__(self, image): + super().__init__("The image {} is missing".format(image)) diff --git a/gns3server/compute/iou/iou_error.py b/gns3server/compute/iou/iou_error.py index 57f4656b..33cf157a 100644 --- a/gns3server/compute/iou/iou_error.py +++ b/gns3server/compute/iou/iou_error.py @@ -19,7 +19,7 @@ Custom exceptions for the IOU module. """ -from ..node_error import NodeError +from ..error import NodeError class IOUError(NodeError): diff --git a/gns3server/compute/iou/iou_vm.py b/gns3server/compute/iou/iou_vm.py index a5192052..2f9d29d5 100644 --- a/gns3server/compute/iou/iou_vm.py +++ b/gns3server/compute/iou/iou_vm.py @@ -91,6 +91,9 @@ class IOUVM(BaseNode): self._ram = 256 # Megabytes self._l1_keepalives = False # used to overcome the always-up Ethernet interfaces (not supported by all IOSes). + def _config(self): + return self._manager.config.get_section_config("IOU") + @asyncio.coroutine def close(self): """ @@ -129,15 +132,6 @@ class IOUVM(BaseNode): self._path = self.manager.get_abs_image_path(path) - # In 1.2 users uploaded images to the images roots - # after the migration their images are inside images/IOU - # but old topologies use old path - if "IOU" not in self._path: - location, filename = os.path.split(self._path) - fix_path = os.path.join(location, "IOU", filename) - if os.path.isfile(fix_path): - self._path = fix_path - @property def use_default_iou_values(self): """ @@ -232,7 +226,7 @@ class IOUVM(BaseNode): :returns: path to IOUYAP """ - path = self._manager.config.get_section_config("IOU").get("iouyap_path", "iouyap") + path = self._config().get("iouyap_path", "iouyap") if path == "iouyap": path = shutil.which("iouyap") return path @@ -245,7 +239,7 @@ class IOUVM(BaseNode): :returns: path to IOURC """ - iourc_path = self._manager.config.get_section_config("IOU").get("iourc_path") + iourc_path = self._config().get("iourc_path") if not iourc_path: # look for the iourc file in the user home dir. path = os.path.join(os.path.expanduser("~/"), ".iourc") @@ -380,7 +374,7 @@ class IOUVM(BaseNode): Checks for a valid IOU key in the iourc file (paranoid mode). """ - license_check = self._manager.config.get_section_config("IOU").getboolean("license_check", True) + license_check = self._config().getboolean("license_check", True) if license_check is False: return diff --git a/gns3server/compute/qemu/qemu_error.py b/gns3server/compute/qemu/qemu_error.py index 8f6f3202..afabc921 100644 --- a/gns3server/compute/qemu/qemu_error.py +++ b/gns3server/compute/qemu/qemu_error.py @@ -19,7 +19,7 @@ Custom exceptions for the Qemu module. """ -from ..node_error import NodeError +from ..error import NodeError class QemuError(NodeError): diff --git a/gns3server/compute/virtualbox/virtualbox_error.py b/gns3server/compute/virtualbox/virtualbox_error.py index c6bf61d1..d950f09d 100644 --- a/gns3server/compute/virtualbox/virtualbox_error.py +++ b/gns3server/compute/virtualbox/virtualbox_error.py @@ -19,7 +19,7 @@ Custom exceptions for the VirtualBox module. """ -from ..node_error import NodeError +from ..error import NodeError class VirtualBoxError(NodeError): diff --git a/gns3server/compute/vmware/vmware_error.py b/gns3server/compute/vmware/vmware_error.py index 71fd84b5..4c390a31 100644 --- a/gns3server/compute/vmware/vmware_error.py +++ b/gns3server/compute/vmware/vmware_error.py @@ -19,7 +19,7 @@ Custom exceptions for the VMware module. """ -from ..node_error import NodeError +from ..error import NodeError class VMwareError(NodeError): diff --git a/gns3server/compute/vpcs/vpcs_error.py b/gns3server/compute/vpcs/vpcs_error.py index da064c71..5a721681 100644 --- a/gns3server/compute/vpcs/vpcs_error.py +++ b/gns3server/compute/vpcs/vpcs_error.py @@ -19,7 +19,7 @@ Custom exceptions for the VPCS module. """ -from ..node_error import NodeError +from ..error import NodeError class VPCSError(NodeError): diff --git a/gns3server/web/route.py b/gns3server/web/route.py index 570a6f4b..3819cc5e 100644 --- a/gns3server/web/route.py +++ b/gns3server/web/route.py @@ -25,7 +25,7 @@ import traceback log = logging.getLogger(__name__) -from ..compute.node_error import NodeError +from ..compute.error import NodeError from ..controller.controller_error import ControllerError from ..ubridge.ubridge_error import UbridgeError from .response import Response @@ -197,11 +197,11 @@ class Route(object): response = Response(request=request, route=route) response.set_status(409) response.json({"message": str(e), "status": 409}) - except (NodeError, UbridgeError) as e: + except (NodeError, UbridgeError, ImageMissingError) as e: log.error("Node error detected: {type}".format(type=type(e)), exc_info=1) response = Response(request=request, route=route) response.set_status(409) - response.json({"message": str(e), "status": 409}) + response.json({"message": str(e), "status": 409, "exception": str(e.__class__)}) except asyncio.futures.CancelledError as e: log.error("Request canceled") response = Response(request=request, route=route) diff --git a/tests/compute/iou/test_iou_vm.py b/tests/compute/iou/test_iou_vm.py index 3a694cb4..4bd7f6fe 100644 --- a/tests/compute/iou/test_iou_vm.py +++ b/tests/compute/iou/test_iou_vm.py @@ -72,11 +72,10 @@ def iourc_file(tmpdir): @pytest.fixture -def fake_iou_bin(tmpdir): +def fake_iou_bin(images_dir): """Create a fake IOU image on disk""" - os.makedirs(str(tmpdir / "IOU"), exist_ok=True) - path = str(tmpdir / "IOU" / "iou.bin") + path = os.path.join(images_dir, "iou.bin") with open(path, "w+") as f: f.write('\x7fELF\x01\x01\x01') os.chmod(path, stat.S_IREAD | stat.S_IEXEC) @@ -97,11 +96,11 @@ def test_vm_startup_config_content(project, manager): assert vm.id == "00010203-0405-0607-0808-0a0b0c0d0e0f" -@patch("gns3server.config.Config.get_section_config", return_value={"iouyap_path": "/bin/test_fake"}) +@patch("gns3server.compute.iou.iou_vm.IOUVM._config", return_value={"iouyap_path": "/bin/test_fake"}) def test_vm_invalid_iouyap_path(project, manager, loop, fake_iou_bin): with pytest.raises(IOUError): vm = IOUVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0e", project, manager) - vm.path = "iou.bin" + vm.path = fake_iou_bin loop.run_until_complete(asyncio.async(vm.start())) @@ -213,20 +212,8 @@ def test_path(vm, fake_iou_bin): assert vm.path == fake_iou_bin -def test_path_12_location(vm, fake_iou_bin): - - # In 1.2 users uploaded images to the images roots - # after the migration their images are inside images/IOU - # but old topologies use old path - with patch("gns3server.config.Config.get_section_config", return_value={"local": True}): - vm.path = fake_iou_bin.replace("/IOU", "") - assert vm.path == fake_iou_bin - - def test_path_relative(vm, fake_iou_bin, tmpdir): - config = Config.instance() - config.set("Server", "images_path", str(tmpdir)) vm.path = "iou.bin" assert vm.path == fake_iou_bin @@ -235,9 +222,6 @@ def test_path_invalid_bin(vm, tmpdir): with patch("gns3server.config.Config.get_section_config", return_value={"local": True}): path = str(tmpdir / "test.bin") - with pytest.raises(IOUError): - vm.path = path - vm._check_requirements() with open(path, "w+") as f: f.write("BUG") diff --git a/tests/compute/qemu/test_qemu_vm.py b/tests/compute/qemu/test_qemu_vm.py index 0fa08a99..f396f08a 100644 --- a/tests/compute/qemu/test_qemu_vm.py +++ b/tests/compute/qemu/test_qemu_vm.py @@ -506,52 +506,52 @@ def test_build_command_with_invalid_options(vm, loop, fake_qemu_binary): cmd = loop.run_until_complete(asyncio.async(vm._build_command())) -def test_hda_disk_image(vm, tmpdir): +def test_hda_disk_image(vm, images_dir): - vm.manager.config.set("Server", "images_path", str(tmpdir)) - - vm.hda_disk_image = str(tmpdir / "test1") - assert vm.hda_disk_image == force_unix_path(str(tmpdir / "test1")) + open(os.path.join(images_dir, "test1"), "w+").close() + vm.hda_disk_image = os.path.join(images_dir, "test1") + assert vm.hda_disk_image == force_unix_path(os.path.join(images_dir, "test1")) + open(os.path.join(images_dir, "QEMU", "test2"), "w+").close() vm.hda_disk_image = "test2" - assert vm.hda_disk_image == force_unix_path(str(tmpdir / "QEMU" / "test2")) + assert vm.hda_disk_image == force_unix_path(os.path.join(images_dir, "QEMU", "test2")) -def test_hda_disk_image_ova(vm, tmpdir): - - vm.manager.config.set("Server", "images_path", str(tmpdir)) +def test_hda_disk_image_ova(vm, images_dir): + os.makedirs(os.path.join(images_dir, "QEMU", "test.ovf")) + open(os.path.join(images_dir, "QEMU", "test.ovf", "test.vmdk"), "w+").close() vm.hda_disk_image = "test.ovf/test.vmdk" - assert vm.hda_disk_image == force_unix_path(str(tmpdir / "QEMU" / "test.ovf" / "test.vmdk")) + assert vm.hda_disk_image == force_unix_path(os.path.join(images_dir, "QEMU", "test.ovf", "test.vmdk")) -def test_hdb_disk_image(vm, tmpdir): +def test_hdb_disk_image(vm, images_dir): - vm.manager.config.set("Server", "images_path", str(tmpdir)) - - vm.hdb_disk_image = str(tmpdir / "test") - assert vm.hdb_disk_image == force_unix_path(str(tmpdir / "test")) - vm.hdb_disk_image = "test" - assert vm.hdb_disk_image == force_unix_path(str(tmpdir / "QEMU" / "test")) + open(os.path.join(images_dir, "test1"), "w+").close() + vm.hdb_disk_image = os.path.join(images_dir, "test1") + assert vm.hdb_disk_image == force_unix_path(os.path.join(images_dir, "test1")) + open(os.path.join(images_dir, "QEMU", "test2"), "w+").close() + vm.hdb_disk_image = "test2" + assert vm.hdb_disk_image == force_unix_path(os.path.join(images_dir, "QEMU", "test2")) -def test_hdc_disk_image(vm, tmpdir): +def test_hdc_disk_image(vm, images_dir): - vm.manager.config.set("Server", "images_path", str(tmpdir)) - - vm.hdc_disk_image = str(tmpdir / "test") - assert vm.hdc_disk_image == force_unix_path(str(tmpdir / "test")) - vm.hdc_disk_image = "test" - assert vm.hdc_disk_image == force_unix_path(str(tmpdir / "QEMU" / "test")) + open(os.path.join(images_dir, "test1"), "w+").close() + vm.hdc_disk_image = os.path.join(images_dir, "test1") + assert vm.hdc_disk_image == force_unix_path(os.path.join(images_dir, "test1")) + open(os.path.join(images_dir, "QEMU", "test2"), "w+").close() + vm.hdc_disk_image = "test2" + assert vm.hdc_disk_image == force_unix_path(os.path.join(images_dir, "QEMU", "test2")) -def test_hdd_disk_image(vm, tmpdir): +def test_hdd_disk_image(vm, images_dir): - vm.manager.config.set("Server", "images_path", str(tmpdir)) - - vm.hdd_disk_image = str(tmpdir / "test") - assert vm.hdd_disk_image == force_unix_path(str(tmpdir / "test")) - vm.hdd_disk_image = "test" - assert vm.hdd_disk_image == force_unix_path(str(tmpdir / "QEMU" / "test")) + open(os.path.join(images_dir, "test1"), "w+").close() + vm.hdd_disk_image = os.path.join(images_dir, "test1") + assert vm.hdd_disk_image == force_unix_path(os.path.join(images_dir, "test1")) + open(os.path.join(images_dir, "QEMU", "test2"), "w+").close() + vm.hdd_disk_image = "test2" + assert vm.hdd_disk_image == force_unix_path(os.path.join(images_dir, "QEMU", "test2")) def test_initrd(vm, tmpdir): diff --git a/tests/compute/test_base_node.py b/tests/compute/test_base_node.py index a5365955..9aa344e9 100644 --- a/tests/compute/test_base_node.py +++ b/tests/compute/test_base_node.py @@ -26,7 +26,7 @@ from unittest.mock import patch, MagicMock from gns3server.compute.vpcs.vpcs_vm import VPCSVM from gns3server.compute.docker.docker_vm import DockerVM from gns3server.compute.vpcs.vpcs_error import VPCSError -from gns3server.compute.node_error import NodeError +from gns3server.compute.error import NodeError from gns3server.compute.vpcs import VPCS diff --git a/tests/compute/test_manager.py b/tests/compute/test_manager.py index 85b6fe03..44267900 100644 --- a/tests/compute/test_manager.py +++ b/tests/compute/test_manager.py @@ -23,7 +23,7 @@ from unittest.mock import patch from gns3server.compute.vpcs import VPCS from gns3server.compute.qemu import Qemu -from gns3server.compute.node_error import NodeError +from gns3server.compute.error import NodeError, ImageMissingError from gns3server.utils import force_unix_path @@ -165,8 +165,8 @@ def test_get_abs_image_additional_image_paths(qemu, tmpdir): # Absolute path assert qemu.get_abs_image_path(str(path2)) == path2 - # If not found return the default path - assert qemu.get_abs_image_path("test4.bin") == os.path.join(qemu.get_images_directory(), "test4.bin") + with pytest.raises(ImageMissingError): + qemu.get_abs_image_path("test4.bin") def test_get_abs_image_recursive(qemu, tmpdir): diff --git a/tests/conftest.py b/tests/conftest.py index 7c0de0bd..d9703cee 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -230,6 +230,18 @@ def run_around_tests(monkeypatch, port_manager, controller, config): pass +@pytest.fixture +def images_dir(config): + """ + Get the location of images + """ + path = config.get_section_config("Server").get("images_path") + os.makedirs(path, exist_ok=True) + os.makedirs(os.path.join(path, "QEMU")) + os.makedirs(os.path.join(path, "IOU")) + return path + + @pytest.yield_fixture def darwin_platform(): """ diff --git a/tests/handlers/api/compute/test_iou.py b/tests/handlers/api/compute/test_iou.py index b24b4fbe..5d3a0631 100644 --- a/tests/handlers/api/compute/test_iou.py +++ b/tests/handlers/api/compute/test_iou.py @@ -29,10 +29,10 @@ pytestmark = pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supp @pytest.fixture -def fake_iou_bin(tmpdir): +def fake_iou_bin(images_dir): """Create a fake IOU image on disk""" - path = str(tmpdir / "iou.bin") + path = os.path.join(images_dir, "IOU", "iou.bin") with open(path, "w+") as f: f.write('\x7fELF\x01\x01\x01') os.chmod(path, stat.S_IREAD | stat.S_IEXEC) @@ -222,7 +222,7 @@ def test_iou_nio_create_udp(http_compute, vm): def test_iou_nio_create_ethernet(http_compute, vm, ethernet_device): response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_ethernet", "ethernet_device": ethernet_device, - }, + }, example=True) assert response.status == 201 assert response.route == "/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" @@ -233,7 +233,7 @@ def test_iou_nio_create_ethernet(http_compute, vm, ethernet_device): def test_iou_nio_create_ethernet_different_port(http_compute, vm, ethernet_device): response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/3/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_ethernet", "ethernet_device": ethernet_device, - }, + }, example=False) assert response.status == 201 assert response.route == "/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" @@ -328,10 +328,9 @@ def test_get_configs_with_startup_config_file(http_compute, project, vm): assert response.json["startup_config_content"] == "TEST" -def test_images(http_compute, tmpdir, fake_iou_bin): +def test_images(http_compute, fake_iou_bin): - with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir)): - response = http_compute.get("/iou/images", example=True) + response = http_compute.get("/iou/images", example=True) assert response.status == 200 assert response.json == [{"filename": "iou.bin", "path": "iou.bin"}] diff --git a/tests/handlers/api/compute/test_qemu.py b/tests/handlers/api/compute/test_qemu.py index 07ac8087..2f00c2b2 100644 --- a/tests/handlers/api/compute/test_qemu.py +++ b/tests/handlers/api/compute/test_qemu.py @@ -38,11 +38,9 @@ def fake_qemu_bin(): @pytest.fixture -def fake_qemu_vm(tmpdir): +def fake_qemu_vm(images_dir): - img_dir = Config.instance().get_section_config("Server").get("images_path") - img_dir = os.path.join(img_dir, "QEMU") - os.makedirs(img_dir) + img_dir = os.path.join(images_dir, "QEMU") bin_path = os.path.join(img_dir, "linux载.img") with open(bin_path, "w+") as f: f.write("1") @@ -154,18 +152,18 @@ def test_qemu_delete(http_compute, vm): assert response.status == 204 -def test_qemu_update(http_compute, vm, tmpdir, free_console_port, project, fake_qemu_vm): +def test_qemu_update(http_compute, vm, free_console_port, project, fake_qemu_vm): params = { "name": "test", "console": free_console_port, "ram": 1024, - "hdb_disk_image": "linux.img" + "hdb_disk_image": "linux载.img" } response = http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_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["hdb_disk_image"] == "linux载.img" assert response.json["ram"] == 1024