mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-25 16:28:11 +00:00
Fix issue when updating a template
This commit is contained in:
parent
45738f262b
commit
7ce5e19a6e
@ -37,24 +37,31 @@ from .controller.iou_license import IOULicense
|
||||
from .controller.capabilities import Capabilities
|
||||
|
||||
# Controller template schemas
|
||||
from .controller.templates.vpcs_templates import VPCSTemplate
|
||||
from .controller.templates.cloud_templates import CloudTemplate
|
||||
from .controller.templates.iou_templates import IOUTemplate
|
||||
from .controller.templates.docker_templates import DockerTemplate
|
||||
from .controller.templates.ethernet_hub_templates import EthernetHubTemplate
|
||||
from .controller.templates.ethernet_switch_templates import EthernetSwitchTemplate
|
||||
from .controller.templates.virtualbox_templates import VirtualBoxTemplate
|
||||
from .controller.templates.vmware_templates import VMwareTemplate
|
||||
from .controller.templates.qemu_templates import QemuTemplate
|
||||
from .controller.templates.vpcs_templates import VPCSTemplate, VPCSTemplateUpdate
|
||||
from .controller.templates.cloud_templates import CloudTemplate, CloudTemplateUpdate
|
||||
from .controller.templates.iou_templates import IOUTemplate, IOUTemplateUpdate
|
||||
from .controller.templates.docker_templates import DockerTemplate, DockerTemplateUpdate
|
||||
from .controller.templates.ethernet_hub_templates import EthernetHubTemplate, EthernetHubTemplateUpdate
|
||||
from .controller.templates.ethernet_switch_templates import EthernetSwitchTemplate, EthernetSwitchTemplateUpdate
|
||||
from .controller.templates.virtualbox_templates import VirtualBoxTemplate, VirtualBoxTemplateUpdate
|
||||
from .controller.templates.vmware_templates import VMwareTemplate, VMwareTemplateUpdate
|
||||
from .controller.templates.qemu_templates import QemuTemplate, QemuTemplateUpdate
|
||||
from .controller.templates.dynamips_templates import (
|
||||
DynamipsTemplate,
|
||||
C1700DynamipsTemplate,
|
||||
C1700DynamipsTemplateUpdate,
|
||||
C2600DynamipsTemplate,
|
||||
C2600DynamipsTemplateUpdate,
|
||||
C2691DynamipsTemplate,
|
||||
C2691DynamipsTemplateUpdate,
|
||||
C3600DynamipsTemplate,
|
||||
C3600DynamipsTemplateUpdate,
|
||||
C3725DynamipsTemplate,
|
||||
C3725DynamipsTemplateUpdate,
|
||||
C3745DynamipsTemplate,
|
||||
C3745DynamipsTemplateUpdate,
|
||||
C7200DynamipsTemplate,
|
||||
C7200DynamipsTemplateUpdate
|
||||
)
|
||||
|
||||
# Compute schemas
|
||||
|
@ -50,9 +50,6 @@ class TemplateBase(BaseModel):
|
||||
compute_id: Optional[str] = None
|
||||
usage: Optional[str] = ""
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class TemplateCreate(TemplateBase):
|
||||
"""
|
||||
@ -63,10 +60,14 @@ class TemplateCreate(TemplateBase):
|
||||
template_type: NodeType
|
||||
compute_id: str
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class TemplateUpdate(TemplateBase):
|
||||
|
||||
pass
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
class Template(DateTimeModelMixin, TemplateBase):
|
||||
@ -80,6 +81,7 @@ class Template(DateTimeModelMixin, TemplateBase):
|
||||
compute_id: Union[str, None]
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
orm_mode = True
|
||||
|
||||
|
||||
|
@ -37,3 +37,8 @@ class CloudTemplate(TemplateBase):
|
||||
remote_console_port: Optional[int] = Field(23, gt=0, le=65535, description="Remote console TCP port")
|
||||
remote_console_type: Optional[CloudConsoleType] = Field("none", description="Remote console type")
|
||||
remote_console_http_path: Optional[str] = Field("/", description="Path of the remote web interface")
|
||||
|
||||
|
||||
class CloudTemplateUpdate(CloudTemplate):
|
||||
|
||||
pass
|
||||
|
@ -51,3 +51,8 @@ class DockerTemplate(TemplateBase):
|
||||
memory: Optional[int] = Field(0, description="Maximum amount of memory the container can use in MB")
|
||||
cpus: Optional[int] = Field(0, description="Maximum amount of CPU resources the container can use")
|
||||
custom_adapters: Optional[List[CustomAdapter]] = Field(default_factory=list, description="Custom adapters")
|
||||
|
||||
|
||||
class DockerTemplateUpdate(DockerTemplate):
|
||||
|
||||
image: Optional[str] = Field(None, description="Docker image name")
|
@ -77,6 +77,12 @@ class C7200DynamipsTemplate(DynamipsTemplate):
|
||||
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||
|
||||
|
||||
class C7200DynamipsTemplateUpdate(C7200DynamipsTemplate):
|
||||
|
||||
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
|
||||
image: Optional[str] = Field(None, description="Path to the IOS image")
|
||||
|
||||
|
||||
class C3725DynamipsTemplate(DynamipsTemplate):
|
||||
|
||||
ram: Optional[int] = Field(128, description="Amount of RAM in MB")
|
||||
@ -85,6 +91,12 @@ class C3725DynamipsTemplate(DynamipsTemplate):
|
||||
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||
|
||||
|
||||
class C3725DynamipsTemplateUpdate(C3725DynamipsTemplate):
|
||||
|
||||
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
|
||||
image: Optional[str] = Field(None, description="Path to the IOS image")
|
||||
|
||||
|
||||
class C3745DynamipsTemplate(DynamipsTemplate):
|
||||
|
||||
ram: Optional[int] = Field(256, description="Amount of RAM in MB")
|
||||
@ -93,6 +105,12 @@ class C3745DynamipsTemplate(DynamipsTemplate):
|
||||
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||
|
||||
|
||||
class C3745DynamipsTemplateUpdate(C3745DynamipsTemplate):
|
||||
|
||||
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
|
||||
image: Optional[str] = Field(None, description="Path to the IOS image")
|
||||
|
||||
|
||||
class C3600ChassisType(str, Enum):
|
||||
|
||||
chassis_3620 = "3620"
|
||||
@ -109,6 +127,12 @@ class C3600DynamipsTemplate(DynamipsTemplate):
|
||||
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||
|
||||
|
||||
class C3600DynamipsTemplateUpdate(C3600DynamipsTemplate):
|
||||
|
||||
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
|
||||
image: Optional[str] = Field(None, description="Path to the IOS image")
|
||||
|
||||
|
||||
class C2691DynamipsTemplate(DynamipsTemplate):
|
||||
|
||||
ram: Optional[int] = Field(192, description="Amount of RAM in MB")
|
||||
@ -117,6 +141,12 @@ class C2691DynamipsTemplate(DynamipsTemplate):
|
||||
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||
|
||||
|
||||
class C2691DynamipsTemplateUpdate(C2691DynamipsTemplate):
|
||||
|
||||
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
|
||||
image: Optional[str] = Field(None, description="Path to the IOS image")
|
||||
|
||||
|
||||
class C2600ChassisType(str, Enum):
|
||||
|
||||
chassis_2610 = "2610"
|
||||
@ -139,6 +169,12 @@ class C2600DynamipsTemplate(DynamipsTemplate):
|
||||
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||
|
||||
|
||||
class C2600DynamipsTemplateUpdate(C2600DynamipsTemplate):
|
||||
|
||||
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
|
||||
image: Optional[str] = Field(None, description="Path to the IOS image")
|
||||
|
||||
|
||||
class C1700ChassisType(str, Enum):
|
||||
|
||||
chassis_1720 = "1720"
|
||||
@ -155,3 +191,9 @@ class C1700DynamipsTemplate(DynamipsTemplate):
|
||||
nvram: Optional[int] = Field(128, description="Amount of NVRAM in KB")
|
||||
iomem: Optional[int] = Field(15, ge=0, le=100, description="I/O memory percentage")
|
||||
sparsemem: Optional[bool] = Field(False, description="Sparse memory feature")
|
||||
|
||||
|
||||
class C1700DynamipsTemplateUpdate(C1700DynamipsTemplate):
|
||||
|
||||
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
|
||||
image: Optional[str] = Field(None, description="Path to the IOS image")
|
||||
|
@ -39,3 +39,8 @@ class EthernetHubTemplate(TemplateBase):
|
||||
default_name_format: Optional[str] = "Hub{0}"
|
||||
symbol: Optional[str] = ":/symbols/hub.svg"
|
||||
ports_mapping: Optional[List[EthernetHubPort]] = Field(DEFAULT_PORTS, description="Ports")
|
||||
|
||||
|
||||
class EthernetHubTemplateUpdate(EthernetHubTemplate):
|
||||
|
||||
pass
|
||||
|
@ -50,3 +50,8 @@ class EthernetSwitchTemplate(TemplateBase):
|
||||
symbol: Optional[str] = ":/symbols/ethernet_switch.svg"
|
||||
ports_mapping: Optional[List[EthernetSwitchPort]] = Field(DEFAULT_PORTS, description="Ports")
|
||||
console_type: Optional[ConsoleType] = Field("none", description="Console type")
|
||||
|
||||
|
||||
class EthernetSwitchTemplateUpdate(EthernetSwitchTemplate):
|
||||
|
||||
pass
|
||||
|
@ -40,3 +40,8 @@ class IOUTemplate(TemplateBase):
|
||||
console_auto_start: Optional[bool] = Field(
|
||||
False, description="Automatically start the console when the node has started"
|
||||
)
|
||||
|
||||
|
||||
class IOUTemplateUpdate(IOUTemplate):
|
||||
|
||||
path: Optional[str] = Field(None, description="Path of IOU executable")
|
||||
|
@ -85,3 +85,8 @@ class QemuTemplate(TemplateBase):
|
||||
process_priority: Optional[QemuProcessPriority] = Field("normal", description="Process priority for QEMU")
|
||||
options: Optional[str] = Field("", description="Additional QEMU options")
|
||||
custom_adapters: Optional[List[CustomAdapter]] = Field(default_factory=list, description="Custom adapters")
|
||||
|
||||
|
||||
class QemuTemplateUpdate(QemuTemplate):
|
||||
|
||||
pass
|
||||
|
@ -58,3 +58,8 @@ class VirtualBoxTemplate(TemplateBase):
|
||||
False, description="Automatically start the console when the node has started"
|
||||
)
|
||||
custom_adapters: Optional[List[CustomAdapter]] = Field(default_factory=list, description="Custom adapters")
|
||||
|
||||
|
||||
class VirtualBoxTemplateUpdate(VirtualBoxTemplate):
|
||||
|
||||
vmname: Optional[str] = Field(None, description="VirtualBox VM name (in VirtualBox itself)")
|
||||
|
@ -54,3 +54,8 @@ class VMwareTemplate(TemplateBase):
|
||||
False, description="Automatically start the console when the node has started"
|
||||
)
|
||||
custom_adapters: Optional[List[CustomAdapter]] = Field(default_factory=list, description="Custom adapters")
|
||||
|
||||
|
||||
class VMwareTemplateUpdate(VMwareTemplate):
|
||||
|
||||
vmx_path: Optional[str] = Field(None, description="Path to the vmx file")
|
||||
|
@ -32,3 +32,8 @@ class VPCSTemplate(TemplateBase):
|
||||
console_auto_start: Optional[bool] = Field(
|
||||
False, description="Automatically start the console when the node has started"
|
||||
)
|
||||
|
||||
|
||||
class VPCSTemplateUpdate(VPCSTemplate):
|
||||
|
||||
pass
|
||||
|
@ -32,7 +32,7 @@ from gns3server.controller.controller_error import (
|
||||
ControllerForbiddenError,
|
||||
)
|
||||
|
||||
TEMPLATE_TYPE_TO_SHEMA = {
|
||||
TEMPLATE_TYPE_TO_SCHEMA = {
|
||||
"cloud": schemas.CloudTemplate,
|
||||
"ethernet_hub": schemas.EthernetHubTemplate,
|
||||
"ethernet_switch": schemas.EthernetSwitchTemplate,
|
||||
@ -45,7 +45,19 @@ TEMPLATE_TYPE_TO_SHEMA = {
|
||||
"qemu": schemas.QemuTemplate,
|
||||
}
|
||||
|
||||
DYNAMIPS_PLATFORM_TO_SHEMA = {
|
||||
TEMPLATE_TYPE_TO_UPDATE_SCHEMA = {
|
||||
"cloud": schemas.CloudTemplateUpdate,
|
||||
"ethernet_hub": schemas.EthernetHubTemplateUpdate,
|
||||
"ethernet_switch": schemas.EthernetSwitchTemplateUpdate,
|
||||
"docker": schemas.DockerTemplateUpdate,
|
||||
"vpcs": schemas.VPCSTemplateUpdate,
|
||||
"virtualbox": schemas.VirtualBoxTemplateUpdate,
|
||||
"vmware": schemas.VMwareTemplateUpdate,
|
||||
"iou": schemas.IOUTemplateUpdate,
|
||||
"qemu": schemas.QemuTemplateUpdate,
|
||||
}
|
||||
|
||||
DYNAMIPS_PLATFORM_TO_SCHEMA = {
|
||||
"c7200": schemas.C7200DynamipsTemplate,
|
||||
"c3745": schemas.C3745DynamipsTemplate,
|
||||
"c3725": schemas.C3725DynamipsTemplate,
|
||||
@ -55,6 +67,16 @@ DYNAMIPS_PLATFORM_TO_SHEMA = {
|
||||
"c1700": schemas.C1700DynamipsTemplate,
|
||||
}
|
||||
|
||||
DYNAMIPS_PLATFORM_TO_UPDATE_SCHEMA = {
|
||||
"c7200": schemas.C7200DynamipsTemplateUpdate,
|
||||
"c3745": schemas.C3745DynamipsTemplateUpdate,
|
||||
"c3725": schemas.C3725DynamipsTemplateUpdate,
|
||||
"c3600": schemas.C3600DynamipsTemplateUpdate,
|
||||
"c2691": schemas.C2691DynamipsTemplateUpdate,
|
||||
"c2600": schemas.C2600DynamipsTemplateUpdate,
|
||||
"c1700": schemas.C1700DynamipsTemplateUpdate,
|
||||
}
|
||||
|
||||
# built-in templates have their compute_id set to None to tell clients to select a compute
|
||||
BUILTIN_TEMPLATES = [
|
||||
{
|
||||
@ -205,20 +227,18 @@ class TemplatesService:
|
||||
|
||||
try:
|
||||
# get the default template settings
|
||||
template_settings = jsonable_encoder(template_create, exclude_unset=True)
|
||||
template_schema = TEMPLATE_TYPE_TO_SHEMA[template_create.template_type]
|
||||
template_settings_with_defaults = template_schema.parse_obj(template_settings)
|
||||
settings = template_settings_with_defaults.dict()
|
||||
create_settings = jsonable_encoder(template_create, exclude_unset=True)
|
||||
template_schema = TEMPLATE_TYPE_TO_SCHEMA[template_create.template_type]
|
||||
template_settings = template_schema.parse_obj(create_settings).dict()
|
||||
if template_create.template_type == "dynamips":
|
||||
# special case for Dynamips to cover all platform types that contain specific settings
|
||||
dynamips_template_schema = DYNAMIPS_PLATFORM_TO_SHEMA[settings["platform"]]
|
||||
dynamips_template_settings_with_defaults = dynamips_template_schema.parse_obj(template_settings)
|
||||
settings = dynamips_template_settings_with_defaults.dict()
|
||||
dynamips_template_schema = DYNAMIPS_PLATFORM_TO_SCHEMA[template_settings["platform"]]
|
||||
template_settings = dynamips_template_schema.parse_obj(create_settings).dict()
|
||||
except pydantic.ValidationError as e:
|
||||
raise ControllerBadRequestError(f"JSON schema error received while creating new template: {e}")
|
||||
|
||||
images_to_add_to_template = await self._find_images(template_create.template_type, settings)
|
||||
db_template = await self._templates_repo.create_template(template_create.template_type, settings)
|
||||
images_to_add_to_template = await self._find_images(template_create.template_type, template_settings)
|
||||
db_template = await self._templates_repo.create_template(template_create.template_type, template_settings)
|
||||
for image in images_to_add_to_template:
|
||||
await self._templates_repo.add_image_to_template(db_template.template_id, image)
|
||||
template = db_template.asjson()
|
||||
@ -245,12 +265,22 @@ class TemplatesService:
|
||||
|
||||
if self.get_builtin_template(template_id):
|
||||
raise ControllerForbiddenError(f"Template '{template_id}' cannot be updated because it is built-in")
|
||||
template_settings = jsonable_encoder(template_update, exclude_unset=True)
|
||||
|
||||
db_template = await self._templates_repo.get_template(template_id)
|
||||
if not db_template:
|
||||
raise ControllerNotFoundError(f"Template '{template_id}' not found")
|
||||
|
||||
try:
|
||||
# validate the update settings
|
||||
update_settings = jsonable_encoder(template_update, exclude_unset=True)
|
||||
if db_template.template_type == "dynamips":
|
||||
template_schema = DYNAMIPS_PLATFORM_TO_UPDATE_SCHEMA[db_template.platform]
|
||||
else:
|
||||
template_schema = TEMPLATE_TYPE_TO_UPDATE_SCHEMA[db_template.template_type]
|
||||
template_settings = template_schema.parse_obj(update_settings).dict(exclude_unset=True)
|
||||
except pydantic.ValidationError as e:
|
||||
raise ControllerBadRequestError(f"JSON schema error received while updating template: {e}")
|
||||
|
||||
images_to_add_to_template = await self._find_images(db_template.template_type, template_settings)
|
||||
if db_template.template_type == "dynamips" and "image" in template_settings:
|
||||
await self._remove_image(db_template.template_id, db_template.image)
|
||||
|
Loading…
Reference in New Issue
Block a user