mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
Appliance management refactoring:
* Install an appliance based on selected version * Each template have unique name and version * Allow to download an appliance file
This commit is contained in:
1 parent
8a643cf4a4
commit
04934691df
11 files changed
+326
-76
No files matched your search
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
# Copyright (C) 2021 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -15,7 +15,9 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import shutil
|
||||
|
||||
from fastapi import FastAPI, status
|
||||
from httpx import AsyncClient
|
||||
@@ -23,8 +25,44 @@ from httpx import AsyncClient
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
|
||||
async def test_appliances_list(app: FastAPI, client: AsyncClient) -> None:
|
||||
class TestApplianceRoutes:
|
||||
|
||||
response = await client.get(app.url_path_for("get_appliances"))
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert len(response.json()) > 0
|
||||
async def test_appliances_list(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
response = await client.get(app.url_path_for("get_appliances"))
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert len(response.json()) > 0
|
||||
|
||||
async def test_appliance_download(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
appliance_id = "3bf492b6-5717-4257-9bfd-b34617c6f133" # Cisco IOSv appliance
|
||||
response = await client.get(app.url_path_for("download_appliance", appliance_id=appliance_id))
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.json()["appliance_id"] == appliance_id
|
||||
|
||||
async def test_docker_appliance_install(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
appliance_id = "fc520ae2-a4e5-48c3-9a13-516bb2e94668" # Alpine Linux appliance
|
||||
response = await client.post(app.url_path_for("install_appliance", appliance_id=appliance_id))
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||
|
||||
async def test_docker_appliance_install_with_version(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
appliance_id = "fc520ae2-a4e5-48c3-9a13-516bb2e94668" # Alpine Linux appliance
|
||||
params = {"version": "123"}
|
||||
response = await client.post(app.url_path_for("install_appliance", appliance_id=appliance_id), params=params)
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
|
||||
async def test_qemu_appliance_install_with_version(self, app: FastAPI, client: AsyncClient, images_dir: str) -> None:
|
||||
|
||||
shutil.copy("tests/resources/empty8G.qcow2", os.path.join(images_dir, "QEMU", "empty8G.qcow2"))
|
||||
appliance_id = "1cfdf900-7c30-4cb7-8f03-3f61d2581633" # Empty VM appliance
|
||||
params = {"version": "8G"}
|
||||
response = await client.post(app.url_path_for("install_appliance", appliance_id=appliance_id), params=params)
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||
|
||||
async def test_qemu_appliance_install_without_version(self, app: FastAPI, client: AsyncClient, images_dir: str) -> None:
|
||||
|
||||
appliance_id = "1cfdf900-7c30-4cb7-8f03-3f61d2581633" # Empty VM appliance
|
||||
response = await client.post(app.url_path_for("install_appliance", appliance_id=appliance_id))
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
@@ -23,7 +23,9 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from fastapi import FastAPI, status
|
||||
from httpx import AsyncClient
|
||||
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.db.repositories.images import ImagesRepository
|
||||
from gns3server.db.repositories.templates import TemplatesRepository
|
||||
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
@@ -256,3 +258,27 @@ class TestImageRoutes:
|
||||
images_repo = ImagesRepository(db_session)
|
||||
images_in_db = await images_repo.get_images()
|
||||
assert len(images_in_db) == 0
|
||||
|
||||
async def test_image_upload_create_appliance(
|
||||
self, app: FastAPI,
|
||||
client: AsyncClient,
|
||||
db_session: AsyncSession,
|
||||
controller: Controller
|
||||
) -> None:
|
||||
|
||||
controller.appliance_manager.load_appliances() # make sure appliances are loaded
|
||||
image_path = "tests/resources/empty30G.qcow2"
|
||||
image_name = os.path.basename(image_path)
|
||||
with open(image_path, "rb") as f:
|
||||
image_data = f.read()
|
||||
response = await client.post(
|
||||
app.url_path_for("upload_image", image_path=image_name),
|
||||
params={"image_type": "qemu"},
|
||||
content=image_data)
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
|
||||
templates_repo = TemplatesRepository(db_session)
|
||||
templates = await templates_repo.get_templates()
|
||||
assert len(templates) == 1
|
||||
assert templates[0].name == "Empty VM"
|
||||
assert templates[0].version == "30G"
|
||||
@@ -62,6 +62,7 @@ class TestTemplateRoutes:
|
||||
template_id = str(uuid.uuid4())
|
||||
params = {"template_id": template_id,
|
||||
"name": "VPCS_TEST",
|
||||
"version": "1.0",
|
||||
"compute_id": "local",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
@@ -72,9 +73,25 @@ class TestTemplateRoutes:
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.json()["template_id"] == template_id
|
||||
|
||||
async def test_template_create_same_name_and_version(
|
||||
self,
|
||||
app: FastAPI,
|
||||
client: AsyncClient,
|
||||
controller: Controller
|
||||
) -> None:
|
||||
|
||||
params = {"name": "VPCS_TEST",
|
||||
"version": "1.0",
|
||||
"compute_id": "local",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
response = await client.post(app.url_path_for("create_template"), json=params)
|
||||
assert response.status_code == status.HTTP_409_CONFLICT
|
||||
|
||||
async def test_template_create_wrong_type(self, app: FastAPI, client: AsyncClient, controller: Controller) -> None:
|
||||
|
||||
params = {"name": "VPCS_TEST",
|
||||
"version": "2.0",
|
||||
"compute_id": "local",
|
||||
"template_type": "invalid_template_type"}
|
||||
|
||||
@@ -86,6 +103,7 @@ class TestTemplateRoutes:
|
||||
template_id = str(uuid.uuid4())
|
||||
params = {"template_id": template_id,
|
||||
"name": "VPCS_TEST",
|
||||
"version": "3.0",
|
||||
"compute_id": "local",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
@@ -107,6 +125,7 @@ class TestTemplateRoutes:
|
||||
template_id = str(uuid.uuid4())
|
||||
params = {"template_id": template_id,
|
||||
"name": "VPCS_TEST",
|
||||
"version": "4.0",
|
||||
"compute_id": "local",
|
||||
"template_type": "vpcs"}
|
||||
|
||||
@@ -426,7 +445,7 @@ class TestDynamipsTemplate:
|
||||
|
||||
async def test_c3600_dynamips_template_create_wrong_chassis(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
params = {"name": "Cisco c3600 template",
|
||||
params = {"name": "Cisco c3600 template with wrong chassis",
|
||||
"platform": "c3600",
|
||||
"chassis": "3650",
|
||||
"compute_id": "local",
|
||||
@@ -530,7 +549,7 @@ class TestDynamipsTemplate:
|
||||
|
||||
async def test_c2600_dynamips_template_create_wrong_chassis(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
params = {"name": "Cisco c2600 template",
|
||||
params = {"name": "Cisco c2600 template with wrong chassis",
|
||||
"platform": "c2600",
|
||||
"chassis": "2660XM",
|
||||
"compute_id": "local",
|
||||
@@ -589,7 +608,7 @@ class TestDynamipsTemplate:
|
||||
|
||||
async def test_c1700_dynamips_template_create_wrong_chassis(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
params = {"name": "Cisco c1700 template",
|
||||
params = {"name": "Cisco c1700 template with wrong chassis",
|
||||
"platform": "c1700",
|
||||
"chassis": "1770",
|
||||
"compute_id": "local",
|
||||
@@ -1200,6 +1219,7 @@ class TestImageAssociationWithTemplate:
|
||||
) -> None:
|
||||
|
||||
params = {"name": "Qemu template",
|
||||
"version": "1.0",
|
||||
"compute_id": "local",
|
||||
"platform": "i386",
|
||||
"hda_disk_image": "subdir/image.qcow2",
|
||||
@@ -1224,7 +1244,7 @@ class TestImageAssociationWithTemplate:
|
||||
|
||||
async def test_template_create_with_non_existing_image(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
params = {"name": "Qemu template",
|
||||
params = {"name": "Qemu template with non existing image",
|
||||
"compute_id": "local",
|
||||
"platform": "i386",
|
||||
"hda_disk_image": "unkown_image.qcow2",
|
||||
|
||||
Reference in new issue
Block a user