mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-26 16:58:28 +00:00
Use pydantic for data validation (instead of jsonschema)
Fix/improve various pydantic shema models.
This commit is contained in:
parent
d6a65883ee
commit
81439c750a
36
gns3server/controller/schemas/__init__.py
Normal file
36
gns3server/controller/schemas/__init__.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .vpcs_templates import VPCSTemplate
|
||||||
|
from .cloud_templates import CloudTemplate
|
||||||
|
from .iou_templates import IOUTemplate
|
||||||
|
from .docker_templates import DockerTemplate
|
||||||
|
from .ethernet_hub_templates import EthernetHubTemplate
|
||||||
|
from .ethernet_switch_templates import EthernetSwitchTemplate
|
||||||
|
from .virtualbox_templates import VirtualBoxTemplate
|
||||||
|
from .vmware_templates import VMwareTemplate
|
||||||
|
from .qemu_templates import QemuTemplate
|
||||||
|
from .dynamips_templates import (
|
||||||
|
DynamipsTemplate,
|
||||||
|
C1700DynamipsTemplate,
|
||||||
|
C2600DynamipsTemplate,
|
||||||
|
C2691DynamipsTemplate,
|
||||||
|
C3600DynamipsTemplate,
|
||||||
|
C3725DynamipsTemplate,
|
||||||
|
C3745DynamipsTemplate,
|
||||||
|
C7200DynamipsTemplate
|
||||||
|
)
|
@ -16,30 +16,14 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from .templates import Category, TemplateBase
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
from .cloud_nodes import EthernetPort, TAPPort, UDPPort
|
from gns3server.endpoints.schemas.cloud_nodes import EthernetPort, TAPPort, UDPPort, CloudConsoleType
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from typing import Optional, Union, List
|
from typing import Optional, Union, List
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
from .nodes import NodeType
|
|
||||||
|
|
||||||
|
|
||||||
class RemoteConsoleType(str, Enum):
|
class CloudTemplate(TemplateBase):
|
||||||
"""
|
|
||||||
Supported remote console types for cloud nodes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
none = "none"
|
|
||||||
telnet = "telnet"
|
|
||||||
vnc = "vnc"
|
|
||||||
spice = "spice"
|
|
||||||
http = "http"
|
|
||||||
https = "https"
|
|
||||||
|
|
||||||
|
|
||||||
class CloudTemplateBase(TemplateBase):
|
|
||||||
|
|
||||||
category: Optional[Category] = "guest"
|
category: Optional[Category] = "guest"
|
||||||
default_name_format: Optional[str] = "Cloud{0}"
|
default_name_format: Optional[str] = "Cloud{0}"
|
||||||
@ -47,28 +31,5 @@ class CloudTemplateBase(TemplateBase):
|
|||||||
ports_mapping: List[Union[EthernetPort, TAPPort, UDPPort]] = []
|
ports_mapping: List[Union[EthernetPort, TAPPort, UDPPort]] = []
|
||||||
remote_console_host: Optional[str] = Field("127.0.0.1", description="Remote console host or IP")
|
remote_console_host: Optional[str] = Field("127.0.0.1", description="Remote console host or IP")
|
||||||
remote_console_port: Optional[int] = Field(23, gt=0, le=65535, description="Remote console TCP port")
|
remote_console_port: Optional[int] = Field(23, gt=0, le=65535, description="Remote console TCP port")
|
||||||
remote_console_type: Optional[RemoteConsoleType] = Field("none", description="Remote console type")
|
remote_console_type: Optional[CloudConsoleType] = Field("none", description="Remote console type")
|
||||||
remote_console_path: Optional[str] = Field("/", description="Path of the remote web interface")
|
remote_console_http_path: Optional[str] = Field("/", description="Path of the remote web interface")
|
||||||
|
|
||||||
|
|
||||||
class CloudTemplateCreate(CloudTemplateBase):
|
|
||||||
|
|
||||||
name: str
|
|
||||||
template_type: NodeType
|
|
||||||
compute_id: str
|
|
||||||
|
|
||||||
|
|
||||||
class CloudTemplateUpdate(CloudTemplateBase):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class CloudTemplate(CloudTemplateBase):
|
|
||||||
|
|
||||||
template_id: str
|
|
||||||
name: str
|
|
||||||
category: Category
|
|
||||||
symbol: str
|
|
||||||
builtin: bool
|
|
||||||
template_type: NodeType
|
|
||||||
compute_id: Union[str, None]
|
|
46
gns3server/controller/schemas/docker_templates.py
Normal file
46
gns3server/controller/schemas/docker_templates.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.nodes import CustomAdapter
|
||||||
|
from gns3server.endpoints.schemas.docker_nodes import ConsoleType, AuxType
|
||||||
|
|
||||||
|
from pydantic import Field
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
class DockerTemplate(TemplateBase):
|
||||||
|
|
||||||
|
category: Optional[Category] = "guest"
|
||||||
|
default_name_format: Optional[str] = "{name}-{0}"
|
||||||
|
symbol: Optional[str] = ":/symbols/docker_guest.svg"
|
||||||
|
image: str = Field(..., description="Docker image name")
|
||||||
|
adapters: Optional[int] = Field(1, ge=0, le=100, description="Number of adapters")
|
||||||
|
start_command: Optional[str] = Field("", description="Docker CMD entry")
|
||||||
|
environment: Optional[str] = Field("", description="Docker environment variables")
|
||||||
|
console_type: Optional[ConsoleType] = Field("telnet", description="Console type")
|
||||||
|
aux_type: Optional[AuxType] = Field("none", description="Auxiliary console type")
|
||||||
|
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
||||||
|
console_http_port: Optional[int] = Field(80, gt=0, le=65535, description="Internal port in the container for the HTTP server")
|
||||||
|
console_http_path: Optional[str] = Field("/", description="Path of the web interface",)
|
||||||
|
console_resolution: Optional[str] = Field("1024x768", regex="^[0-9]+x[0-9]+$", description="Console resolution for VNC")
|
||||||
|
extra_hosts: Optional[str] = Field("", description="Docker extra hosts (added to /etc/hosts)")
|
||||||
|
extra_volumes: Optional[List] = Field([], description="Additional directories to make persistent")
|
||||||
|
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([], description="Custom adapters")
|
154
gns3server/controller/schemas/dynamips_templates.py
Normal file
154
gns3server/controller/schemas/dynamips_templates.py
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.dynamips_nodes import (
|
||||||
|
DynamipsConsoleType,
|
||||||
|
DynamipsPlatform,
|
||||||
|
DynamipsAdapters,
|
||||||
|
DynamipsWics,
|
||||||
|
DynamipsNPE,
|
||||||
|
DynamipsMidplane
|
||||||
|
)
|
||||||
|
|
||||||
|
from pydantic import Field
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class DynamipsTemplate(TemplateBase):
|
||||||
|
|
||||||
|
category: Optional[Category] = "router"
|
||||||
|
default_name_format: Optional[str] = "R{0}"
|
||||||
|
symbol: Optional[str] = ":/symbols/router.svg"
|
||||||
|
platform: DynamipsPlatform = Field(..., description="Cisco router platform")
|
||||||
|
image: Path = Field(..., description="Path to the IOS image")
|
||||||
|
exec_area: Optional[int] = Field(64, description="Exec area value")
|
||||||
|
mmap: Optional[bool] = Field(True, description="MMAP feature")
|
||||||
|
mac_addr: Optional[str] = Field("", description="Base MAC address", regex="^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$|^$")
|
||||||
|
system_id: Optional[str] = Field("FTX0945W0MY", description="System ID")
|
||||||
|
startup_config: Optional[str] = Field("ios_base_startup-config.txt", description="IOS startup configuration file")
|
||||||
|
private_config: Optional[str] = Field("", description="IOS private configuration file")
|
||||||
|
idlepc: Optional[str] = Field("", description="Idle-PC value", regex="^(0x[0-9a-fA-F]+)?$|^$")
|
||||||
|
idlemax: Optional[int] = Field(500, description="Idlemax value")
|
||||||
|
idlesleep: Optional[int] = Field(30, description="Idlesleep value")
|
||||||
|
disk0: Optional[int] = Field(0, description="Disk0 size in MB")
|
||||||
|
disk1: Optional[int] = Field(0, description="Disk1 size in MB")
|
||||||
|
auto_delete_disks: Optional[bool] = Field(False, description="Automatically delete nvram and disk files")
|
||||||
|
console_type: Optional[DynamipsConsoleType] = Field("telnet", description="Console type")
|
||||||
|
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
||||||
|
aux_type: Optional[DynamipsConsoleType] = Field("none", description="Auxiliary console type")
|
||||||
|
slot0: Optional[DynamipsAdapters] = Field(None, description="Network module slot 0")
|
||||||
|
slot1: Optional[DynamipsAdapters] = Field(None, description="Network module slot 1")
|
||||||
|
slot2: Optional[DynamipsAdapters] = Field(None, description="Network module slot 2")
|
||||||
|
slot3: Optional[DynamipsAdapters] = Field(None, description="Network module slot 3")
|
||||||
|
slot4: Optional[DynamipsAdapters] = Field(None, description="Network module slot 4")
|
||||||
|
slot5: Optional[DynamipsAdapters] = Field(None, description="Network module slot 5")
|
||||||
|
slot6: Optional[DynamipsAdapters] = Field(None, description="Network module slot 6")
|
||||||
|
wic0: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 0")
|
||||||
|
wic1: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 1")
|
||||||
|
wic2: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 2")
|
||||||
|
|
||||||
|
|
||||||
|
class C7200DynamipsTemplate(DynamipsTemplate):
|
||||||
|
|
||||||
|
ram: Optional[int] = Field(512, description="Amount of RAM in MB")
|
||||||
|
nvram: Optional[int] = Field(512, description="Amount of NVRAM in KB")
|
||||||
|
npe: Optional[DynamipsNPE] = Field("npe-400", description="NPE model")
|
||||||
|
midplane: Optional[DynamipsMidplane] = Field("vxr", description="Midplane model")
|
||||||
|
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||||
|
|
||||||
|
|
||||||
|
class C3725DynamipsTemplate(DynamipsTemplate):
|
||||||
|
|
||||||
|
ram: Optional[int] = Field(128, description="Amount of RAM in MB")
|
||||||
|
nvram: Optional[int] = Field(256, description="Amount of NVRAM in KB")
|
||||||
|
iomem: Optional[int] = Field(5, ge=0, le=100, description="I/O memory percentage")
|
||||||
|
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||||
|
|
||||||
|
|
||||||
|
class C3745DynamipsTemplate(DynamipsTemplate):
|
||||||
|
|
||||||
|
ram: Optional[int] = Field(256, description="Amount of RAM in MB")
|
||||||
|
nvram: Optional[int] = Field(256, description="Amount of NVRAM in KB")
|
||||||
|
iomem: Optional[int] = Field(5, ge=0, le=100, description="I/O memory percentage")
|
||||||
|
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||||
|
|
||||||
|
|
||||||
|
class C3600ChassisType(str, Enum):
|
||||||
|
|
||||||
|
chassis_3620 = "3620"
|
||||||
|
chassis_3640 = "3640"
|
||||||
|
chassis_3660 = "3660"
|
||||||
|
|
||||||
|
|
||||||
|
class C3600DynamipsTemplate(DynamipsTemplate):
|
||||||
|
|
||||||
|
chassis: Optional[C3600ChassisType] = Field("c3660", description="Chassis type")
|
||||||
|
ram: Optional[int] = Field(192, description="Amount of RAM in MB")
|
||||||
|
nvram: Optional[int] = Field(128, description="Amount of NVRAM in KB")
|
||||||
|
iomem: Optional[int] = Field(5, ge=0, le=100, description="I/O memory percentage")
|
||||||
|
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||||
|
|
||||||
|
|
||||||
|
class C2691DynamipsTemplate(DynamipsTemplate):
|
||||||
|
|
||||||
|
ram: Optional[int] = Field(192, description="Amount of RAM in MB")
|
||||||
|
nvram: Optional[int] = Field(256, description="Amount of NVRAM in KB")
|
||||||
|
iomem: Optional[int] = Field(5, ge=0, le=100, description="I/O memory percentage")
|
||||||
|
sparsemem: Optional[bool] = Field(True, description="Sparse memory feature")
|
||||||
|
|
||||||
|
|
||||||
|
class C2600ChassisType(str, Enum):
|
||||||
|
|
||||||
|
chassis_2610 = "2610"
|
||||||
|
chassis_2620 = "2620"
|
||||||
|
chassis_2610xm = "2610XM"
|
||||||
|
chassis_2620xm = "2620XM"
|
||||||
|
chassis_2650xm = "2650XM"
|
||||||
|
chassis_2621 = "2621"
|
||||||
|
chassis_2611xm = "2611XM"
|
||||||
|
chassis_2621xm = "2621XM"
|
||||||
|
chassis_2651xm = "2651XM"
|
||||||
|
|
||||||
|
|
||||||
|
class C2600DynamipsTemplate(DynamipsTemplate):
|
||||||
|
|
||||||
|
chassis: Optional[C2600ChassisType] = Field("2651XM", description="Chassis type")
|
||||||
|
ram: Optional[int] = Field(160, description="Amount of RAM in MB")
|
||||||
|
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(True, description="Sparse memory feature")
|
||||||
|
|
||||||
|
|
||||||
|
class C1700ChassisType(str, Enum):
|
||||||
|
|
||||||
|
chassis_1720 = "1720"
|
||||||
|
chassis_1721 = "1721"
|
||||||
|
chassis_1750 = "1750"
|
||||||
|
chassis_1751 = "1751"
|
||||||
|
chassis_1760 = "1760"
|
||||||
|
|
||||||
|
|
||||||
|
class C1700DynamipsTemplate(DynamipsTemplate):
|
||||||
|
|
||||||
|
chassis: Optional[C1700ChassisType] = Field("1760", description="Chassis type")
|
||||||
|
ram: Optional[int] = Field(160, description="Amount of RAM in MB")
|
||||||
|
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")
|
43
gns3server/controller/schemas/ethernet_hub_templates.py
Normal file
43
gns3server/controller/schemas/ethernet_hub_templates.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.ethernet_hub_nodes import EthernetHubPort
|
||||||
|
|
||||||
|
from pydantic import Field
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_PORTS = [
|
||||||
|
dict(port_number=0, name="Ethernet0"),
|
||||||
|
dict(port_number=1, name="Ethernet1"),
|
||||||
|
dict(port_number=2, name="Ethernet2"),
|
||||||
|
dict(port_number=3, name="Ethernet3"),
|
||||||
|
dict(port_number=4, name="Ethernet4"),
|
||||||
|
dict(port_number=5, name="Ethernet5"),
|
||||||
|
dict(port_number=6, name="Ethernet6"),
|
||||||
|
dict(port_number=7, name="Ethernet7")
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class EthernetHubTemplate(TemplateBase):
|
||||||
|
|
||||||
|
category: Optional[Category] = "switch"
|
||||||
|
default_name_format: Optional[str] = "Hub{0}"
|
||||||
|
symbol: Optional[str] = ":/symbols/hub.svg"
|
||||||
|
ports_mapping: Optional[List[EthernetHubPort]] = Field(DEFAULT_PORTS, description="Ports")
|
53
gns3server/controller/schemas/ethernet_switch_templates.py
Normal file
53
gns3server/controller/schemas/ethernet_switch_templates.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.ethernet_switch_nodes import EthernetSwitchPort
|
||||||
|
|
||||||
|
from pydantic import Field
|
||||||
|
from typing import Optional, List
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
DEFAULT_PORTS = [
|
||||||
|
dict(port_number=0, name="Ethernet0", vlan=1, type="access", ethertype=""),
|
||||||
|
dict(port_number=1, name="Ethernet1", vlan=1, type="access", ethertype=""),
|
||||||
|
dict(port_number=2, name="Ethernet2", vlan=1, type="access", ethertype=""),
|
||||||
|
dict(port_number=3, name="Ethernet3", vlan=1, type="access", ethertype=""),
|
||||||
|
dict(port_number=4, name="Ethernet4", vlan=1, type="access", ethertype=""),
|
||||||
|
dict(port_number=5, name="Ethernet5", vlan=1, type="access", ethertype=""),
|
||||||
|
dict(port_number=6, name="Ethernet6", vlan=1, type="access", ethertype=""),
|
||||||
|
dict(port_number=7, name="Ethernet7", vlan=1, type="access", ethertype="")
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ConsoleType(str, Enum):
|
||||||
|
"""
|
||||||
|
Supported console types for Ethernet switch nodes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
none = "none"
|
||||||
|
telnet = "telnet"
|
||||||
|
|
||||||
|
|
||||||
|
class EthernetSwitchTemplate(TemplateBase):
|
||||||
|
|
||||||
|
category: Optional[Category] = "switch"
|
||||||
|
default_name_format: Optional[str] = "Switch{0}"
|
||||||
|
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")
|
@ -16,31 +16,19 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from .templates import Category, TemplateBase
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.iou_nodes import ConsoleType
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Union
|
from typing import Optional
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
from .nodes import NodeType
|
|
||||||
|
|
||||||
|
|
||||||
class ConsoleType(str, Enum):
|
class IOUTemplate(TemplateBase):
|
||||||
"""
|
|
||||||
Supported console types for IOU nodes
|
|
||||||
"""
|
|
||||||
|
|
||||||
none = "none"
|
|
||||||
telnet = "telnet"
|
|
||||||
|
|
||||||
|
|
||||||
class IOUTemplateBase(TemplateBase):
|
|
||||||
|
|
||||||
category: Optional[Category] = "router"
|
category: Optional[Category] = "router"
|
||||||
default_name_format: Optional[str] = "IOU{0}"
|
default_name_format: Optional[str] = "IOU{0}"
|
||||||
symbol: Optional[str] = ":/symbols/multilayer_switch.svg"
|
symbol: Optional[str] = ":/symbols/multilayer_switch.svg"
|
||||||
|
|
||||||
path: Path = Field(..., description="Path of IOU executable")
|
path: Path = Field(..., description="Path of IOU executable")
|
||||||
ethernet_adapters: Optional[int] = Field(2, description="Number of ethernet adapters")
|
ethernet_adapters: Optional[int] = Field(2, description="Number of ethernet adapters")
|
||||||
serial_adapters: Optional[int] = Field(2, description="Number of serial adapters")
|
serial_adapters: Optional[int] = Field(2, description="Number of serial adapters")
|
||||||
@ -53,25 +41,3 @@ class IOUTemplateBase(TemplateBase):
|
|||||||
console_type: Optional[ConsoleType] = Field("telnet", description="Console type")
|
console_type: Optional[ConsoleType] = Field("telnet", description="Console type")
|
||||||
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
||||||
|
|
||||||
|
|
||||||
class IOUTemplateCreate(IOUTemplateBase):
|
|
||||||
|
|
||||||
name: str
|
|
||||||
template_type: NodeType
|
|
||||||
compute_id: str
|
|
||||||
|
|
||||||
|
|
||||||
class IOUTemplateUpdate(IOUTemplateBase):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class IOUTemplate(IOUTemplateBase):
|
|
||||||
|
|
||||||
template_id: str
|
|
||||||
name: str
|
|
||||||
category: Category
|
|
||||||
symbol: str
|
|
||||||
builtin: bool
|
|
||||||
template_type: NodeType
|
|
||||||
compute_id: Union[str, None]
|
|
77
gns3server/controller/schemas/qemu_templates.py
Normal file
77
gns3server/controller/schemas/qemu_templates.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.qemu_nodes import (
|
||||||
|
QemuConsoleType,
|
||||||
|
QemuPlatform,
|
||||||
|
QemuAdapterType,
|
||||||
|
QemuOnCloseAction,
|
||||||
|
QemuBootPriority,
|
||||||
|
QemuDiskInterfaceType,
|
||||||
|
QemuProcessPriority,
|
||||||
|
CustomAdapter
|
||||||
|
)
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from pydantic import Field
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
class QemuTemplate(TemplateBase):
|
||||||
|
|
||||||
|
category: Optional[Category] = "guest"
|
||||||
|
default_name_format: Optional[str] = "{name}-{0}"
|
||||||
|
symbol: Optional[str] = ":/symbols/qemu_guest.svg"
|
||||||
|
qemu_path: Optional[Path] = Field("", description="Qemu executable path")
|
||||||
|
platform: Optional[QemuPlatform] = Field("i386", description="Platform to emulate")
|
||||||
|
linked_clone: Optional[bool] = Field(True, description="Whether the VM is a linked clone or not")
|
||||||
|
ram: Optional[int] = Field(256, description="Amount of RAM in MB")
|
||||||
|
cpus: Optional[int] = Field(1, ge=1, le=255, description="Number of vCPUs")
|
||||||
|
maxcpus: Optional[int] = Field(1, ge=1, le=255, description="Maximum number of hotpluggable vCPUs")
|
||||||
|
adapters: Optional[int] = Field(1, ge=0, le=275, description="Number of adapters")
|
||||||
|
adapter_type: Optional[QemuAdapterType] = Field("e1000", description="QEMU adapter type")
|
||||||
|
mac_address: Optional[str] = Field("", description="QEMU MAC address", regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$|^$")
|
||||||
|
first_port_name: Optional[str] = Field("", description="Optional name of the first networking port example: eth0")
|
||||||
|
port_name_format: Optional[str] = Field("Ethernet{0}", description="Optional formatting of the networking port example: eth{0}")
|
||||||
|
port_segment_size: Optional[int] = Field(0, description="Optional port segment size. A port segment is a block of port. For example Ethernet0/0 Ethernet0/1 is the module 0 with a port segment size of 2")
|
||||||
|
console_type: Optional[QemuConsoleType] = Field("telnet", description="Console type")
|
||||||
|
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
||||||
|
aux_type: Optional[QemuConsoleType] = Field("none", description="Auxiliary console type")
|
||||||
|
boot_priority: Optional[QemuBootPriority] = Field("c", description="QEMU boot priority")
|
||||||
|
hda_disk_image: Optional[Path] = Field("", description="QEMU hda disk image path")
|
||||||
|
hda_disk_interface: Optional[QemuDiskInterfaceType] = Field("none", description="QEMU hda interface")
|
||||||
|
hdb_disk_image: Optional[Path] = Field("", description="QEMU hdb disk image path")
|
||||||
|
hdb_disk_interface: Optional[QemuDiskInterfaceType] = Field("none", description="QEMU hdb interface")
|
||||||
|
hdc_disk_image: Optional[Path] = Field("", description="QEMU hdc disk image path")
|
||||||
|
hdc_disk_interface: Optional[QemuDiskInterfaceType] = Field("none", description="QEMU hdc interface")
|
||||||
|
hdd_disk_image: Optional[Path] = Field("", description="QEMU hdd disk image path")
|
||||||
|
hdd_disk_interface: Optional[QemuDiskInterfaceType] = Field("none", description="QEMU hdd interface")
|
||||||
|
cdrom_image: Optional[Path] = Field("", description="QEMU cdrom image path")
|
||||||
|
initrd: Optional[Path] = Field("", description="QEMU initrd path")
|
||||||
|
kernel_image: Optional[Path] = Field("", description="QEMU kernel image path")
|
||||||
|
bios_image: Optional[Path] = Field("", description="QEMU bios image path")
|
||||||
|
kernel_command_line: Optional[str] = Field("", description="QEMU kernel command line")
|
||||||
|
legacy_networking: Optional[bool] = Field(False, description="Use QEMU legagy networking commands (-net syntax)")
|
||||||
|
replicate_network_connection_state: Optional[bool] = Field(True, description="Replicate the network connection state for links in Qemu")
|
||||||
|
create_config_disk: Optional[bool] = Field(False, description="Automatically create a config disk on HDD disk interface (secondary slave)")
|
||||||
|
on_close: Optional[QemuOnCloseAction] = Field("power_off", description="Action to execute on the VM is closed")
|
||||||
|
cpu_throttling: Optional[int] = Field(0, ge=0, le=800, description="Percentage of CPU allowed for QEMU")
|
||||||
|
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([], description="Custom adapters")
|
85
gns3server/controller/schemas/topology.py
Normal file
85
gns3server/controller/schemas/topology.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2015 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#
|
||||||
|
# This file contains the validation for checking a .gns3 file
|
||||||
|
#
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.computes import Compute
|
||||||
|
from gns3server.endpoints.schemas.drawings import Drawing
|
||||||
|
from gns3server.endpoints.schemas.links import Link
|
||||||
|
from gns3server.endpoints.schemas.nodes import Node
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.projects import (
|
||||||
|
Supplier,
|
||||||
|
Variable
|
||||||
|
)
|
||||||
|
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional, List
|
||||||
|
from enum import Enum
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
|
||||||
|
class TopologyType(str, Enum):
|
||||||
|
|
||||||
|
topology = "topology"
|
||||||
|
|
||||||
|
|
||||||
|
class TopologyContent(BaseModel):
|
||||||
|
|
||||||
|
computes: List[Compute] = Field(..., description="List of computes")
|
||||||
|
drawings: List[Drawing] = Field(..., description="List of drawings")
|
||||||
|
links: List[Link] = Field(..., description="List of links")
|
||||||
|
nodes: List[Node] = Field(..., description="List of nodes")
|
||||||
|
|
||||||
|
|
||||||
|
class Topology(BaseModel):
|
||||||
|
|
||||||
|
project_id: UUID = Field(..., description="Project UUID")
|
||||||
|
type: TopologyType = Field(..., description="Type of file. It's always topology")
|
||||||
|
revision: int = Field(..., description="Version of the .gns3 specification")
|
||||||
|
version: str = Field(..., description="Version of the GNS3 software which have update the file for the last time")
|
||||||
|
name: str = Field(..., description="Name of the project")
|
||||||
|
topology: TopologyContent = Field(..., description="Topology content")
|
||||||
|
auto_start: Optional[bool] = Field(None, description="Start the topology when opened")
|
||||||
|
auto_close: Optional[bool] = Field(None, description="Close the topology when no client is connected")
|
||||||
|
scene_height: Optional[int] = Field(None, description="Height of the drawing area")
|
||||||
|
scene_width: Optional[int] = Field(None, description="Width of the drawing area")
|
||||||
|
zoom: Optional[int] = Field(None, description="Zoom of the drawing area")
|
||||||
|
show_layers: Optional[bool] = Field(None, description="Show layers on the drawing area")
|
||||||
|
snap_to_grid: Optional[bool] = Field(None, description="Snap to grid on the drawing area")
|
||||||
|
show_grid: Optional[bool] = Field(None, description="Show the grid on the drawing area")
|
||||||
|
grid_size: Optional[int] = Field(None, description="Grid size for the drawing area for nodes")
|
||||||
|
drawing_grid_size: Optional[int] = Field(None, description="Grid size for the drawing area for drawings")
|
||||||
|
show_interface_labels: Optional[bool] = Field(None, description="Show interface labels on the drawing area")
|
||||||
|
supplier: Optional[Supplier] = Field(None, description="Supplier of the project")
|
||||||
|
variables: Optional[List[Variable]] = Field(None, description="Variables required to run the project")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
with open(sys.argv[1]) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
Topology.parse_obj(data)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
48
gns3server/controller/schemas/virtualbox_templates.py
Normal file
48
gns3server/controller/schemas/virtualbox_templates.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.virtualbox_nodes import (
|
||||||
|
VirtualBoxConsoleType,
|
||||||
|
VirtualBoxAdapterType,
|
||||||
|
VirtualBoxOnCloseAction,
|
||||||
|
CustomAdapter
|
||||||
|
)
|
||||||
|
|
||||||
|
from pydantic import Field
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualBoxTemplate(TemplateBase):
|
||||||
|
|
||||||
|
category: Optional[Category] = "guest"
|
||||||
|
default_name_format: Optional[str] = "{name}-{0}"
|
||||||
|
symbol: Optional[str] = ":/symbols/vbox_guest.svg"
|
||||||
|
vmname: str = Field(..., description="VirtualBox VM name (in VirtualBox itself)")
|
||||||
|
ram: Optional[int] = Field(256, gt=0, description="Amount of RAM in MB")
|
||||||
|
linked_clone: Optional[bool] = Field(False, description="Whether the VM is a linked clone or not")
|
||||||
|
adapters: Optional[int] = Field(1, ge=0, le=36, description="Number of adapters") # 36 is the maximum given by the ICH9 chipset in VirtualBox
|
||||||
|
use_any_adapter: Optional[bool] = Field(False, description="Allow GNS3 to use any VirtualBox adapter")
|
||||||
|
adapter_type: Optional[VirtualBoxAdapterType] = Field("Intel PRO/1000 MT Desktop (82540EM)", description="VirtualBox adapter type")
|
||||||
|
first_port_name: Optional[str] = Field("", description="Optional name of the first networking port example: eth0")
|
||||||
|
port_name_format: Optional[str] = Field("Ethernet{0}", description="Optional formatting of the networking port example: eth{0}")
|
||||||
|
port_segment_size: Optional[int] = Field(0, description="Optional port segment size. A port segment is a block of port. For example Ethernet0/0 Ethernet0/1 is the module 0 with a port segment size of 2")
|
||||||
|
headless: Optional[bool] = Field(False, description="Headless mode")
|
||||||
|
on_close: Optional[VirtualBoxOnCloseAction] = Field("power_off", description="Action to execute on the VM is closed")
|
||||||
|
console_type: Optional[VirtualBoxConsoleType] = Field("none", description="Console type")
|
||||||
|
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
||||||
|
custom_adapters: Optional[List[CustomAdapter]] = Field([], description="Custom adapters")
|
49
gns3server/controller/schemas/vmware_templates.py
Normal file
49
gns3server/controller/schemas/vmware_templates.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 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
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.vmware_nodes import (
|
||||||
|
VMwareConsoleType,
|
||||||
|
VMwareAdapterType,
|
||||||
|
VMwareOnCloseAction,
|
||||||
|
CustomAdapter
|
||||||
|
)
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from pydantic import Field
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
class VMwareTemplate(TemplateBase):
|
||||||
|
|
||||||
|
category: Optional[Category] = "guest"
|
||||||
|
default_name_format: Optional[str] = "{name}-{0}"
|
||||||
|
symbol: Optional[str] = ":/symbols/vmware_guest.svg"
|
||||||
|
vmx_path: Path = Field(..., description="Path to the vmx file")
|
||||||
|
linked_clone: Optional[bool] = Field(False, description="Whether the VM is a linked clone or not")
|
||||||
|
first_port_name: Optional[str] = Field("", description="Optional name of the first networking port example: eth0")
|
||||||
|
port_name_format: Optional[str] = Field("Ethernet{0}", description="Optional formatting of the networking port example: eth{0}")
|
||||||
|
port_segment_size: Optional[int] = Field(0, description="Optional port segment size. A port segment is a block of port. For example Ethernet0/0 Ethernet0/1 is the module 0 with a port segment size of 2")
|
||||||
|
adapters: Optional[int] = Field(1, ge=0, le=10, description="Number of adapters") # 10 is the maximum adapters support by VMware VMs
|
||||||
|
adapter_type: Optional[VMwareAdapterType] = Field("e1000", description="VMware adapter type")
|
||||||
|
use_any_adapter: Optional[bool] = Field(False, description="Allow GNS3 to use any VMware adapter")
|
||||||
|
headless: Optional[bool] = Field(False, description="Headless mode")
|
||||||
|
on_close: Optional[VMwareOnCloseAction] = Field("power_off", description="Action to execute on the VM is closed")
|
||||||
|
console_type: Optional[VMwareConsoleType] = Field("none", description="Console type")
|
||||||
|
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
||||||
|
custom_adapters: Optional[List[CustomAdapter]] = Field([], description="Custom adapters")
|
@ -16,53 +16,18 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from .templates import Category, TemplateBase
|
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||||
|
from gns3server.endpoints.schemas.vpcs_nodes import ConsoleType
|
||||||
|
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from typing import Optional, Union
|
from typing import Optional
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
from .nodes import NodeType
|
|
||||||
|
|
||||||
|
|
||||||
class ConsoleType(str, Enum):
|
class VPCSTemplate(TemplateBase):
|
||||||
"""
|
|
||||||
Supported console types for VPCS nodes
|
|
||||||
"""
|
|
||||||
|
|
||||||
none = "none"
|
|
||||||
telnet = "telnet"
|
|
||||||
|
|
||||||
|
|
||||||
class VPCSTemplateBase(TemplateBase):
|
|
||||||
|
|
||||||
category: Optional[Category] = "guest"
|
category: Optional[Category] = "guest"
|
||||||
default_name_format: Optional[str] = "PC{0}"
|
default_name_format: Optional[str] = "PC{0}"
|
||||||
symbol: Optional[str] = ":/symbols/vpcs_guest.svg"
|
symbol: Optional[str] = ":/symbols/vpcs_guest.svg"
|
||||||
|
|
||||||
base_script_file: Optional[str] = Field("vpcs_base_config.txt", description="Script file")
|
base_script_file: Optional[str] = Field("vpcs_base_config.txt", description="Script file")
|
||||||
console_type: Optional[ConsoleType] = Field("telnet", description="Console type")
|
console_type: Optional[ConsoleType] = Field("telnet", description="Console type")
|
||||||
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
console_auto_start: Optional[bool] = Field(False, description="Automatically start the console when the node has started")
|
||||||
|
|
||||||
|
|
||||||
class VPCSTemplateCreate(VPCSTemplateBase):
|
|
||||||
|
|
||||||
name: str
|
|
||||||
template_type: NodeType
|
|
||||||
compute_id: str
|
|
||||||
|
|
||||||
|
|
||||||
class VPCSTemplateUpdate(VPCSTemplateBase):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class VPCSTemplate(VPCSTemplateBase):
|
|
||||||
|
|
||||||
template_id: str
|
|
||||||
name: str
|
|
||||||
category: Category
|
|
||||||
symbol: str
|
|
||||||
builtin: bool
|
|
||||||
template_type: NodeType
|
|
||||||
compute_id: Union[str, None]
|
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -17,57 +17,14 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import uuid
|
import uuid
|
||||||
import json
|
|
||||||
import jsonschema
|
|
||||||
|
|
||||||
from gns3server.schemas.cloud_template import CLOUD_TEMPLATE_OBJECT_SCHEMA
|
from pydantic import ValidationError
|
||||||
from gns3server.schemas.ethernet_switch_template import ETHERNET_SWITCH_TEMPLATE_OBJECT_SCHEMA
|
from fastapi.encoders import jsonable_encoder
|
||||||
from gns3server.schemas.ethernet_hub_template import ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA
|
from gns3server.controller import schemas
|
||||||
from gns3server.schemas.docker_template import DOCKER_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
from gns3server.schemas.vpcs_template import VPCS_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
from gns3server.schemas.traceng_template import TRACENG_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
from gns3server.schemas.virtualbox_template import VIRTUALBOX_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
from gns3server.schemas.vmware_template import VMWARE_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
from gns3server.schemas.iou_template import IOU_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
from gns3server.schemas.qemu_template import QEMU_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
|
|
||||||
from gns3server.schemas.dynamips_template import (
|
|
||||||
DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
|
||||||
C7200_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
|
||||||
C3745_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
|
||||||
C3725_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
|
||||||
C3600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
|
||||||
C2691_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
|
||||||
C2600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
|
||||||
C1700_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
)
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# Add default values for missing entries in a request, largely taken from jsonschema documentation example
|
|
||||||
# https://python-jsonschema.readthedocs.io/en/latest/faq/#why-doesn-t-my-schema-s-default-property-set-the-default-on-my-instance
|
|
||||||
def extend_with_default(validator_class):
|
|
||||||
|
|
||||||
validate_properties = validator_class.VALIDATORS["properties"]
|
|
||||||
def set_defaults(validator, properties, instance, schema):
|
|
||||||
if jsonschema.Draft4Validator(schema).is_valid(instance):
|
|
||||||
# only add default for the matching sub-schema (e.g. when using 'oneOf')
|
|
||||||
for property, subschema in properties.items():
|
|
||||||
if "default" in subschema:
|
|
||||||
instance.setdefault(property, subschema["default"])
|
|
||||||
|
|
||||||
for error in validate_properties(validator, properties, instance, schema,):
|
|
||||||
yield error
|
|
||||||
|
|
||||||
return jsonschema.validators.extend(
|
|
||||||
validator_class, {"properties" : set_defaults},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
ValidatorWithDefaults = extend_with_default(jsonschema.Draft4Validator)
|
|
||||||
|
|
||||||
ID_TO_CATEGORY = {
|
ID_TO_CATEGORY = {
|
||||||
3: "firewall",
|
3: "firewall",
|
||||||
2: "guest",
|
2: "guest",
|
||||||
@ -76,27 +33,26 @@ ID_TO_CATEGORY = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE_TYPE_TO_SHEMA = {
|
TEMPLATE_TYPE_TO_SHEMA = {
|
||||||
"cloud": CLOUD_TEMPLATE_OBJECT_SCHEMA,
|
"cloud": schemas.CloudTemplate,
|
||||||
"ethernet_hub": ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA,
|
"ethernet_hub": schemas.EthernetHubTemplate,
|
||||||
"ethernet_switch": ETHERNET_SWITCH_TEMPLATE_OBJECT_SCHEMA,
|
"ethernet_switch": schemas.EthernetSwitchTemplate,
|
||||||
"docker": DOCKER_TEMPLATE_OBJECT_SCHEMA,
|
"docker": schemas.DockerTemplate,
|
||||||
"dynamips": DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
"dynamips": schemas.DynamipsTemplate,
|
||||||
"vpcs": VPCS_TEMPLATE_OBJECT_SCHEMA,
|
"vpcs": schemas.VPCSTemplate,
|
||||||
"traceng": TRACENG_TEMPLATE_OBJECT_SCHEMA,
|
"virtualbox": schemas.VirtualBoxTemplate,
|
||||||
"virtualbox": VIRTUALBOX_TEMPLATE_OBJECT_SCHEMA,
|
"vmware": schemas.VMwareTemplate,
|
||||||
"vmware": VMWARE_TEMPLATE_OBJECT_SCHEMA,
|
"iou": schemas.IOUTemplate,
|
||||||
"iou": IOU_TEMPLATE_OBJECT_SCHEMA,
|
"qemu": schemas.QemuTemplate
|
||||||
"qemu": QEMU_TEMPLATE_OBJECT_SCHEMA
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DYNAMIPS_PLATFORM_TO_SHEMA = {
|
DYNAMIPS_PLATFORM_TO_SHEMA = {
|
||||||
"c7200": C7200_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
"c7200": schemas.C7200DynamipsTemplate,
|
||||||
"c3745": C3745_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
"c3745": schemas.C3745DynamipsTemplate,
|
||||||
"c3725": C3725_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
"c3725": schemas.C3725DynamipsTemplate,
|
||||||
"c3600": C3600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
"c3600": schemas.C3600DynamipsTemplate,
|
||||||
"c2691": C2691_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
"c2691": schemas.C2691DynamipsTemplate,
|
||||||
"c2600": C2600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
"c2600": schemas.C2600DynamipsTemplate,
|
||||||
"c1700": C1700_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA
|
"c1700": schemas.C1700DynamipsTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -141,11 +97,18 @@ class Template:
|
|||||||
self._builtin = builtin
|
self._builtin = builtin
|
||||||
|
|
||||||
if builtin is False:
|
if builtin is False:
|
||||||
self.validate_and_apply_defaults(TEMPLATE_TYPE_TO_SHEMA[self.template_type])
|
try:
|
||||||
|
template_schema = TEMPLATE_TYPE_TO_SHEMA[self.template_type]
|
||||||
|
template_settings_with_defaults = template_schema .parse_obj(self.__json__())
|
||||||
|
self._settings = jsonable_encoder(template_settings_with_defaults.dict())
|
||||||
if self.template_type == "dynamips":
|
if self.template_type == "dynamips":
|
||||||
# special case for Dynamips to cover all platform types that contain specific settings
|
# special case for Dynamips to cover all platform types that contain specific settings
|
||||||
self.validate_and_apply_defaults(DYNAMIPS_PLATFORM_TO_SHEMA[self._settings["platform"]])
|
dynamips_template_schema = DYNAMIPS_PLATFORM_TO_SHEMA[self._settings["platform"]]
|
||||||
|
dynamips_template_settings_with_defaults = dynamips_template_schema.parse_obj(self.__json__())
|
||||||
|
self._settings = jsonable_encoder(dynamips_template_settings_with_defaults.dict())
|
||||||
|
except ValidationError as e:
|
||||||
|
print(e) #TODO: handle errors
|
||||||
|
raise
|
||||||
|
|
||||||
log.debug('Template "{name}" [{id}] loaded'.format(name=self.name, id=self._id))
|
log.debug('Template "{name}" [{id}] loaded'.format(name=self.name, id=self._id))
|
||||||
|
|
||||||
@ -179,7 +142,6 @@ class Template:
|
|||||||
|
|
||||||
def update(self, **kwargs):
|
def update(self, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
from gns3server.controller import Controller
|
from gns3server.controller import Controller
|
||||||
controller = Controller.instance()
|
controller = Controller.instance()
|
||||||
Controller.instance().check_can_write_config()
|
Controller.instance().check_can_write_config()
|
||||||
@ -187,17 +149,6 @@ class Template:
|
|||||||
controller.notification.controller_emit("template.updated", self.__json__())
|
controller.notification.controller_emit("template.updated", self.__json__())
|
||||||
controller.save()
|
controller.save()
|
||||||
|
|
||||||
def validate_and_apply_defaults(self, schema):
|
|
||||||
|
|
||||||
validator = ValidatorWithDefaults(schema)
|
|
||||||
try:
|
|
||||||
validator.validate(self.__json__())
|
|
||||||
except jsonschema.ValidationError as e:
|
|
||||||
message = "JSON schema error {}".format(e.message)
|
|
||||||
log.error(message)
|
|
||||||
log.debug("Input schema: {}".format(json.dumps(schema)))
|
|
||||||
raise
|
|
||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
"""
|
"""
|
||||||
Template settings.
|
Template settings.
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import uuid
|
import uuid
|
||||||
import jsonschema
|
import pydantic
|
||||||
|
|
||||||
from .controller_error import ControllerError, ControllerNotFoundError
|
from .controller_error import ControllerError, ControllerNotFoundError
|
||||||
from .template import Template
|
from .template import Template
|
||||||
@ -53,8 +53,8 @@ class TemplateManager:
|
|||||||
try:
|
try:
|
||||||
template = Template(template_settings.get("template_id"), template_settings)
|
template = Template(template_settings.get("template_id"), template_settings)
|
||||||
self._templates[template.id] = template
|
self._templates[template.id] = template
|
||||||
except jsonschema.ValidationError as e:
|
except pydantic.ValidationError as e:
|
||||||
message = "Cannot load template with JSON data '{}': {}".format(template_settings, e.message)
|
message = "Cannot load template with JSON data '{}': {}".format(template_settings, e)
|
||||||
log.warning(message)
|
log.warning(message)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -90,8 +90,8 @@ class TemplateManager:
|
|||||||
template_id = settings.setdefault("template_id", str(uuid.uuid4()))
|
template_id = settings.setdefault("template_id", str(uuid.uuid4()))
|
||||||
try:
|
try:
|
||||||
template = Template(template_id, settings)
|
template = Template(template_id, settings)
|
||||||
except jsonschema.ValidationError as e:
|
except pydantic.ValidationError as e:
|
||||||
message = "JSON schema error adding template with JSON data '{}': {}".format(settings, e.message)
|
message = "JSON schema error adding template with JSON data '{}': {}".format(settings, e)
|
||||||
raise ControllerError(message)
|
raise ControllerError(message)
|
||||||
|
|
||||||
from . import Controller
|
from . import Controller
|
||||||
|
@ -18,21 +18,22 @@
|
|||||||
import os
|
import os
|
||||||
import html
|
import html
|
||||||
import json
|
import json
|
||||||
import copy
|
|
||||||
import uuid
|
import uuid
|
||||||
import glob
|
import glob
|
||||||
import shutil
|
import shutil
|
||||||
import zipfile
|
import zipfile
|
||||||
import jsonschema
|
import pydantic
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from ..version import __version__
|
from ..version import __version__
|
||||||
from ..schemas.topology import TOPOLOGY_SCHEMA
|
|
||||||
from ..schemas import dynamips_vm
|
|
||||||
from ..utils.qt import qt_font_to_style
|
from ..utils.qt import qt_font_to_style
|
||||||
from ..compute.dynamips import PLATFORMS_DEFAULT_RAM
|
from ..compute.dynamips import PLATFORMS_DEFAULT_RAM
|
||||||
from .controller_error import ControllerError
|
from .controller_error import ControllerError
|
||||||
|
|
||||||
|
from gns3server.controller.schemas.topology import Topology
|
||||||
|
from gns3server.endpoints.schemas.dynamips_nodes import DynamipsCreate, NodeStatus
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -40,29 +41,21 @@ log = logging.getLogger(__name__)
|
|||||||
GNS3_FILE_FORMAT_REVISION = 9
|
GNS3_FILE_FORMAT_REVISION = 9
|
||||||
|
|
||||||
|
|
||||||
|
class DynamipsNodeValidation(DynamipsCreate):
|
||||||
|
name: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
def _check_topology_schema(topo):
|
def _check_topology_schema(topo):
|
||||||
try:
|
try:
|
||||||
jsonschema.validate(topo, TOPOLOGY_SCHEMA)
|
Topology.parse_obj(topo)
|
||||||
|
|
||||||
# Check the nodes property against compute schemas
|
# Check the nodes property against compute schemas
|
||||||
for node in topo["topology"].get("nodes", []):
|
for node in topo["topology"].get("nodes", []):
|
||||||
schema = None
|
|
||||||
if node["node_type"] == "dynamips":
|
if node["node_type"] == "dynamips":
|
||||||
schema = copy.deepcopy(dynamips_vm.VM_CREATE_SCHEMA)
|
DynamipsNodeValidation.parse_obj(node.get("properties", {}))
|
||||||
|
|
||||||
if schema:
|
except pydantic.ValidationError as e:
|
||||||
# Properties send to compute but in an other place in topology
|
error = "Invalid data in topology file: {}".format(e)
|
||||||
delete_properties = ["name", "node_id"]
|
|
||||||
for prop in delete_properties:
|
|
||||||
del schema["properties"][prop]
|
|
||||||
schema["required"] = [p for p in schema["required"] if p not in delete_properties]
|
|
||||||
|
|
||||||
jsonschema.validate(node.get("properties", {}), schema)
|
|
||||||
|
|
||||||
except jsonschema.ValidationError as e:
|
|
||||||
error = "Invalid data in topology file: {} in schema: {}".format(
|
|
||||||
e.message,
|
|
||||||
json.dumps(e.schema))
|
|
||||||
log.critical(error)
|
log.critical(error)
|
||||||
raise ControllerError(error)
|
raise ControllerError(error)
|
||||||
|
|
||||||
|
@ -27,13 +27,14 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
from fastapi import APIRouter, Request, Response, HTTPException, status
|
from fastapi import APIRouter, Request, Response, HTTPException, status
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
from typing import Union, List
|
from typing import List
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from gns3server.endpoints.schemas.common import ErrorMessage
|
from gns3server.endpoints.schemas.common import ErrorMessage
|
||||||
from gns3server.endpoints import schemas
|
from gns3server.endpoints import schemas
|
||||||
from gns3server.controller import Controller
|
from gns3server.controller import Controller
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
responses = {
|
responses = {
|
||||||
@ -41,11 +42,6 @@ responses = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#template_create_models = Union[schemas.VPCSTemplateCreate, schemas.CloudTemplateCreate, schemas.IOUTemplateCreate]
|
|
||||||
#template_update_models = Union[schemas.VPCSTemplateUpdate, schemas.CloudTemplateUpdate, schemas.IOUTemplateUpdate]
|
|
||||||
#template_response_models = Union[schemas.VPCSTemplate, schemas.CloudTemplate, schemas.IOUTemplate]
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/templates",
|
@router.post("/templates",
|
||||||
status_code=status.HTTP_201_CREATED,
|
status_code=status.HTTP_201_CREATED,
|
||||||
response_model=schemas.Template)
|
response_model=schemas.Template)
|
||||||
|
@ -40,6 +40,3 @@ from .qemu_nodes import QemuCreate, QemuUpdate, Qemu, QemuDiskResize, QemuImageC
|
|||||||
from .virtualbox_nodes import VirtualBoxCreate, VirtualBoxUpdate, VirtualBox
|
from .virtualbox_nodes import VirtualBoxCreate, VirtualBoxUpdate, VirtualBox
|
||||||
from .vmware_nodes import VMwareCreate, VMwareUpdate, VMware
|
from .vmware_nodes import VMwareCreate, VMwareUpdate, VMware
|
||||||
from .vpcs_nodes import VPCSCreate, VPCSUpdate, VPCS
|
from .vpcs_nodes import VPCSCreate, VPCSUpdate, VPCS
|
||||||
from .vpcs_templates import VPCSTemplateCreate, VPCSTemplateUpdate, VPCSTemplate
|
|
||||||
from .cloud_templates import CloudTemplateCreate, CloudTemplateUpdate, CloudTemplate
|
|
||||||
from .iou_templates import IOUTemplateCreate, IOUTemplateUpdate, IOUTemplate
|
|
||||||
|
@ -103,12 +103,12 @@ class Compute(ComputeBase):
|
|||||||
|
|
||||||
compute_id: Union[str, UUID]
|
compute_id: Union[str, UUID]
|
||||||
name: str
|
name: str
|
||||||
connected: bool = Field(..., description="Whether the controller is connected to the compute or not")
|
connected: Optional[bool] = Field(None, description="Whether the controller is connected to the compute or not")
|
||||||
cpu_usage_percent: float = Field(..., description="CPU usage of the compute", ge=0, le=100)
|
cpu_usage_percent: Optional[float] = Field(None, description="CPU usage of the compute", ge=0, le=100)
|
||||||
memory_usage_percent: float = Field(..., description="Memory usage of the compute", ge=0, le=100)
|
memory_usage_percent: Optional[float] = Field(None, description="Memory usage of the compute", ge=0, le=100)
|
||||||
disk_usage_percent: float = Field(..., description="Disk usage of the compute", ge=0, le=100)
|
disk_usage_percent: Optional[float] = Field(None, description="Disk usage of the compute", ge=0, le=100)
|
||||||
last_error: Optional[str] = Field(None, description="Last error found on the compute")
|
last_error: Optional[str] = Field(None, description="Last error found on the compute")
|
||||||
capabilities: Capabilities
|
capabilities: Optional[Capabilities] = None
|
||||||
|
|
||||||
|
|
||||||
class AutoIdlePC(BaseModel):
|
class AutoIdlePC(BaseModel):
|
||||||
|
@ -25,6 +25,20 @@ from uuid import UUID
|
|||||||
from .nodes import NodeStatus
|
from .nodes import NodeStatus
|
||||||
|
|
||||||
|
|
||||||
|
class DynamipsPlatform(str, Enum):
|
||||||
|
"""
|
||||||
|
Supported Dynamips Platforms.
|
||||||
|
"""
|
||||||
|
|
||||||
|
c7200 = "c7200"
|
||||||
|
c3725 = "c3725"
|
||||||
|
c3745 = "c3745"
|
||||||
|
c3600 = "c3600"
|
||||||
|
c2691 = "c2691"
|
||||||
|
c2600 = "c2600"
|
||||||
|
c1700 = "c1700"
|
||||||
|
|
||||||
|
|
||||||
class DynamipsAdapters(str, Enum):
|
class DynamipsAdapters(str, Enum):
|
||||||
"""
|
"""
|
||||||
Supported Dynamips Network Modules.
|
Supported Dynamips Network Modules.
|
||||||
@ -56,6 +70,7 @@ class DynamipsAdapters(str, Enum):
|
|||||||
gt96100_fe = "GT96100-FE"
|
gt96100_fe = "GT96100-FE"
|
||||||
leopard_2fe = "Leopard-2FE"
|
leopard_2fe = "Leopard-2FE"
|
||||||
|
|
||||||
|
|
||||||
class DynamipsWics(str, Enum):
|
class DynamipsWics(str, Enum):
|
||||||
"""
|
"""
|
||||||
Supported Dynamips WICs.
|
Supported Dynamips WICs.
|
||||||
@ -108,7 +123,7 @@ class DynamipsBase(BaseModel):
|
|||||||
node_id: Optional[UUID] = None
|
node_id: Optional[UUID] = None
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
dynamips_id: Optional[int] = Field(None, description="Dynamips internal ID")
|
dynamips_id: Optional[int] = Field(None, description="Dynamips internal ID")
|
||||||
platform: Optional[str] = Field(None, description="Cisco router platform", regex="^c[0-9]{4}$")
|
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
|
||||||
ram: Optional[int] = Field(None, description="Amount of RAM in MB")
|
ram: Optional[int] = Field(None, description="Amount of RAM in MB")
|
||||||
nvram: Optional[int] = Field(None, description="Amount of NVRAM in KB")
|
nvram: Optional[int] = Field(None, description="Amount of NVRAM in KB")
|
||||||
image: Optional[Path] = Field(None, description="Path to the IOS image")
|
image: Optional[Path] = Field(None, description="Path to the IOS image")
|
||||||
@ -133,16 +148,16 @@ class DynamipsBase(BaseModel):
|
|||||||
aux_type: Optional[DynamipsConsoleType] = Field(None, description="Auxiliary console type")
|
aux_type: Optional[DynamipsConsoleType] = Field(None, description="Auxiliary console type")
|
||||||
mac_addr: Optional[str] = Field(None, description="Base MAC address", regex="^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$")
|
mac_addr: Optional[str] = Field(None, description="Base MAC address", regex="^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$")
|
||||||
system_id: Optional[str] = Field(None, description="System ID")
|
system_id: Optional[str] = Field(None, description="System ID")
|
||||||
slot0: Optional[str] = Field(None, description="Network module slot 0")
|
slot0: Optional[DynamipsAdapters] = Field(None, description="Network module slot 0")
|
||||||
slot1: Optional[str] = Field(None, description="Network module slot 1")
|
slot1: Optional[DynamipsAdapters] = Field(None, description="Network module slot 1")
|
||||||
slot2: Optional[str] = Field(None, description="Network module slot 2")
|
slot2: Optional[DynamipsAdapters] = Field(None, description="Network module slot 2")
|
||||||
slot3: Optional[str] = Field(None, description="Network module slot 3")
|
slot3: Optional[DynamipsAdapters] = Field(None, description="Network module slot 3")
|
||||||
slot4: Optional[str] = Field(None, description="Network module slot 4")
|
slot4: Optional[DynamipsAdapters] = Field(None, description="Network module slot 4")
|
||||||
slot5: Optional[str] = Field(None, description="Network module slot 5")
|
slot5: Optional[DynamipsAdapters] = Field(None, description="Network module slot 5")
|
||||||
slot6: Optional[str] = Field(None, description="Network module slot 6")
|
slot6: Optional[DynamipsAdapters] = Field(None, description="Network module slot 6")
|
||||||
wic0: Optional[str] = Field(None, description="Network module WIC slot 0")
|
wic0: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 0")
|
||||||
wic1: Optional[str] = Field(None, description="Network module WIC slot 1")
|
wic1: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 1")
|
||||||
wic2: Optional[str] = Field(None, description="Network module WIC slot 2")
|
wic2: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 2")
|
||||||
npe: Optional[DynamipsNPE] = Field(None, description="NPE model")
|
npe: Optional[DynamipsNPE] = Field(None, description="NPE model")
|
||||||
midplane: Optional[DynamipsMidplane] = Field(None, description="Midplane model")
|
midplane: Optional[DynamipsMidplane] = Field(None, description="Midplane model")
|
||||||
sensors: Optional[List] = Field(None, description="Temperature sensors")
|
sensors: Optional[List] = Field(None, description="Temperature sensors")
|
||||||
|
@ -35,7 +35,7 @@ class ProjectStatus(str, Enum):
|
|||||||
class Supplier(BaseModel):
|
class Supplier(BaseModel):
|
||||||
|
|
||||||
logo: str = Field(..., description="Path to the project supplier logo")
|
logo: str = Field(..., description="Path to the project supplier logo")
|
||||||
url: HttpUrl = Field(..., description="URL to the project supplier site")
|
url: Optional[HttpUrl] = Field(None, description="URL to the project supplier site")
|
||||||
|
|
||||||
|
|
||||||
class Variable(BaseModel):
|
class Variable(BaseModel):
|
||||||
|
@ -104,6 +104,54 @@ class QemuProcessPriority(str, Enum):
|
|||||||
very_low = "very low"
|
very_low = "very low"
|
||||||
|
|
||||||
|
|
||||||
|
class QemuAdapterType(str, Enum):
|
||||||
|
"""
|
||||||
|
Supported Qemu VM adapter types.
|
||||||
|
"""
|
||||||
|
|
||||||
|
e1000 = "e1000"
|
||||||
|
e1000_82544gc = "e1000-82544gc"
|
||||||
|
e1000_82545em = "e1000-82545em"
|
||||||
|
e1000e = "e1000e"
|
||||||
|
i82550 = "i82550"
|
||||||
|
i82551 = "i82551"
|
||||||
|
i82557a = "i82557a"
|
||||||
|
i82557b = "i82557b"
|
||||||
|
i82557c = "i82557c"
|
||||||
|
i82558a = "i82558a"
|
||||||
|
i82558b = "i82558b"
|
||||||
|
i82559a = "i82559a"
|
||||||
|
i82559b = "i82559b"
|
||||||
|
i82559c = "i82559c"
|
||||||
|
i82559er = "i82559er"
|
||||||
|
i82562 = "i82562"
|
||||||
|
i82801 = "i82801"
|
||||||
|
ne2k_pci = "ne2k_pci"
|
||||||
|
pcnet = "pcnet"
|
||||||
|
rocker = "rocker"
|
||||||
|
rtl8139 = "rtl8139"
|
||||||
|
virtio = "virtio"
|
||||||
|
virtio_net_pci = "virtio-net-pci"
|
||||||
|
vmxnet3 = "vmxnet3"
|
||||||
|
|
||||||
|
|
||||||
|
class QemuDiskInterfaceType(str, Enum):
|
||||||
|
"""
|
||||||
|
Supported Qemu VM disk interface types.
|
||||||
|
"""
|
||||||
|
|
||||||
|
ide = "ide"
|
||||||
|
sate = "sata"
|
||||||
|
nvme = "nvme"
|
||||||
|
scsi = "scsi"
|
||||||
|
sd = "sd"
|
||||||
|
mtd = "mtd"
|
||||||
|
floppy = "floppy"
|
||||||
|
pflash = "pflash"
|
||||||
|
virtio = "virtio"
|
||||||
|
none = "none"
|
||||||
|
|
||||||
|
|
||||||
class QemuBase(BaseModel):
|
class QemuBase(BaseModel):
|
||||||
"""
|
"""
|
||||||
Common Qemu node properties.
|
Common Qemu node properties.
|
||||||
@ -121,16 +169,16 @@ class QemuBase(BaseModel):
|
|||||||
aux_type: Optional[QemuConsoleType] = Field(None, description="Auxiliary console type")
|
aux_type: Optional[QemuConsoleType] = Field(None, description="Auxiliary console type")
|
||||||
hda_disk_image: Optional[Path] = Field(None, description="QEMU hda disk image path")
|
hda_disk_image: Optional[Path] = Field(None, description="QEMU hda disk image path")
|
||||||
hda_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hda disk image checksum")
|
hda_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hda disk image checksum")
|
||||||
hda_disk_image_interface: Optional[str] = Field(None, description="QEMU hda interface")
|
hda_disk_interface: Optional[QemuDiskInterfaceType] = Field(None, description="QEMU hda interface")
|
||||||
hdb_disk_image: Optional[Path] = Field(None, description="QEMU hdb disk image path")
|
hdb_disk_image: Optional[Path] = Field(None, description="QEMU hdb disk image path")
|
||||||
hdb_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdb disk image checksum")
|
hdb_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdb disk image checksum")
|
||||||
hdb_disk_image_interface: Optional[str] = Field(None, description="QEMU hdb interface")
|
hdb_disk_interface: Optional[QemuDiskInterfaceType] = Field(None, description="QEMU hdb interface")
|
||||||
hdc_disk_image: Optional[Path] = Field(None, description="QEMU hdc disk image path")
|
hdc_disk_image: Optional[Path] = Field(None, description="QEMU hdc disk image path")
|
||||||
hdc_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdc disk image checksum")
|
hdc_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdc disk image checksum")
|
||||||
hdc_disk_image_interface: Optional[str] = Field(None, description="QEMU hdc interface")
|
hdc_disk_interface: Optional[QemuDiskInterfaceType] = Field(None, description="QEMU hdc interface")
|
||||||
hdd_disk_image: Optional[Path] = Field(None, description="QEMU hdd disk image path")
|
hdd_disk_image: Optional[Path] = Field(None, description="QEMU hdd disk image path")
|
||||||
hdd_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdd disk image checksum")
|
hdd_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdd disk image checksum")
|
||||||
hdd_disk_image_interface: Optional[str] = Field(None, description="QEMU hdd interface")
|
hdd_disk_interface: Optional[QemuDiskInterfaceType] = Field(None, description="QEMU hdd interface")
|
||||||
cdrom_image: Optional[Path] = Field(None, description="QEMU cdrom image path")
|
cdrom_image: Optional[Path] = Field(None, description="QEMU cdrom image path")
|
||||||
cdrom_image_md5sum: Optional[str] = Field(None, description="QEMU cdrom image checksum")
|
cdrom_image_md5sum: Optional[str] = Field(None, description="QEMU cdrom image checksum")
|
||||||
bios_image: Optional[Path] = Field(None, description="QEMU bios image path")
|
bios_image: Optional[Path] = Field(None, description="QEMU bios image path")
|
||||||
@ -140,12 +188,12 @@ class QemuBase(BaseModel):
|
|||||||
kernel_image: Optional[Path] = Field(None, description="QEMU kernel image path")
|
kernel_image: Optional[Path] = Field(None, description="QEMU kernel image path")
|
||||||
kernel_image_md5sum: Optional[str] = Field(None, description="QEMU kernel image checksum")
|
kernel_image_md5sum: Optional[str] = Field(None, description="QEMU kernel image checksum")
|
||||||
kernel_command_line: Optional[str] = Field(None, description="QEMU kernel command line")
|
kernel_command_line: Optional[str] = Field(None, description="QEMU kernel command line")
|
||||||
boot_priotiry: Optional[QemuBootPriority] = Field(None, description="QEMU boot priority")
|
boot_priority: Optional[QemuBootPriority] = Field(None, description="QEMU boot priority")
|
||||||
ram: Optional[int] = Field(None, description="Amount of RAM in MB")
|
ram: Optional[int] = Field(None, description="Amount of RAM in MB")
|
||||||
cpus: Optional[int] = Field(None, ge=1, le=255, description="Number of vCPUs")
|
cpus: Optional[int] = Field(None, ge=1, le=255, description="Number of vCPUs")
|
||||||
maxcpus: Optional[int] = Field(None, ge=1, le=255, description="Maximum number of hotpluggable vCPUs")
|
maxcpus: Optional[int] = Field(None, ge=1, le=255, description="Maximum number of hotpluggable vCPUs")
|
||||||
adapters: Optional[int] = Field(None, ge=0, le=275, description="Number of adapters")
|
adapters: Optional[int] = Field(None, ge=0, le=275, description="Number of adapters")
|
||||||
adapter_type: Optional[str] = Field(None, description="QEMU adapter type")
|
adapter_type: Optional[QemuAdapterType] = Field(None, description="QEMU adapter type")
|
||||||
mac_address: Optional[str] = Field(None, description="QEMU MAC address", regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
|
mac_address: Optional[str] = Field(None, description="QEMU MAC address", regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
|
||||||
legacy_networking: Optional[bool] = Field(None, description="Use QEMU legagy networking commands (-net syntax)")
|
legacy_networking: Optional[bool] = Field(None, description="Use QEMU legagy networking commands (-net syntax)")
|
||||||
replicate_network_connection_state: Optional[bool] = Field(None, description="Replicate the network connection state for links in Qemu")
|
replicate_network_connection_state: Optional[bool] = Field(None, description="Replicate the network connection state for links in Qemu")
|
||||||
|
@ -45,8 +45,8 @@ class TemplateBase(BaseModel):
|
|||||||
symbol: Optional[str] = None
|
symbol: Optional[str] = None
|
||||||
builtin: Optional[bool] = None
|
builtin: Optional[bool] = None
|
||||||
template_type: Optional[NodeType] = None
|
template_type: Optional[NodeType] = None
|
||||||
usage: Optional[str] = None
|
|
||||||
compute_id: Optional[str] = None
|
compute_id: Optional[str] = None
|
||||||
|
usage: Optional[str] = ""
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
extra = "allow"
|
extra = "allow"
|
||||||
|
@ -42,6 +42,16 @@ class VirtualBoxOnCloseAction(str, Enum):
|
|||||||
save_vm_state = "save_vm_state"
|
save_vm_state = "save_vm_state"
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualBoxAdapterType(str, Enum):
|
||||||
|
|
||||||
|
pcnet_pci_ii = "PCnet-PCI II (Am79C970A)",
|
||||||
|
pcnet_fast_iii = "PCNet-FAST III (Am79C973)",
|
||||||
|
intel_pro_1000_mt_desktop = "Intel PRO/1000 MT Desktop (82540EM)",
|
||||||
|
intel_pro_1000_t_server = "Intel PRO/1000 T Server (82543GC)",
|
||||||
|
intel_pro_1000_mt_server = "Intel PRO/1000 MT Server (82545EM)",
|
||||||
|
paravirtualized_network = "Paravirtualized Network (virtio-net)"
|
||||||
|
|
||||||
|
|
||||||
class VirtualBoxBase(BaseModel):
|
class VirtualBoxBase(BaseModel):
|
||||||
"""
|
"""
|
||||||
Common VirtualBox node properties.
|
Common VirtualBox node properties.
|
||||||
@ -54,14 +64,14 @@ class VirtualBoxBase(BaseModel):
|
|||||||
usage: Optional[str] = Field(None, description="How to use the node")
|
usage: Optional[str] = Field(None, description="How to use the node")
|
||||||
# 36 adapters is the maximum given by the ICH9 chipset in VirtualBox
|
# 36 adapters is the maximum given by the ICH9 chipset in VirtualBox
|
||||||
adapters: Optional[int] = Field(None, ge=0, le=36, description="Number of adapters")
|
adapters: Optional[int] = Field(None, ge=0, le=36, description="Number of adapters")
|
||||||
adapter_type: Optional[str] = Field(None, description="VirtualBox adapter type")
|
adapter_type: Optional[VirtualBoxAdapterType] = Field(None, description="VirtualBox adapter type")
|
||||||
use_any_adapter: Optional[bool] = Field(None, description="Allow GNS3 to use any VirtualBox adapter")
|
use_any_adapter: Optional[bool] = Field(None, description="Allow GNS3 to use any VirtualBox adapter")
|
||||||
console: Optional[int] = Field(None, gt=0, le=65535, description="Console TCP port")
|
console: Optional[int] = Field(None, gt=0, le=65535, description="Console TCP port")
|
||||||
console_type: Optional[VirtualBoxConsoleType] = Field(None, description="Console type")
|
console_type: Optional[VirtualBoxConsoleType] = Field(None, description="Console type")
|
||||||
ram: Optional[int] = Field(None, ge=0, le=65535, description="Amount of RAM in MB")
|
ram: Optional[int] = Field(None, ge=0, le=65535, description="Amount of RAM in MB")
|
||||||
headless: Optional[bool] = Field(None, description="Headless mode")
|
headless: Optional[bool] = Field(None, description="Headless mode")
|
||||||
on_close: Optional[VirtualBoxOnCloseAction] = Field(None, description="Action to execute on the VM is closed")
|
on_close: Optional[VirtualBoxOnCloseAction] = Field(None, description="Action to execute on the VM is closed")
|
||||||
custom_adapters: Optional[List[CustomAdapter]] = Field(None, description="Custom adpaters")
|
custom_adapters: Optional[List[CustomAdapter]] = Field(None, description="Custom adapters")
|
||||||
|
|
||||||
|
|
||||||
class VirtualBoxCreate(VirtualBoxBase):
|
class VirtualBoxCreate(VirtualBoxBase):
|
||||||
|
@ -43,6 +43,21 @@ class VMwareOnCloseAction(str, Enum):
|
|||||||
save_vm_state = "save_vm_state"
|
save_vm_state = "save_vm_state"
|
||||||
|
|
||||||
|
|
||||||
|
class VMwareAdapterType(str, Enum):
|
||||||
|
"""
|
||||||
|
Supported VMware VM adapter types.
|
||||||
|
"""
|
||||||
|
|
||||||
|
default = "default"
|
||||||
|
e1000 = "e1000"
|
||||||
|
e1000e = "e1000e"
|
||||||
|
flexible = "flexible"
|
||||||
|
vlance = "vlance"
|
||||||
|
vmxnet = "vmxnet"
|
||||||
|
vmxnet2 = "vmxnet2"
|
||||||
|
vmxnet3 = "vmxnet3"
|
||||||
|
|
||||||
|
|
||||||
class VMwareBase(BaseModel):
|
class VMwareBase(BaseModel):
|
||||||
"""
|
"""
|
||||||
Common VMware node properties.
|
Common VMware node properties.
|
||||||
@ -59,7 +74,7 @@ class VMwareBase(BaseModel):
|
|||||||
on_close: Optional[VMwareOnCloseAction] = Field(None, description="Action to execute on the VM is closed")
|
on_close: Optional[VMwareOnCloseAction] = Field(None, description="Action to execute on the VM is closed")
|
||||||
# 10 adapters is the maximum supported by VMware VMs.
|
# 10 adapters is the maximum supported by VMware VMs.
|
||||||
adapters: Optional[int] = Field(None, ge=0, le=10, description="Number of adapters")
|
adapters: Optional[int] = Field(None, ge=0, le=10, description="Number of adapters")
|
||||||
adapter_type: Optional[str] = Field(None, description="VMware adapter type")
|
adapter_type: Optional[VMwareAdapterType] = Field(None, description="VMware adapter type")
|
||||||
use_any_adapter: Optional[bool] = Field(None, description="Allow GNS3 to use any VMware adapter")
|
use_any_adapter: Optional[bool] = Field(None, description="Allow GNS3 to use any VMware adapter")
|
||||||
custom_adapters: Optional[List[CustomAdapter]] = Field(None, description="Custom adpaters")
|
custom_adapters: Optional[List[CustomAdapter]] = Field(None, description="Custom adpaters")
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ from uuid import UUID
|
|||||||
from .nodes import NodeStatus, CustomAdapter
|
from .nodes import NodeStatus, CustomAdapter
|
||||||
|
|
||||||
|
|
||||||
class VPCSConsoleType(str, Enum):
|
class ConsoleType(str, Enum):
|
||||||
"""
|
"""
|
||||||
Supported console types.
|
Supported console types.
|
||||||
"""
|
"""
|
||||||
@ -41,7 +41,7 @@ class VPCSBase(BaseModel):
|
|||||||
node_id: Optional[UUID]
|
node_id: Optional[UUID]
|
||||||
usage: Optional[str] = Field(None, description="How to use the node")
|
usage: Optional[str] = Field(None, description="How to use the node")
|
||||||
console: Optional[int] = Field(None, gt=0, le=65535, description="Console TCP port")
|
console: Optional[int] = Field(None, gt=0, le=65535, description="Console TCP port")
|
||||||
console_type: Optional[VPCSConsoleType] = Field(None, description="Console type")
|
console_type: Optional[ConsoleType] = Field(None, description="Console type")
|
||||||
startup_script: Optional[str] = Field(None, description="Content of the VPCS startup script")
|
startup_script: Optional[str] = Field(None, description="Content of the VPCS startup script")
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2016 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
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# 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 copy
|
|
||||||
from .template import BASE_TEMPLATE_PROPERTIES
|
|
||||||
|
|
||||||
|
|
||||||
ETHERNET_HUB_TEMPLATE_PROPERTIES = {
|
|
||||||
"ports_mapping": {
|
|
||||||
"type": "array",
|
|
||||||
"default": [{"port_number": 0,
|
|
||||||
"name": "Ethernet0"
|
|
||||||
},
|
|
||||||
{"port_number": 1,
|
|
||||||
"name": "Ethernet1"
|
|
||||||
},
|
|
||||||
{"port_number": 2,
|
|
||||||
"name": "Ethernet2"
|
|
||||||
},
|
|
||||||
{"port_number": 3,
|
|
||||||
"name": "Ethernet3"
|
|
||||||
},
|
|
||||||
{"port_number": 4,
|
|
||||||
"name": "Ethernet4"
|
|
||||||
},
|
|
||||||
{"port_number": 5,
|
|
||||||
"name": "Ethernet5"
|
|
||||||
},
|
|
||||||
{"port_number": 6,
|
|
||||||
"name": "Ethernet6"
|
|
||||||
},
|
|
||||||
{"port_number": 7,
|
|
||||||
"name": "Ethernet7"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"items": [
|
|
||||||
{"type": "object",
|
|
||||||
"oneOf": [{"description": "Ethernet port",
|
|
||||||
"properties": {"name": {"description": "Port name",
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1},
|
|
||||||
"port_number": {
|
|
||||||
"description": "Port number",
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0}
|
|
||||||
},
|
|
||||||
"required": ["name", "port_number"],
|
|
||||||
"additionalProperties": False}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ETHERNET_HUB_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
|
|
||||||
ETHERNET_HUB_TEMPLATE_PROPERTIES["category"]["default"] = "switch"
|
|
||||||
ETHERNET_HUB_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "Hub{0}"
|
|
||||||
ETHERNET_HUB_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/hub.svg"
|
|
||||||
|
|
||||||
ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA = {
|
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
|
||||||
"description": "An Ethernet hub template object",
|
|
||||||
"type": "object",
|
|
||||||
"properties": ETHERNET_HUB_TEMPLATE_PROPERTIES,
|
|
||||||
"additionalProperties": False
|
|
||||||
}
|
|
@ -655,7 +655,8 @@ async def test_clean_pictures_and_keep_supplier_logo(project):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
project.supplier = {
|
project.supplier = {
|
||||||
'logo': 'logo.png'
|
'logo': 'logo.png',
|
||||||
|
'url': 'http://acme.com'
|
||||||
}
|
}
|
||||||
|
|
||||||
drawing = await project.add_drawing()
|
drawing = await project.add_drawing()
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import jsonschema
|
import pydantic
|
||||||
|
|
||||||
from gns3server.controller.template import Template
|
from gns3server.controller.template import Template
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ def test_template_json():
|
|||||||
|
|
||||||
def test_template_json_with_not_known_category():
|
def test_template_json_with_not_known_category():
|
||||||
|
|
||||||
with pytest.raises(jsonschema.ValidationError):
|
with pytest.raises(pydantic.ValidationError):
|
||||||
Template(None, {
|
Template(None, {
|
||||||
"node_type": "qemu",
|
"node_type": "qemu",
|
||||||
"name": "Test",
|
"name": "Test",
|
||||||
|
@ -908,7 +908,12 @@ async def test_cloud_template_create(controller_api):
|
|||||||
"compute_id": "local",
|
"compute_id": "local",
|
||||||
"default_name_format": "Cloud{0}",
|
"default_name_format": "Cloud{0}",
|
||||||
"name": "Cloud template",
|
"name": "Cloud template",
|
||||||
"symbol": ":/symbols/cloud.svg"}
|
"ports_mapping": [],
|
||||||
|
"symbol": ":/symbols/cloud.svg",
|
||||||
|
"remote_console_host": "127.0.0.1",
|
||||||
|
"remote_console_port": 23,
|
||||||
|
"remote_console_type": "none",
|
||||||
|
"remote_console_http_path": "/"}
|
||||||
|
|
||||||
for item, value in expected_response.items():
|
for item, value in expected_response.items():
|
||||||
assert response.json.get(item) == value
|
assert response.json.get(item) == value
|
||||||
|
Loading…
Reference in New Issue
Block a user