From 71fcf855b40f777bfc2b7297567c4dfc166f7774 Mon Sep 17 00:00:00 2001 From: grossmj Date: Sat, 17 Nov 2018 15:37:20 +0700 Subject: [PATCH] Add tests for all appliance types. --- gns3server/schemas/appliance.py | 181 +++-- gns3server/web/route.py | 6 +- .../handlers/api/controller/test_appliance.py | 746 +++++++++++++++++- 3 files changed, 851 insertions(+), 82 deletions(-) diff --git a/gns3server/schemas/appliance.py b/gns3server/schemas/appliance.py index 25e69bdc..764245e8 100644 --- a/gns3server/schemas/appliance.py +++ b/gns3server/schemas/appliance.py @@ -169,12 +169,6 @@ C7200_DYNAMIPS_APPLIANCE_PROPERTIES = { "description": "Platform type", "enum": ["c7200"] }, - # "chassis": { - # "description": "Chassis type", - # "type": ["string", "null"], - # "maxLength": 0, - # "default": None - # }, "ram": { "description": "Amount of RAM in MB", "type": "integer", @@ -209,12 +203,6 @@ C3745_DYNAMIPS_APPLIANCE_PROPERTIES = { "description": "Platform type", "enum": ["c3745"] }, - # "chassis": { - # "description": "Chassis type", - # "type": ["string", "null"], - # "maxLength": 0, - # "default": None - # }, "ram": { "description": "Amount of RAM in MB", "type": "integer", @@ -246,12 +234,6 @@ C3725_DYNAMIPS_APPLIANCE_PROPERTIES = { "description": "Platform type", "enum": ["c3725"] }, - # "chassis": { - # "description": "Chassis type", - # "type": ["string", "null"], - # "maxLength": 0, - # "default": None - # }, "ram": { "description": "Amount of RAM in MB", "type": "integer", @@ -320,12 +302,6 @@ C2691_DYNAMIPS_APPLIANCE_PROPERTIES = { "description": "Platform type", "enum": ["c2691"] }, - # "chassis": { - # "description": "Chassis type", - # "type": ["string", "null"], - # "maxLength": 0, - # "default": None - # }, "ram": { "description": "Amount of RAM in MB", "type": "integer", @@ -461,7 +437,7 @@ IOU_APPLIANCE_PROPERTIES = { "startup_config": { "description": "Startup-config of IOU", "type": "string", - "default": "iou_l2_base_startup-config.txt" + "default": "iou_l3_base_startup-config.txt" }, "private_config": { "description": "Private-config of IOU", @@ -504,13 +480,11 @@ DOCKER_APPLIANCE_PROPERTIES = { "start_command": { "description": "Docker CMD entry", "type": "string", - "minLength": 1, "default": "" }, "environment": { "description": "Docker environment variables", "type": "string", - "minLength": 1, "default": "" }, "console_type": { @@ -545,7 +519,6 @@ DOCKER_APPLIANCE_PROPERTIES = { "extra_hosts": { "description": "Docker extra hosts (added to /etc/hosts)", "type": "string", - "minLength": 1, "default": "", }, "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA @@ -563,13 +536,11 @@ QEMU_APPLIANCE_PROPERTIES = { "usage": { "description": "How to use the Qemu VM", "type": "string", - "minLength": 1, "default": "" }, "qemu_path": { "description": "Path to QEMU", "type": "string", - "minLength": 1, "default": "" }, "platform": { @@ -604,13 +575,14 @@ QEMU_APPLIANCE_PROPERTIES = { "adapter_type": { "description": "QEMU adapter type", "type": "string", - "minLength": 1, + "enum": ["e1000", "i82550", "i82551", "i82557a", "i82557b", "i82557c", "i82558a","i82558b", "i82559a", + "i82559b", "i82559c", "i82559er", "i82562", "i82801", "ne2k_pci", "pcnet", "rtl8139", "virtio", + "virtio-net-pci", "vmxnet3"], "default": "e1000" }, "mac_address": { "description": "QEMU MAC address", "type": "string", - "minLength": 1, "anyOf": [ {"pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"}, {"pattern": "^$"} @@ -620,13 +592,11 @@ QEMU_APPLIANCE_PROPERTIES = { "first_port_name": { "description": "Optional name of the first networking port example: eth0", "type": "string", - "minLength": 1, "default": "" }, "port_name_format": { "description": "Optional formatting of the networking port example: eth{0}", "type": "string", - "minLength": 1, "default": "Ethernet{0}" }, "port_segment_size": { @@ -652,79 +622,66 @@ QEMU_APPLIANCE_PROPERTIES = { "hda_disk_image": { "description": "QEMU hda disk image path", "type": "string", - "minLength": 1, "default": "" }, "hda_disk_interface": { "description": "QEMU hda interface", - "type": "string", - "minLength": 1, + "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], "default": "ide" }, "hdb_disk_image": { "description": "QEMU hdb disk image path", "type": "string", - "minLength": 1, "default": "" }, "hdb_disk_interface": { "description": "QEMU hdb interface", - "type": "string", - "minLength": 1, + "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], "default": "ide" }, "hdc_disk_image": { "description": "QEMU hdc disk image path", "type": "string", - "minLength": 1, "default": "" }, "hdc_disk_interface": { "description": "QEMU hdc interface", - "type": "string", - "minLength": 1, + "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], "default": "ide" }, "hdd_disk_image": { "description": "QEMU hdd disk image path", "type": "string", - "minLength": 1, "default": "" }, "hdd_disk_interface": { "description": "QEMU hdd interface", - "type": "string", - "minLength": 1, + "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], "default": "ide" }, "cdrom_image": { "description": "QEMU cdrom image path", "type": "string", - "minLength": 1, "default": "" }, "initrd": { "description": "QEMU initrd path", "type": "string", - "minLength": 1, "default": "" }, "kernel_image": { "description": "QEMU kernel image path", "type": "string", - "minLength": 1, "default": "" }, "bios_image": { "description": "QEMU bios image path", "type": "string", - "minLength": 1, "default": "" }, "kernel_command_line": { "description": "QEMU kernel command line", "type": "string", - "minLength": 1, "default": "" }, "legacy_networking": { @@ -752,7 +709,6 @@ QEMU_APPLIANCE_PROPERTIES = { "options": { "description": "Additional QEMU options", "type": "string", - "minLength": 1, "default": "" }, "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA @@ -788,13 +744,11 @@ VMWARE_APPLIANCE_PROPERTIES = { "first_port_name": { "description": "Optional name of the first networking port example: eth0", "type": "string", - "minLength": 1, "default": "" }, "port_name_format": { "description": "Optional formatting of the networking port example: eth{0}", "type": "string", - "minLength": 1, "default": "Ethernet{0}" }, "port_segment_size": { @@ -811,8 +765,7 @@ VMWARE_APPLIANCE_PROPERTIES = { }, "adapter_type": { "description": "VMware adapter type", - "type": "string", - "minLength": 1, + "enum": ["default", "e1000", "e1000e", "flexible", "vlance", "vmxnet", "vmxnet2", "vmxnet3"], "default": "e1000" }, "use_any_adapter": { @@ -883,20 +836,22 @@ VIRTUALBOX_APPLIANCE_PROPERTIES = { }, "adapter_type": { "description": "VirtualBox adapter type", - "type": "string", - "minLength": 1, + "enum": ["PCnet-PCI II (Am79C970A)", + "PCNet-FAST III (Am79C973)", + "Intel PRO/1000 MT Desktop (82540EM)", + "Intel PRO/1000 T Server (82543GC)", + "Intel PRO/1000 MT Server (82545EM)", + "Paravirtualized Network (virtio-net)"], "default": "Intel PRO/1000 MT Desktop (82540EM)" }, "first_port_name": { "description": "Optional name of the first networking port example: eth0", "type": "string", - "minLength": 1, "default": "" }, "port_name_format": { "description": "Optional formatting of the networking port example: eth{0}", "type": "string", - "minLength": 1, "default": "Ethernet{0}" }, "port_segment_size": { @@ -991,6 +946,55 @@ ETHERNET_SWITCH_APPLIANCE_PROPERTIES = { }, "ports_mapping": { "type": "array", + "default": [{"ethertype": "", + "name": "Ethernet0", + "vlan": 1, + "type": "access", + "port_number": 0 + }, + {"ethertype": "", + "name": "Ethernet1", + "vlan": 1, + "type": "access", + "port_number": 1 + }, + {"ethertype": "", + "name": "Ethernet2", + "vlan": 1, + "type": "access", + "port_number": 2 + }, + {"ethertype": "", + "name": "Ethernet3", + "vlan": 1, + "type": "access", + "port_number": 3 + }, + {"ethertype": "", + "name": "Ethernet4", + "vlan": 1, + "type": "access", + "port_number": 4 + }, + {"ethertype": "", + "name": "Ethernet5", + "vlan": 1, + "type": "access", + "port_number": 5 + }, + {"ethertype": "", + "name": "Ethernet6", + "vlan": 1, + "type": "access", + "port_number": 6 + }, + {"ethertype": "", + "name": "Ethernet7", + "vlan": 1, + "type": "access", + "port_number": 7 + } + ], "items": [ {"type": "object", "oneOf": [ @@ -1044,27 +1048,46 @@ ETHERNET_HUB_APPLIANCE_PROPERTIES = { }, "ports_mapping": { "type": "array", + "default": [{"port_number": 0, + "name": "Ethernet0" + }, + {"port_number": 1, + "name": "Ethernet1" + }, + {"port_number": 2, + "name": "Ethernet2" + }, + {"port_number": 3, + "name": "Ethernet3" + }, + {"port_number": 4, + "name": "Ethernet4" + }, + {"port_number": 5, + "name": "Ethernet5" + }, + {"port_number": 6, + "name": "Ethernet6" + }, + {"port_number": 7, + "name": "Ethernet7" + } + ], "items": [ {"type": "object", - "oneOf": [ - { - "description": "Ethernet port", - "properties": { - "name": { - "description": "Port name", - "type": "string", - "minLength": 1 - }, - "port_number": { - "description": "Port number", - "type": "integer", - "minimum": 0 - }, - }, - "required": ["name", "port_number"], - "additionalProperties": False - }, - ]}, + "oneOf": [{"description": "Ethernet port", + "properties": {"name": {"description": "Port name", + "type": "string", + "minLength": 1}, + "port_number": { + "description": "Port number", + "type": "integer", + "minimum": 0} + }, + "required": ["name", "port_number"], + "additionalProperties": False} + ], + } ] } } diff --git a/gns3server/web/route.py b/gns3server/web/route.py index 22e66f52..764286c3 100644 --- a/gns3server/web/route.py +++ b/gns3server/web/route.py @@ -86,8 +86,10 @@ async def parse_request(request, input_schema, raw, set_input_schema_defaults=Fa try: validator.validate(request.json) except jsonschema.ValidationError as e: - best_match = jsonschema.exceptions.best_match(validator.iter_errors(request.json)) - message = "JSON schema error with API request '{}': {} (best matched error: {})".format(request.path_qs, e.message, best_match.message) + message = "JSON schema error with API request '{}': {}".format(request.path_qs, e.message) + if "is not valid under any of the given schemas" not in message: + best_match = jsonschema.exceptions.best_match(validator.iter_errors(request.json)) + message += " (best matched error: {})".format(best_match.message) log.error(message) log.debug("Input schema: {}".format(json.dumps(input_schema))) raise aiohttp.web.HTTPBadRequest(text=message) diff --git a/tests/handlers/api/controller/test_appliance.py b/tests/handlers/api/controller/test_appliance.py index 05835fd3..41ead4bc 100644 --- a/tests/handlers/api/controller/test_appliance.py +++ b/tests/handlers/api/controller/test_appliance.py @@ -113,6 +113,24 @@ def test_appliance_create_with_id(http_controller, controller): assert len(controller.appliances) == 1 +def test_appliance_create_wrong_type(http_controller, controller): + + params = {"appliance_id": str(uuid.uuid4()), + "base_script_file": "vpcs_base_config.txt", + "category": "guest", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "PC{0}", + "name": "VPCS_TEST", + "compute_id": "local", + "symbol": ":/symbols/vpcs_guest.svg", + "appliance_type": "invalid_appliance_type"} + + response = http_controller.post("/appliances", params) + assert response.status == 400 + assert len(controller.appliances) == 0 + + def test_appliance_get(http_controller, controller): appliance_id = str(uuid.uuid4()) @@ -192,6 +210,733 @@ def test_appliance_delete(http_controller, controller): assert len(controller.appliances) == 0 +def test_c7200_dynamips_appliance_create(http_controller): + + params = {"name": "Cisco c7200 appliance", + "platform": "c7200", + "compute_id": "local", + "image": "c7200-adventerprisek9-mz.124-24.T5.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "dynamips", + "auto_delete_disks": False, + "builtin": False, + "category": "router", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "R{0}", + "disk0": 0, + "disk1": 0, + "exec_area": 64, + "idlemax": 500, + "idlepc": "", + "idlesleep": 30, + "image": "c7200-adventerprisek9-mz.124-24.T5.image", + "mac_addr": "", + "midplane": "vxr", + "mmap": True, + "name": "Cisco c7200 appliance", + "npe": "npe-400", + "nvram": 512, + "platform": "c7200", + "private_config": "", + "ram": 512, + "sparsemem": True, + "startup_config": "ios_base_startup-config.txt", + "symbol": ":/symbols/router.svg", + "system_id": "FTX0945W0MY"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_c3745_dynamips_appliance_create(http_controller): + + params = {"name": "Cisco c3745 appliance", + "platform": "c3745", + "compute_id": "local", + "image": "c3745-adventerprisek9-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "dynamips", + "auto_delete_disks": False, + "builtin": False, + "category": "router", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "R{0}", + "disk0": 0, + "disk1": 0, + "exec_area": 64, + "idlemax": 500, + "idlepc": "", + "idlesleep": 30, + "image": "c3745-adventerprisek9-mz.124-25d.image", + "mac_addr": "", + "mmap": True, + "name": "Cisco c3745 appliance", + "iomem": 5, + "nvram": 256, + "platform": "c3745", + "private_config": "", + "ram": 256, + "sparsemem": True, + "startup_config": "ios_base_startup-config.txt", + "symbol": ":/symbols/router.svg", + "system_id": "FTX0945W0MY"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_c3725_dynamips_appliance_create(http_controller): + + params = {"name": "Cisco c3725 appliance", + "platform": "c3725", + "compute_id": "local", + "image": "c3725-adventerprisek9-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "dynamips", + "auto_delete_disks": False, + "builtin": False, + "category": "router", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "R{0}", + "disk0": 0, + "disk1": 0, + "exec_area": 64, + "idlemax": 500, + "idlepc": "", + "idlesleep": 30, + "image": "c3725-adventerprisek9-mz.124-25d.image", + "mac_addr": "", + "mmap": True, + "name": "Cisco c3725 appliance", + "iomem": 5, + "nvram": 256, + "platform": "c3725", + "private_config": "", + "ram": 128, + "sparsemem": True, + "startup_config": "ios_base_startup-config.txt", + "symbol": ":/symbols/router.svg", + "system_id": "FTX0945W0MY"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_c3600_dynamips_appliance_create(http_controller): + + params = {"name": "Cisco c3600 appliance", + "platform": "c3600", + "chassis": "3660", + "compute_id": "local", + "image": "c3660-a3jk9s-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "dynamips", + "auto_delete_disks": False, + "builtin": False, + "category": "router", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "R{0}", + "disk0": 0, + "disk1": 0, + "exec_area": 64, + "idlemax": 500, + "idlepc": "", + "idlesleep": 30, + "image": "c3660-a3jk9s-mz.124-25d.image", + "mac_addr": "", + "mmap": True, + "name": "Cisco c3600 appliance", + "iomem": 5, + "nvram": 128, + "platform": "c3600", + "chassis": "3660", + "private_config": "", + "ram": 192, + "sparsemem": True, + "startup_config": "ios_base_startup-config.txt", + "symbol": ":/symbols/router.svg", + "system_id": "FTX0945W0MY"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_c3600_dynamips_appliance_create_wrong_chassis(http_controller): + + params = {"name": "Cisco c3600 appliance", + "platform": "c3600", + "chassis": "3650", + "compute_id": "local", + "image": "c3660-a3jk9s-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params) + assert response.status == 400 + assert "is not valid under any of the given schemas" in response.json["message"] + + +def test_c2691_dynamips_appliance_create(http_controller): + + params = {"name": "Cisco c2691 appliance", + "platform": "c2691", + "compute_id": "local", + "image": "c2691-adventerprisek9-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "dynamips", + "auto_delete_disks": False, + "builtin": False, + "category": "router", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "R{0}", + "disk0": 0, + "disk1": 0, + "exec_area": 64, + "idlemax": 500, + "idlepc": "", + "idlesleep": 30, + "image": "c2691-adventerprisek9-mz.124-25d.image", + "mac_addr": "", + "mmap": True, + "name": "Cisco c2691 appliance", + "iomem": 5, + "nvram": 256, + "platform": "c2691", + "private_config": "", + "ram": 192, + "sparsemem": True, + "startup_config": "ios_base_startup-config.txt", + "symbol": ":/symbols/router.svg", + "system_id": "FTX0945W0MY"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_c2600_dynamips_appliance_create(http_controller): + + params = {"name": "Cisco c2600 appliance", + "platform": "c2600", + "chassis": "2651XM", + "compute_id": "local", + "image": "c2600-adventerprisek9-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "dynamips", + "auto_delete_disks": False, + "builtin": False, + "category": "router", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "R{0}", + "disk0": 0, + "disk1": 0, + "exec_area": 64, + "idlemax": 500, + "idlepc": "", + "idlesleep": 30, + "image": "c2600-adventerprisek9-mz.124-25d.image", + "mac_addr": "", + "mmap": True, + "name": "Cisco c2600 appliance", + "iomem": 15, + "nvram": 128, + "platform": "c2600", + "chassis": "2651XM", + "private_config": "", + "ram": 160, + "sparsemem": True, + "startup_config": "ios_base_startup-config.txt", + "symbol": ":/symbols/router.svg", + "system_id": "FTX0945W0MY"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_c2600_dynamips_appliance_create_wrong_chassis(http_controller): + + params = {"name": "Cisco c2600 appliance", + "platform": "c2600", + "chassis": "2660XM", + "compute_id": "local", + "image": "c2600-adventerprisek9-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params) + assert response.status == 400 + assert "is not valid under any of the given schemas" in response.json["message"] + + +def test_c1700_dynamips_appliance_create(http_controller): + + params = {"name": "Cisco c1700 appliance", + "platform": "c1700", + "chassis": "1760", + "compute_id": "local", + "image": "c1700-adventerprisek9-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "dynamips", + "auto_delete_disks": False, + "builtin": False, + "category": "router", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "R{0}", + "disk0": 0, + "disk1": 0, + "exec_area": 64, + "idlemax": 500, + "idlepc": "", + "idlesleep": 30, + "image": "c1700-adventerprisek9-mz.124-25d.image", + "mac_addr": "", + "mmap": True, + "name": "Cisco c1700 appliance", + "iomem": 15, + "nvram": 128, + "platform": "c1700", + "chassis": "1760", + "private_config": "", + "ram": 160, + "sparsemem": False, + "startup_config": "ios_base_startup-config.txt", + "symbol": ":/symbols/router.svg", + "system_id": "FTX0945W0MY"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_c1700_dynamips_appliance_create_wrong_chassis(http_controller): + + params = {"name": "Cisco c1700 appliance", + "platform": "c1700", + "chassis": "1770", + "compute_id": "local", + "image": "c1700-adventerprisek9-mz.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params) + assert response.status == 400 + assert "is not valid under any of the given schemas" in response.json["message"] + + +def test_dynamips_appliance_create_wrong_platform(http_controller): + + params = {"name": "Cisco c3900 appliance", + "platform": "c3900", + "compute_id": "local", + "image": "c3900-test.124-25d.image", + "appliance_type": "dynamips"} + + response = http_controller.post("/appliances", params) + assert response.status == 400 + assert "is not valid under any of the given schemas" in response.json["message"] + + +def test_iou_appliance_create(http_controller): + + params = {"name": "IOU appliance", + "compute_id": "local", + "path": "/path/to/i86bi_linux-ipbase-ms-12.4.bin", + "appliance_type": "iou"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "iou", + "builtin": False, + "category": "router", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "IOU{0}", + "ethernet_adapters": 2, + "name": "IOU appliance", + "nvram": 128, + "path": "/path/to/i86bi_linux-ipbase-ms-12.4.bin", + "private_config": "", + "ram": 256, + "serial_adapters": 2, + "startup_config": "iou_l3_base_startup-config.txt", + "symbol": ":/symbols/multilayer_switch.svg", + "use_default_iou_values": True} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_docker_appliance_create(http_controller): + + params = {"name": "Docker appliance", + "compute_id": "local", + "image": "gns3/endhost:latest", + "appliance_type": "docker"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"adapters": 1, + "appliance_type": "docker", + "builtin": False, + "category": "guest", + "compute_id": "local", + "console_auto_start": False, + "console_http_path": "/", + "console_http_port": 80, + "console_resolution": "1024x768", + "console_type": "telnet", + "default_name_format": "{name}-{0}", + "environment": "", + "extra_hosts": "", + "image": "gns3/endhost:latest", + "name": "Docker appliance", + "start_command": "", + "symbol": ":/symbols/docker_guest.svg"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_qemu_appliance_create(http_controller): + + params = {"name": "Qemu appliance", + "compute_id": "local", + "platform": "i386", + "hda_disk_image": "IOSvL2-15.2.4.0.55E.qcow2", + "ram": 512, + "appliance_type": "qemu"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"adapter_type": "e1000", + "adapters": 1, + "appliance_type": "qemu", + "bios_image": "", + "boot_priority": "c", + "builtin": False, + "category": "guest", + "cdrom_image": "", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "cpu_throttling": 0, + "cpus": 1, + "default_name_format": "{name}-{0}", + "first_port_name": "", + "hda_disk_image": "IOSvL2-15.2.4.0.55E.qcow2", + "hda_disk_interface": "ide", + "hdb_disk_image": "", + "hdb_disk_interface": "ide", + "hdc_disk_image": "", + "hdc_disk_interface": "ide", + "hdd_disk_image": "", + "hdd_disk_interface": "ide", + "initrd": "", + "kernel_command_line": "", + "kernel_image": "", + "legacy_networking": False, + "linked_clone": True, + "mac_address": "", + "name": "Qemu appliance", + "on_close": "power_off", + "options": "", + "platform": "i386", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "process_priority": "normal", + "qemu_path": "", + "ram": 512, + "symbol": ":/symbols/qemu_guest.svg", + "usage": ""} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_vmware_appliance_create(http_controller): + + params = {"name": "VMware appliance", + "compute_id": "local", + "appliance_type": "vmware", + "vmx_path": "/path/to/vm.vmx"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"adapter_type": "e1000", + "adapters": 1, + "appliance_type": "vmware", + "builtin": False, + "category": "guest", + "compute_id": "local", + "console_auto_start": False, + "console_type": "none", + "default_name_format": "{name}-{0}", + "first_port_name": "", + "headless": False, + "linked_clone": False, + "name": "VMware appliance", + "on_close": "power_off", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "symbol": ":/symbols/vmware_guest.svg", + "use_any_adapter": False, + "vmx_path": "/path/to/vm.vmx"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_virtualbox_appliance_create(http_controller): + + params = {"name": "VirtualBox appliance", + "compute_id": "local", + "appliance_type": "virtualbox", + "vmname": "My VirtualBox VM"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"adapter_type": "Intel PRO/1000 MT Desktop (82540EM)", + "adapters": 1, + "appliance_type": "virtualbox", + "builtin": False, + "category": "guest", + "compute_id": "local", + "console_auto_start": False, + "console_type": "none", + "default_name_format": "{name}-{0}", + "first_port_name": "", + "headless": False, + "linked_clone": False, + "name": "VirtualBox appliance", + "on_close": "power_off", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "ram": 256, + "symbol": ":/symbols/vbox_guest.svg", + "use_any_adapter": False, + "vmname": "My VirtualBox VM"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + +def test_vpcs_appliance_create(http_controller): + + params = {"name": "VPCS appliance", + "compute_id": "local", + "appliance_type": "vpcs"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "vpcs", + "base_script_file": "vpcs_base_config.txt", + "builtin": False, + "category": "guest", + "compute_id": "local", + "console_auto_start": False, + "console_type": "telnet", + "default_name_format": "PC{0}", + "name": "VPCS appliance", + "symbol": ":/symbols/vpcs_guest.svg"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + +def test_ethernet_switch_appliance_create(http_controller): + + params = {"name": "Ethernet switch appliance", + "compute_id": "local", + "appliance_type": "ethernet_switch"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "ethernet_switch", + "builtin": False, + "category": "switch", + "compute_id": "local", + "console_type": "telnet", + "default_name_format": "Switch{0}", + "name": "Ethernet switch appliance", + "ports_mapping": [{"ethertype": "", + "name": "Ethernet0", + "port_number": 0, + "type": "access", + "vlan": 1 + }, + {"ethertype": "", + "name": "Ethernet1", + "port_number": 1, + "type": "access", + "vlan": 1 + }, + {"ethertype": "", + "name": "Ethernet2", + "port_number": 2, + "type": "access", + "vlan": 1 + }, + {"ethertype": "", + "name": "Ethernet3", + "port_number": 3, + "type": "access", + "vlan": 1 + }, + {"ethertype": "", + "name": "Ethernet4", + "port_number": 4, + "type": "access", + "vlan": 1 + }, + {"ethertype": "", + "name": "Ethernet5", + "port_number": 5, + "type": "access", + "vlan": 1 + }, + {"ethertype": "", + "name": "Ethernet6", + "port_number": 6, + "type": "access", + "vlan": 1 + }, + {"ethertype": "", + "name": "Ethernet7", + "port_number": 7, + "type": "access", + "vlan": 1 + }], + "symbol": ":/symbols/ethernet_switch.svg"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_cloud_appliance_create(http_controller): + + params = {"name": "Cloud appliance", + "compute_id": "local", + "appliance_type": "cloud"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"appliance_type": "cloud", + "builtin": False, + "category": "guest", + "compute_id": "local", + "default_name_format": "Cloud{0}", + "name": "Cloud appliance", + "symbol": ":/symbols/cloud.svg"} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + +def test_ethernet_hub_appliance_create(http_controller): + + params = {"name": "Ethernet hub appliance", + "compute_id": "local", + "appliance_type": "ethernet_hub"} + + response = http_controller.post("/appliances", params, example=True) + assert response.status == 201 + assert response.json["appliance_id"] is not None + + expected_response = {"ports_mapping": [{"port_number": 0, + "name": "Ethernet0" + }, + {"port_number": 1, + "name": "Ethernet1" + }, + {"port_number": 2, + "name": "Ethernet2" + }, + {"port_number": 3, + "name": "Ethernet3" + }, + {"port_number": 4, + "name": "Ethernet4" + }, + {"port_number": 5, + "name": "Ethernet5" + }, + {"port_number": 6, + "name": "Ethernet6" + }, + {"port_number": 7, + "name": "Ethernet7" + }], + "compute_id": "local", + "name": "Ethernet hub appliance", + "symbol": ":/symbols/hub.svg", + "default_name_format": "Hub{0}", + "appliance_type": "ethernet_hub", + "category": "switch", + "builtin": False} + + for item, value in expected_response.items(): + assert response.json.get(item) == value + + def test_create_node_from_appliance(http_controller, controller, project, compute): id = str(uuid.uuid4()) @@ -209,6 +954,5 @@ def test_create_node_from_appliance(http_controller, controller, project, comput "y": 12 }) mock.assert_called_with(id, x=42, y=12, compute_id=None) - print(response.body) assert response.route == "/projects/{project_id}/appliances/{appliance_id}" assert response.status == 201