1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-28 11:18:11 +00:00

Option to prune images when deleting template.

This commit is contained in:
grossmj 2021-08-23 10:27:10 +09:30
parent bf9a3aee20
commit 332fa47b50
4 changed files with 44 additions and 4 deletions

View File

@ -25,14 +25,15 @@ import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
from fastapi import APIRouter, Request, Response, HTTPException, Depends, Response, status from fastapi import APIRouter, Request, HTTPException, Depends, Response, status
from typing import List from typing import List, Optional
from uuid import UUID from uuid import UUID
from gns3server import schemas from gns3server import schemas
from gns3server.db.repositories.templates import TemplatesRepository from gns3server.db.repositories.templates import TemplatesRepository
from gns3server.services.templates import TemplatesService from gns3server.services.templates import TemplatesService
from gns3server.db.repositories.rbac import RbacRepository from gns3server.db.repositories.rbac import RbacRepository
from gns3server.db.repositories.images import ImagesRepository
from .dependencies.authentication import get_current_active_user from .dependencies.authentication import get_current_active_user
from .dependencies.database import get_repository from .dependencies.database import get_repository
@ -97,7 +98,9 @@ async def update_template(
@router.delete("/{template_id}", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{template_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_template( async def delete_template(
template_id: UUID, template_id: UUID,
prune_images: Optional[bool] = False,
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)), templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
images_repo: RbacRepository = Depends(get_repository(ImagesRepository)),
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)) rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response: ) -> Response:
""" """
@ -106,6 +109,8 @@ async def delete_template(
await TemplatesService(templates_repo).delete_template(template_id) await TemplatesService(templates_repo).delete_template(template_id)
await rbac_repo.delete_all_permissions_with_path(f"/templates/{template_id}") await rbac_repo.delete_all_permissions_with_path(f"/templates/{template_id}")
if prune_images:
await images_repo.prune_images()
return Response(status_code=status.HTTP_204_NO_CONTENT) return Response(status_code=status.HTTP_204_NO_CONTENT)

View File

@ -117,10 +117,11 @@ class ImagesRepository(BaseRepository):
images_deleted = 0 images_deleted = 0
for image in images: for image in images:
try: try:
log.debug(f"Deleting image '{image.path}'")
os.remove(image.path) os.remove(image.path)
except OSError: except OSError:
log.warning(f"Could not delete image file {image.path}") log.warning(f"Could not delete image file {image.path}")
if await self.delete_image(image.filename): if await self.delete_image(image.filename):
images_deleted += 1 images_deleted += 1
log.info(f"{images_deleted} image have been deleted") log.info(f"{images_deleted} image(s) have been deleted")
return images_deleted return images_deleted

View File

@ -159,7 +159,7 @@ class TemplatesService:
image = await self._templates_repo.get_image(image_name) image = await self._templates_repo.get_image(image_name)
if not image or not os.path.exists(image.path): if not image or not os.path.exists(image.path):
raise ControllerNotFoundError(f"Image {image_name} could not be found") raise ControllerNotFoundError(f"Image '{image_name}' could not be found")
return image return image
async def _find_images(self, template_type: str, settings: dict) -> List[models.Image]: async def _find_images(self, template_type: str, settings: dict) -> List[models.Image]:

View File

@ -116,6 +116,40 @@ class TestTemplateRoutes:
response = await client.delete(app.url_path_for("delete_template", template_id=template_id)) response = await client.delete(app.url_path_for("delete_template", template_id=template_id))
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_template_delete_with_prune_images(
self,
app: FastAPI,
client: AsyncClient,
db_session: AsyncSession,
tmpdir: str,
) -> None:
path = os.path.join(tmpdir, "test.qcow2")
with open(path, "wb+") as f:
f.write(b'\x42\x42\x42\x42')
images_repo = ImagesRepository(db_session)
await images_repo.add_image("test.qcow2", "qemu", 42, path, "e342eb86c1229b6c154367a5476969b5", "md5")
template_id = str(uuid.uuid4())
params = {"template_id": template_id,
"name": "QEMU_TEMPLATE",
"compute_id": "local",
"hda_disk_image": "test.qcow2",
"template_type": "qemu"}
response = await client.post(app.url_path_for("create_template"), json=params)
assert response.status_code == status.HTTP_201_CREATED
response = await client.delete(
app.url_path_for("delete_template", template_id=template_id),
params={"prune_images": True}
)
assert response.status_code == status.HTTP_204_NO_CONTENT
images_repo = ImagesRepository(db_session)
images = await images_repo.get_images()
assert len(images) == 0
# async def test_create_node_from_template(self, controller_api, controller, project): # async def test_create_node_from_template(self, controller_api, controller, project):
# #
# id = str(uuid.uuid4()) # id = str(uuid.uuid4())