mirror of
https://github.com/GNS3/gns3-server.git
synced 2024-11-16 16:54:51 +02:00
Update VPCS instance
This commit is contained in:
parent
7abb426d04
commit
368d1ff70b
@ -18,5 +18,5 @@ X-ROUTE: /vpcs/{uuid}
|
||||
"project_uuid": "a1e920ca-338a-4e9f-b363-aa607b09dd80",
|
||||
"script_file": null,
|
||||
"startup_script": null,
|
||||
"uuid": "40f76457-de2b-4399-8853-a35393a72a2d"
|
||||
"uuid": "f8155d67-c0bf-4229-be4c-97edaaae7b0b"
|
||||
}
|
||||
|
@ -21,5 +21,5 @@ X-ROUTE: /vpcs
|
||||
"project_uuid": "a1e920ca-338a-4e9f-b363-aa607b09dd80",
|
||||
"script_file": null,
|
||||
"startup_script": null,
|
||||
"uuid": "a022aa0d-acab-4554-b2a6-6e6f51c9d65e"
|
||||
"uuid": "5a9aac64-5b62-41bd-955a-fcef90a2fac5"
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
from ..web.route import Route
|
||||
from ..schemas.vpcs import VPCS_CREATE_SCHEMA
|
||||
from ..schemas.vpcs import VPCS_UPDATE_SCHEMA
|
||||
from ..schemas.vpcs import VPCS_OBJECT_SCHEMA
|
||||
from ..schemas.vpcs import VPCS_NIO_SCHEMA
|
||||
from ..modules.vpcs import VPCS
|
||||
@ -67,6 +68,27 @@ class VPCSHandler:
|
||||
vm = vpcs_manager.get_vm(request.match_info["uuid"])
|
||||
response.json(vm)
|
||||
|
||||
@classmethod
|
||||
@Route.put(
|
||||
r"/vpcs/{uuid}",
|
||||
status_codes={
|
||||
200: "VPCS instance updated",
|
||||
409: "Conflict"
|
||||
},
|
||||
description="Update a VPCS instance",
|
||||
input=VPCS_UPDATE_SCHEMA,
|
||||
output=VPCS_OBJECT_SCHEMA)
|
||||
def update(request, response):
|
||||
|
||||
vpcs_manager = VPCS.instance()
|
||||
vm = vpcs_manager.get_vm(request.match_info["uuid"])
|
||||
vm.name = request.json.get("name", vm.name)
|
||||
vm.console = request.json.get("console", vm.console)
|
||||
vm.script_file = request.json.get("script_file", vm.script_file)
|
||||
vm.startup_script = request.json.get("startup_script", vm.startup_script)
|
||||
|
||||
response.json(vm)
|
||||
|
||||
@classmethod
|
||||
@Route.post(
|
||||
r"/vpcs/{uuid}/start",
|
||||
|
@ -59,6 +59,10 @@ class BaseVM:
|
||||
:param new_name: name
|
||||
"""
|
||||
|
||||
log.info("{module} {name} [{uuid}]: renamed to {new_name}".format(module=self.module_name,
|
||||
name=self._name,
|
||||
uuid=self.uuid,
|
||||
new_name=new_name))
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
|
@ -123,7 +123,17 @@ class VPCSVM(BaseVM):
|
||||
|
||||
return self._console
|
||||
|
||||
# FIXME: correct way to subclass a property?
|
||||
@console.setter
|
||||
def console(self, console):
|
||||
"""
|
||||
Change console port
|
||||
|
||||
:params console: Console port (integer)
|
||||
"""
|
||||
if self._console:
|
||||
self._manager.port_manager.release_console_port(self._console)
|
||||
self._console = self._manager.port_manager.reserve_console_port(console)
|
||||
|
||||
@BaseVM.name.setter
|
||||
def name(self, new_name):
|
||||
"""
|
||||
@ -133,22 +143,11 @@ class VPCSVM(BaseVM):
|
||||
"""
|
||||
|
||||
if self._script_file:
|
||||
# update the startup.vpc
|
||||
config_path = os.path.join(self.working_dir, "startup.vpc")
|
||||
if os.path.isfile(config_path):
|
||||
try:
|
||||
with open(config_path, "r+", errors="replace") as f:
|
||||
old_config = f.read()
|
||||
new_config = old_config.replace(self._name, new_name)
|
||||
f.seek(0)
|
||||
f.write(new_config)
|
||||
except OSError as e:
|
||||
raise VPCSError("Could not amend the configuration {}: {}".format(config_path, e))
|
||||
content = self.startup_script
|
||||
content = content.replace(self._name, new_name)
|
||||
self.startup_script = content
|
||||
|
||||
log.info("VPCS {name} [{uuid}]: renamed to {new_name}".format(name=self._name,
|
||||
uuid=self.uuid,
|
||||
new_name=new_name))
|
||||
BaseVM.name = new_name
|
||||
super(VPCSVM, VPCSVM).name.__set__(self, new_name)
|
||||
|
||||
@property
|
||||
def startup_script(self):
|
||||
@ -173,7 +172,10 @@ class VPCSVM(BaseVM):
|
||||
self._script_file = os.path.join(self.working_dir, 'startup.vpcs')
|
||||
try:
|
||||
with open(self._script_file, '+w') as f:
|
||||
f.write(startup_script)
|
||||
if startup_script is None:
|
||||
f.write('')
|
||||
else:
|
||||
f.write(startup_script)
|
||||
except OSError as e:
|
||||
raise VPCSError("Can't write VPCS startup file '{}'".format(self._script_file))
|
||||
|
||||
|
@ -63,6 +63,33 @@ VPCS_CREATE_SCHEMA = {
|
||||
"required": ["name", "project_uuid"]
|
||||
}
|
||||
|
||||
VPCS_UPDATE_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"description": "Request validation to update a VPCS instance",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "VPCS device name",
|
||||
"type": ["string", "null"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"console": {
|
||||
"description": "console TCP port",
|
||||
"minimum": 1,
|
||||
"maximum": 65535,
|
||||
"type": ["integer", "null"]
|
||||
},
|
||||
"script_file": {
|
||||
"description": "VPCS startup script",
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"startup_script": {
|
||||
"description": "Content of the VPCS startup script",
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
},
|
||||
"additionalProperties": False,
|
||||
}
|
||||
|
||||
VPCS_NIO_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
|
@ -45,6 +45,9 @@ class Query:
|
||||
def post(self, path, body={}, **kwargs):
|
||||
return self._fetch("POST", path, body, **kwargs)
|
||||
|
||||
def put(self, path, body={}, **kwargs):
|
||||
return self._fetch("PUT", path, body, **kwargs)
|
||||
|
||||
def get(self, path, **kwargs):
|
||||
return self._fetch("GET", path, **kwargs)
|
||||
|
||||
@ -147,11 +150,10 @@ def loop(request):
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def server(request, loop):
|
||||
def server(request, loop, port_manager):
|
||||
port = _get_unused_port()
|
||||
host = "localhost"
|
||||
app = web.Application()
|
||||
port_manager = PortManager("127.0.0.1", False)
|
||||
for method, route, handler in Route.get_routes():
|
||||
app.router.add_route(method, route, handler)
|
||||
for module in MODULES:
|
||||
|
@ -20,7 +20,7 @@ This test suite check /project endpoint
|
||||
"""
|
||||
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
from tests.utils import asyncio_patch, port_manager
|
||||
from tests.api.base import server, loop
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
@ -20,7 +20,7 @@ This test suite check /version endpoint
|
||||
It's also used for unittest the HTTP implementation.
|
||||
"""
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
from tests.utils import asyncio_patch, port_manager
|
||||
from tests.api.base import server, loop
|
||||
from gns3server.version import __version__
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from tests.api.base import server, loop, project
|
||||
from tests.utils import asyncio_patch
|
||||
from tests.utils import asyncio_patch, port_manager
|
||||
from gns3server.modules.virtualbox.virtualbox_vm import VirtualBoxVM
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
import pytest
|
||||
import os
|
||||
from tests.api.base import server, loop, project
|
||||
from tests.utils import asyncio_patch
|
||||
from tests.utils import asyncio_patch, free_console_port, port_manager
|
||||
from unittest.mock import patch, Mock
|
||||
from gns3server.modules.vpcs.vpcs_vm import VPCSVM
|
||||
|
||||
@ -68,13 +68,13 @@ def test_vpcs_create_startup_script(server, project):
|
||||
assert response.json["startup_script"] == "ip 192.168.1.2\necho TEST"
|
||||
|
||||
|
||||
def test_vpcs_create_port(server, project):
|
||||
response = server.post("/vpcs", {"name": "PC TEST 1", "project_uuid": project.uuid, "console": 4242})
|
||||
def test_vpcs_create_port(server, project, free_console_port):
|
||||
response = server.post("/vpcs", {"name": "PC TEST 1", "project_uuid": project.uuid, "console": free_console_port})
|
||||
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
|
||||
assert response.json["console"] == free_console_port
|
||||
|
||||
|
||||
def test_vpcs_nio_create_udp(server, vm):
|
||||
@ -119,3 +119,18 @@ def test_vpcs_stop(server, vm):
|
||||
response = server.post("/vpcs/{}/stop".format(vm["uuid"]))
|
||||
assert mock.called
|
||||
assert response.status == 200
|
||||
|
||||
|
||||
def test_vpcs_update(server, vm, tmpdir, free_console_port):
|
||||
path = os.path.join(str(tmpdir), 'startup2.vpcs')
|
||||
with open(path, 'w+') as f:
|
||||
f.write(path)
|
||||
response = server.put("/vpcs/{}".format(vm["uuid"]), {"name": "test",
|
||||
"console": free_console_port,
|
||||
"script_file": path,
|
||||
"startup_script": "ip 192.168.1.1"})
|
||||
assert response.status == 200
|
||||
assert response.json["name"] == "test"
|
||||
assert response.json["console"] == free_console_port
|
||||
assert response.json["script_file"] == path
|
||||
assert response.json["startup_script"] == "ip 192.168.1.1"
|
||||
|
@ -18,7 +18,7 @@
|
||||
import pytest
|
||||
import asyncio
|
||||
import os
|
||||
from tests.utils import asyncio_patch
|
||||
from tests.utils import asyncio_patch, port_manager, free_console_port
|
||||
|
||||
# TODO: Move loop to util
|
||||
from tests.api.base import loop, project
|
||||
@ -136,3 +136,28 @@ def test_get_startup_script(vm):
|
||||
content = "echo GNS3 VPCS\nip 192.168.1.2\n"
|
||||
vm.startup_script = content
|
||||
assert vm.startup_script == content
|
||||
|
||||
|
||||
def test_change_console_port(vm, free_console_port):
|
||||
vm.console = free_console_port
|
||||
vm.console = free_console_port + 1
|
||||
assert vm.console == free_console_port
|
||||
PortManager.instance().reserve_console_port(free_console_port + 1)
|
||||
|
||||
|
||||
def test_change_name(vm, tmpdir):
|
||||
path = os.path.join(str(tmpdir), 'startup.vpcs')
|
||||
vm.name = "world"
|
||||
with open(path, 'w+') as f:
|
||||
f.write("name world")
|
||||
vm.script_file = path
|
||||
vm.name = "hello"
|
||||
assert vm.name == "hello"
|
||||
with open(path) as f:
|
||||
assert f.read() == "name hello"
|
||||
|
||||
|
||||
def test_change_script_file(vm, tmpdir):
|
||||
path = os.path.join(str(tmpdir), 'startup2.vpcs')
|
||||
vm.script_file = path
|
||||
assert vm.script_file == path
|
||||
|
@ -16,7 +16,10 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
from gns3server.modules.project_manager import ProjectManager
|
||||
from gns3server.modules.port_manager import PortManager
|
||||
|
||||
|
||||
class _asyncio_patch:
|
||||
@ -54,3 +57,18 @@ class _asyncio_patch:
|
||||
|
||||
def asyncio_patch(function, *args, **kwargs):
|
||||
return _asyncio_patch(function, *args, **kwargs)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def port_manager():
|
||||
return PortManager("127.0.0.1", False)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def free_console_port(request, port_manager):
|
||||
# In case of already use ports we will raise an exception
|
||||
port = port_manager.get_free_console_port()
|
||||
# We release the port immediately in order to allow
|
||||
# the test do whatever the test want
|
||||
port_manager.release_console_port(port)
|
||||
return port
|
||||
|
Loading…
Reference in New Issue
Block a user