diff --git a/docs/api/examples/post_vpcs.txt b/docs/api/examples/post_vpcs.txt index 9b6ffd02..4fdc51cd 100644 --- a/docs/api/examples/post_vpcs.txt +++ b/docs/api/examples/post_vpcs.txt @@ -20,5 +20,5 @@ X-ROUTE: /vpcs "name": "PC TEST 1", "project_uuid": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "script_file": null, - "uuid": "aa017896-574d-4a10-bcad-d3001ea98f8b" + "uuid": "f598eb3a-67b2-43ab-af37-3c9b1f643cdd" } diff --git a/gns3server/handlers/vpcs_handler.py b/gns3server/handlers/vpcs_handler.py index 2978e0de..54d32af2 100644 --- a/gns3server/handlers/vpcs_handler.py +++ b/gns3server/handlers/vpcs_handler.py @@ -44,6 +44,7 @@ class VPCSHandler: vm = yield from vpcs.create_vm(request.json["name"], request.json["project_uuid"], uuid=request.json.get("uuid"), + console=request.json.get("console"), script_file=request.json.get("script_file")) response.json(vm) diff --git a/gns3server/modules/port_manager.py b/gns3server/modules/port_manager.py index 26b2c990..6ffc3309 100644 --- a/gns3server/modules/port_manager.py +++ b/gns3server/modules/port_manager.py @@ -157,6 +157,7 @@ class PortManager: Get an available TCP console port and reserve it """ + print("FREE") port = self.find_unused_port(self._console_port_range[0], self._console_port_range[1], host=self._console_host, @@ -176,6 +177,7 @@ class PortManager: if port in self._used_tcp_ports: raise HTTPConflict(reason="TCP port already {} in use on host".format(port, self._console_host)) self._used_tcp_ports.add(port) + return port def release_console_port(self, port): """ diff --git a/gns3server/modules/vpcs/vpcs_vm.py b/gns3server/modules/vpcs/vpcs_vm.py index 66cba55e..02a20a9b 100644 --- a/gns3server/modules/vpcs/vpcs_vm.py +++ b/gns3server/modules/vpcs/vpcs_vm.py @@ -72,13 +72,10 @@ class VPCSVM(BaseVM): self._script_file = script_file self._ethernet_adapter = EthernetAdapter() # one adapter with 1 Ethernet interface - try: - if not self._console: - self._console = self._manager.port_manager.get_free_console_port() - else: - self._console = self._manager.port_manager.reserve_console_port(self._console) - except Exception as e: - raise VPCSError(e) + if self._console is not None: + self._console = self._manager.port_manager.reserve_console_port(self._console) + else: + self._console = self._manager.port_manager.get_free_console_port() self._check_requirements() @@ -106,9 +103,9 @@ class VPCSVM(BaseVM): def __json__(self): - return {"name": self.name, - "uuid": self.uuid, - "console": self.console, + return {"name": self._name, + "uuid": self._uuid, + "console": self._console, "project_uuid": self.project.uuid, "script_file": self.script_file} diff --git a/gns3server/schemas/vpcs.py b/gns3server/schemas/vpcs.py index ed738eb4..ea54ee0c 100644 --- a/gns3server/schemas/vpcs.py +++ b/gns3server/schemas/vpcs.py @@ -48,7 +48,7 @@ VPCS_CREATE_SCHEMA = { "description": "console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "script_file": { "description": "VPCS startup script", diff --git a/gns3server/web/response.py b/gns3server/web/response.py index 2a0b3911..04d0846a 100644 --- a/gns3server/web/response.py +++ b/gns3server/web/response.py @@ -49,6 +49,8 @@ class Response(aiohttp.web.Response): try: jsonschema.validate(answer, self._output_schema) except jsonschema.ValidationError as e: - log.error("Invalid output schema") + log.error("Invalid output schema {} '{}' in schema: {}".format(e.validator, + e.validator_value, + json.dumps(e.schema))) raise aiohttp.web.HTTPBadRequest(text="{}".format(e)) self.body = json.dumps(answer, indent=4, sort_keys=True).encode('utf-8') diff --git a/gns3server/web/route.py b/gns3server/web/route.py index 4cc6a863..cd1ece5d 100644 --- a/gns3server/web/route.py +++ b/gns3server/web/route.py @@ -40,7 +40,9 @@ def parse_request(request, input_schema): try: jsonschema.validate(request.json, input_schema) except jsonschema.ValidationError as e: - log.error("Invalid input schema") + log.error("Invalid input schema {} '{}' in schema: {}".format(e.validator, + e.validator_value, + json.dumps(e.schema))) raise aiohttp.web.HTTPBadRequest(text="Request is not {} '{}' in schema: {}".format( e.validator, e.validator_value, diff --git a/tests/api/test_vpcs.py b/tests/api/test_vpcs.py index 0f56e1a1..3f9ff2f7 100644 --- a/tests/api/test_vpcs.py +++ b/tests/api/test_vpcs.py @@ -47,6 +47,15 @@ def test_vpcs_create_script_file(server, project): assert response.json["script_file"] == "/tmp/test" +def test_vpcs_create_port(server, project): + response = server.post("/vpcs", {"name": "PC TEST 1", "project_uuid": project.uuid, "console": 4242}) + assert response.status == 200 + assert response.route == "/vpcs" + assert response.json["name"] == "PC TEST 1" + assert response.json["project_uuid"] == project.uuid + assert response.json["console"] == 4242 + + def test_vpcs_nio_create_udp(server, vm): response = server.post("/vpcs/{}/ports/0/nio".format(vm["uuid"]), {"type": "nio_udp", "lport": 4242,