mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
Delete a VM, mark it as destroyable
This commit is contained in:
parent
28308b10bc
commit
f97c2b2cbe
@ -30,9 +30,28 @@ class ProjectHandler:
|
||||
output=PROJECT_OBJECT_SCHEMA,
|
||||
input=PROJECT_OBJECT_SCHEMA)
|
||||
def create_project(request, response):
|
||||
|
||||
pm = ProjectManager.instance()
|
||||
p = pm.create_project(
|
||||
location=request.json.get("location"),
|
||||
uuid=request.json.get("uuid")
|
||||
)
|
||||
response.json(p)
|
||||
|
||||
@classmethod
|
||||
@Route.post(
|
||||
r"/project/{uuid}/commit",
|
||||
description="Write changes on disk",
|
||||
parameters={
|
||||
"uuid": "Project instance UUID",
|
||||
},
|
||||
status_codes={
|
||||
204: "Changes write on disk",
|
||||
404: "Project instance doesn't exist"
|
||||
})
|
||||
def create_project(request, response):
|
||||
|
||||
pm = ProjectManager.instance()
|
||||
project = pm.get_project(request.match_info["uuid"])
|
||||
project.commit()
|
||||
response.set_status(204)
|
||||
|
@ -149,14 +149,13 @@ class BaseManager:
|
||||
self._vms[vm.uuid] = vm
|
||||
return vm
|
||||
|
||||
# FIXME: should be named close_vm and we should have a
|
||||
# delete_vm when a user deletes a VM (including files in workdir)
|
||||
@asyncio.coroutine
|
||||
def delete_vm(self, uuid):
|
||||
def close_vm(self, uuid):
|
||||
"""
|
||||
Delete a VM
|
||||
|
||||
:param uuid: VM UUID
|
||||
:returns: VM instance
|
||||
"""
|
||||
|
||||
vm = self.get_vm(uuid)
|
||||
@ -164,7 +163,22 @@ class BaseManager:
|
||||
yield from vm.close()
|
||||
else:
|
||||
vm.close()
|
||||
return vm
|
||||
|
||||
@asyncio.coroutine
|
||||
def delete_vm(self, uuid):
|
||||
"""
|
||||
Delete a VM. VM working directory will be destroy when
|
||||
we receive a commit.
|
||||
|
||||
:param uuid: VM UUID
|
||||
:returns: VM instance
|
||||
"""
|
||||
|
||||
vm = yield from self.close_vm(uuid)
|
||||
vm.project.mark_vm_for_destruction(vm)
|
||||
del self._vms[vm.uuid]
|
||||
return vm
|
||||
|
||||
@staticmethod
|
||||
def _has_privileged_access(executable):
|
||||
|
@ -96,7 +96,7 @@ class BaseVM:
|
||||
Return VM working directory
|
||||
"""
|
||||
|
||||
return self._project.vm_working_directory(self.manager.module_name.lower(), self._uuid)
|
||||
return self._project.vm_working_directory(self)
|
||||
|
||||
def create(self):
|
||||
"""
|
||||
|
@ -18,6 +18,7 @@
|
||||
import aiohttp
|
||||
import os
|
||||
import tempfile
|
||||
import shutil
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
|
||||
@ -45,6 +46,7 @@ class Project:
|
||||
if location is None:
|
||||
self._location = tempfile.mkdtemp()
|
||||
|
||||
self._vms_to_destroy = set()
|
||||
self._path = os.path.join(self._location, self._uuid)
|
||||
try:
|
||||
os.makedirs(os.path.join(self._path, "vms"), exist_ok=True)
|
||||
@ -66,25 +68,40 @@ class Project:
|
||||
|
||||
return self._path
|
||||
|
||||
def vm_working_directory(self, module, vm_uuid):
|
||||
def vm_working_directory(self, vm):
|
||||
"""
|
||||
Return a working directory for a specific VM.
|
||||
If the directory doesn't exist, the directory is created.
|
||||
|
||||
:param module: The module name (vpcs, dynamips...)
|
||||
:param vm_uuid: VM UUID
|
||||
:param vm: An instance of VM
|
||||
:returns: A string with a VM working directory
|
||||
"""
|
||||
|
||||
workdir = os.path.join(self._path, module, vm_uuid)
|
||||
workdir = os.path.join(self._path, vm.manager.module_name.lower(), vm.uuid)
|
||||
try:
|
||||
os.makedirs(workdir, exist_ok=True)
|
||||
except OSError as e:
|
||||
raise aiohttp.web.HTTPInternalServerError(text="Could not create VM working directory: {}".format(e))
|
||||
return workdir
|
||||
|
||||
def mark_vm_for_destruction(self, vm):
|
||||
"""
|
||||
:param vm: An instance of VM
|
||||
"""
|
||||
|
||||
self._vms_to_destroy.add(vm)
|
||||
|
||||
def __json__(self):
|
||||
|
||||
return {
|
||||
"uuid": self._uuid,
|
||||
"location": self._location
|
||||
}
|
||||
|
||||
def commit(self):
|
||||
"""Write project changes on disk"""
|
||||
while self._vms_to_destroy:
|
||||
vm = self._vms_to_destroy.pop()
|
||||
directory = self.vm_working_directory(vm)
|
||||
if os.path.exists(directory):
|
||||
shutil.rmtree(directory)
|
||||
|
@ -19,6 +19,8 @@
|
||||
This test suite check /project endpoint
|
||||
"""
|
||||
|
||||
import uuid
|
||||
|
||||
|
||||
def test_create_project_with_dir(server, tmpdir):
|
||||
response = server.post("/project", {"location": str(tmpdir)})
|
||||
@ -46,3 +48,13 @@ def test_create_project_with_uuid(server):
|
||||
assert response.status == 200
|
||||
assert response.json["uuid"] == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
assert response.json["location"] == "/tmp"
|
||||
|
||||
|
||||
def test_commit_project(server, project):
|
||||
response = server.post("/project/{uuid}/commit".format(uuid=project.uuid))
|
||||
assert response.status == 204
|
||||
|
||||
|
||||
def test_commit_project_invalid_project_uuid(server, project):
|
||||
response = server.post("/project/{uuid}/commit".format(uuid=uuid.uuid4()))
|
||||
assert response.status == 404
|
||||
|
@ -17,7 +17,21 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from gns3server.modules.project import Project
|
||||
from gns3server.modules.vpcs import VPCS, VPCSVM
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def manager(port_manager):
|
||||
m = VPCS.instance()
|
||||
m.port_manager = port_manager
|
||||
return m
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vm(project, manager):
|
||||
return VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
|
||||
|
||||
def test_affect_uuid():
|
||||
@ -45,7 +59,25 @@ def test_json(tmpdir):
|
||||
assert p.__json__() == {"location": p.location, "uuid": p.uuid}
|
||||
|
||||
|
||||
def test_vm_working_directory(tmpdir):
|
||||
def test_vm_working_directory(tmpdir, vm):
|
||||
p = Project(location=str(tmpdir))
|
||||
assert os.path.exists(p.vm_working_directory('vpcs', '00010203-0405-0607-0809-0a0b0c0d0e0f'))
|
||||
assert os.path.exists(os.path.join(str(tmpdir), p.uuid, 'vpcs', '00010203-0405-0607-0809-0a0b0c0d0e0f'))
|
||||
assert os.path.exists(p.vm_working_directory(vm))
|
||||
assert os.path.exists(os.path.join(str(tmpdir), p.uuid, vm.module_name, vm.uuid))
|
||||
|
||||
|
||||
def test_mark_vm_for_destruction(tmpdir, vm):
|
||||
p = Project(location=str(tmpdir))
|
||||
p.mark_vm_for_destruction(vm)
|
||||
assert len(p._vms_to_destroy) == 1
|
||||
|
||||
|
||||
def test_commit(tmpdir, manager):
|
||||
project = Project(location=str(tmpdir))
|
||||
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||
directory = project.vm_working_directory(vm)
|
||||
project.mark_vm_for_destruction(vm)
|
||||
assert len(project._vms_to_destroy) == 1
|
||||
assert os.path.exists(directory)
|
||||
project.commit()
|
||||
assert len(project._vms_to_destroy) == 0
|
||||
assert os.path.exists(directory) is False
|
||||
|
Loading…
Reference in New Issue
Block a user