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

Add a custom version to an appliance

This commit is contained in:
grossmj 2021-10-19 15:15:10 +10:30
parent be473aaaf7
commit a31e5615a4
4 changed files with 63 additions and 8 deletions

View File

@ -26,7 +26,12 @@ from uuid import UUID
from gns3server import schemas
from gns3server.controller import Controller
from gns3server.controller.controller_error import ControllerNotFoundError
from gns3server.controller.controller_error import (
ControllerError,
ControllerBadRequestError,
ControllerNotFoundError
)
from gns3server.db.repositories.images import ImagesRepository
from gns3server.db.repositories.templates import TemplatesRepository
from gns3server.db.repositories.rbac import RbacRepository
@ -68,6 +73,31 @@ def get_appliance(appliance_id: UUID) -> schemas.Appliance:
return appliance.asdict()
@router.post("/{appliance_id}/version", status_code=status.HTTP_201_CREATED)
def add_appliance_version(appliance_id: UUID, appliance_version: schemas.ApplianceVersion) -> schemas.Appliance:
"""
Add a version to an appliance
"""
controller = Controller.instance()
appliance = controller.appliance_manager.appliances.get(str(appliance_id))
if not appliance:
raise ControllerNotFoundError(message=f"Could not find appliance '{appliance_id}'")
if not appliance.versions:
raise ControllerBadRequestError(message=f"Appliance '{appliance_id}' do not have versions")
if not appliance_version.images:
raise ControllerBadRequestError(message=f"Version '{appliance_version.name}' must contain images")
for version in appliance.versions:
if version.get("name") == appliance_version.name:
raise ControllerError(message=f"Appliance '{appliance_id}' already has version '{appliance_version.name}'")
appliance.versions.append(appliance_version.dict(exclude_unset=True))
return appliance.asdict()
@router.post("/{appliance_id}/install", status_code=status.HTTP_204_NO_CONTENT)
async def install_appliance(
appliance_id: UUID,

View File

@ -24,7 +24,7 @@ from .controller.links import LinkCreate, LinkUpdate, Link
from .controller.computes import ComputeCreate, ComputeUpdate, AutoIdlePC, Compute
from .controller.templates import TemplateCreate, TemplateUpdate, TemplateUsage, Template
from .controller.images import Image, ImageType
from .controller.appliances import Appliance
from .controller.appliances import ApplianceVersion, Appliance
from .controller.drawings import Drawing
from .controller.gns3vm import GNS3VM
from .controller.nodes import NodeCreate, NodeUpdate, NodeDuplicate, NodeCapture, Node

View File

@ -317,7 +317,7 @@ class Compression(Enum):
field_7z = '7z'
class Image(BaseModel):
class ApplianceImage(BaseModel):
filename: str = Field(..., title='Filename')
version: str = Field(..., title='Version of the file')
@ -335,7 +335,7 @@ class Image(BaseModel):
)
class Images(BaseModel):
class ApplianceVersionImages(BaseModel):
kernel_image: Optional[str] = Field(None, title='Kernel image')
initrd: Optional[str] = Field(None, title='Initrd disk image')
@ -348,11 +348,11 @@ class Images(BaseModel):
cdrom_image: Optional[str] = Field(None, title='cdrom image')
class Version(BaseModel):
class ApplianceVersion(BaseModel):
name: str = Field(..., title='Name of the version')
idlepc: Optional[str] = Field(None, regex='^0x[0-9a-f]{8}')
images: Optional[Images] = Field(None, title='Images used for this version')
images: Optional[ApplianceVersionImages] = Field(None, title='Images used for this version')
class DynamipsSlot(Enum):
@ -460,5 +460,5 @@ class Appliance(BaseModel):
iou: Optional[Iou] = Field(None, title='IOU specific options')
dynamips: Optional[Dynamips] = Field(None, title='Dynamips specific options')
qemu: Optional[Qemu] = Field(None, title='Qemu specific options')
images: Optional[List[Image]] = Field(None, title='Images for this appliance')
versions: Optional[List[Version]] = Field(None, title='Versions of the appliance')
images: Optional[List[ApplianceImage]] = Field(None, title='Images for this appliance')
versions: Optional[List[ApplianceVersion]] = Field(None, title='Versions of the appliance')

View File

@ -66,3 +66,28 @@ class TestApplianceRoutes:
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
async def test_add_version_appliance(self, app: FastAPI, client: AsyncClient) -> None:
appliance_id = "1cfdf900-7c30-4cb7-8f03-3f61d2581633" # Empty VM appliance
new_version = {
"name": "99G",
"images": {
"hda_disk_image": "empty99G.qcow2"
}
}
response = await client.post(app.url_path_for("add_appliance_version", appliance_id=appliance_id), json=new_version)
assert response.status_code == status.HTTP_201_CREATED
assert new_version in response.json()["versions"]
async def test_add_existing_version_appliance(self, app: FastAPI, client: AsyncClient) -> None:
appliance_id = "1cfdf900-7c30-4cb7-8f03-3f61d2581633" # Empty VM appliance
new_version = {
"name": "8G",
"images": {
"hda_disk_image": "empty8G.qcow2"
}
}
response = await client.post(app.url_path_for("add_appliance_version", appliance_id=appliance_id), json=new_version)
assert response.status_code == status.HTTP_409_CONFLICT