mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-12 19:38:57 +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/>.
|
||||
|
||||
|
||||
from .templates import Category, TemplateBase
|
||||
from .cloud_nodes import EthernetPort, TAPPort, UDPPort
|
||||
from gns3server.endpoints.schemas.templates import Category, TemplateBase
|
||||
from gns3server.endpoints.schemas.cloud_nodes import EthernetPort, TAPPort, UDPPort, CloudConsoleType
|
||||
|
||||
from pydantic import Field
|
||||
from typing import Optional, Union, List
|
||||
from enum import Enum
|
||||
|
||||
from .nodes import NodeType
|
||||
|
||||
|
||||
class RemoteConsoleType(str, Enum):
|
||||
"""
|
||||
Supported remote console types for cloud nodes.
|
||||
"""
|
||||
|
||||
none = "none"
|
||||
telnet = "telnet"
|
||||
vnc = "vnc"
|
||||
spice = "spice"
|
||||
http = "http"
|
||||
https = "https"
|
||||
|
||||
|
||||
class CloudTemplateBase(TemplateBase):
|
||||
class CloudTemplate(TemplateBase):
|
||||
|
||||
category: Optional[Category] = "guest"
|
||||
default_name_format: Optional[str] = "Cloud{0}"
|
||||
@ -47,28 +31,5 @@ class CloudTemplateBase(TemplateBase):
|
||||
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_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_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]
|
||||
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")
|
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/>.
|
||||
|
||||
|
||||
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 pathlib import Path
|
||||
from typing import Optional, Union
|
||||
from enum import Enum
|
||||
|
||||
from .nodes import NodeType
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class ConsoleType(str, Enum):
|
||||
"""
|
||||
Supported console types for IOU nodes
|
||||
"""
|
||||
|
||||
none = "none"
|
||||
telnet = "telnet"
|
||||
|
||||
|
||||
class IOUTemplateBase(TemplateBase):
|
||||
class IOUTemplate(TemplateBase):
|
||||
|
||||
category: Optional[Category] = "router"
|
||||
default_name_format: Optional[str] = "IOU{0}"
|
||||
symbol: Optional[str] = ":/symbols/multilayer_switch.svg"
|
||||
|
||||
path: Path = Field(..., description="Path of IOU executable")
|
||||
ethernet_adapters: Optional[int] = Field(2, description="Number of ethernet 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_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/>.
|
||||
|
||||
|
||||
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 typing import Optional, Union
|
||||
from enum import Enum
|
||||
|
||||
from .nodes import NodeType
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class ConsoleType(str, Enum):
|
||||
"""
|
||||
Supported console types for VPCS nodes
|
||||
"""
|
||||
|
||||
none = "none"
|
||||
telnet = "telnet"
|
||||
|
||||
|
||||
class VPCSTemplateBase(TemplateBase):
|
||||
class VPCSTemplate(TemplateBase):
|
||||
|
||||
category: Optional[Category] = "guest"
|
||||
default_name_format: Optional[str] = "PC{0}"
|
||||
symbol: Optional[str] = ":/symbols/vpcs_guest.svg"
|
||||
|
||||
base_script_file: Optional[str] = Field("vpcs_base_config.txt", description="Script file")
|
||||
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")
|
||||
|
||||
|
||||
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
|
||||
#
|
||||
# Copyright (C) 2016 GNS3 Technologies Inc.
|
||||
# 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
|
||||
@ -17,57 +17,14 @@
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
import json
|
||||
import jsonschema
|
||||
|
||||
from gns3server.schemas.cloud_template import CLOUD_TEMPLATE_OBJECT_SCHEMA
|
||||
from gns3server.schemas.ethernet_switch_template import ETHERNET_SWITCH_TEMPLATE_OBJECT_SCHEMA
|
||||
from gns3server.schemas.ethernet_hub_template import ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA
|
||||
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
|
||||
)
|
||||
from pydantic import ValidationError
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from gns3server.controller import schemas
|
||||
|
||||
import logging
|
||||
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 = {
|
||||
3: "firewall",
|
||||
2: "guest",
|
||||
@ -76,27 +33,26 @@ ID_TO_CATEGORY = {
|
||||
}
|
||||
|
||||
TEMPLATE_TYPE_TO_SHEMA = {
|
||||
"cloud": CLOUD_TEMPLATE_OBJECT_SCHEMA,
|
||||
"ethernet_hub": ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA,
|
||||
"ethernet_switch": ETHERNET_SWITCH_TEMPLATE_OBJECT_SCHEMA,
|
||||
"docker": DOCKER_TEMPLATE_OBJECT_SCHEMA,
|
||||
"dynamips": DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
||||
"vpcs": VPCS_TEMPLATE_OBJECT_SCHEMA,
|
||||
"traceng": TRACENG_TEMPLATE_OBJECT_SCHEMA,
|
||||
"virtualbox": VIRTUALBOX_TEMPLATE_OBJECT_SCHEMA,
|
||||
"vmware": VMWARE_TEMPLATE_OBJECT_SCHEMA,
|
||||
"iou": IOU_TEMPLATE_OBJECT_SCHEMA,
|
||||
"qemu": QEMU_TEMPLATE_OBJECT_SCHEMA
|
||||
"cloud": schemas.CloudTemplate,
|
||||
"ethernet_hub": schemas.EthernetHubTemplate,
|
||||
"ethernet_switch": schemas.EthernetSwitchTemplate,
|
||||
"docker": schemas.DockerTemplate,
|
||||
"dynamips": schemas.DynamipsTemplate,
|
||||
"vpcs": schemas.VPCSTemplate,
|
||||
"virtualbox": schemas.VirtualBoxTemplate,
|
||||
"vmware": schemas.VMwareTemplate,
|
||||
"iou": schemas.IOUTemplate,
|
||||
"qemu": schemas.QemuTemplate
|
||||
}
|
||||
|
||||
DYNAMIPS_PLATFORM_TO_SHEMA = {
|
||||
"c7200": C7200_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
||||
"c3745": C3745_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
||||
"c3725": C3725_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
||||
"c3600": C3600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
||||
"c2691": C2691_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
||||
"c2600": C2600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA,
|
||||
"c1700": C1700_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA
|
||||
"c7200": schemas.C7200DynamipsTemplate,
|
||||
"c3745": schemas.C3745DynamipsTemplate,
|
||||
"c3725": schemas.C3725DynamipsTemplate,
|
||||
"c3600": schemas.C3600DynamipsTemplate,
|
||||
"c2691": schemas.C2691DynamipsTemplate,
|
||||
"c2600": schemas.C2600DynamipsTemplate,
|
||||
"c1700": schemas.C1700DynamipsTemplate
|
||||
}
|
||||
|
||||
|
||||
@ -141,11 +97,18 @@ class Template:
|
||||
self._builtin = builtin
|
||||
|
||||
if builtin is False:
|
||||
self.validate_and_apply_defaults(TEMPLATE_TYPE_TO_SHEMA[self.template_type])
|
||||
|
||||
if self.template_type == "dynamips":
|
||||
# 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"]])
|
||||
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":
|
||||
# special case for Dynamips to cover all platform types that contain specific settings
|
||||
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))
|
||||
|
||||
@ -179,7 +142,6 @@ class Template:
|
||||
|
||||
def update(self, **kwargs):
|
||||
|
||||
|
||||
from gns3server.controller import Controller
|
||||
controller = Controller.instance()
|
||||
Controller.instance().check_can_write_config()
|
||||
@ -187,17 +149,6 @@ class Template:
|
||||
controller.notification.controller_emit("template.updated", self.__json__())
|
||||
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):
|
||||
"""
|
||||
Template settings.
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
import jsonschema
|
||||
import pydantic
|
||||
|
||||
from .controller_error import ControllerError, ControllerNotFoundError
|
||||
from .template import Template
|
||||
@ -53,8 +53,8 @@ class TemplateManager:
|
||||
try:
|
||||
template = Template(template_settings.get("template_id"), template_settings)
|
||||
self._templates[template.id] = template
|
||||
except jsonschema.ValidationError as e:
|
||||
message = "Cannot load template with JSON data '{}': {}".format(template_settings, e.message)
|
||||
except pydantic.ValidationError as e:
|
||||
message = "Cannot load template with JSON data '{}': {}".format(template_settings, e)
|
||||
log.warning(message)
|
||||
continue
|
||||
|
||||
@ -90,8 +90,8 @@ class TemplateManager:
|
||||
template_id = settings.setdefault("template_id", str(uuid.uuid4()))
|
||||
try:
|
||||
template = Template(template_id, settings)
|
||||
except jsonschema.ValidationError as e:
|
||||
message = "JSON schema error adding template with JSON data '{}': {}".format(settings, e.message)
|
||||
except pydantic.ValidationError as e:
|
||||
message = "JSON schema error adding template with JSON data '{}': {}".format(settings, e)
|
||||
raise ControllerError(message)
|
||||
|
||||
from . import Controller
|
||||
|
@ -18,21 +18,22 @@
|
||||
import os
|
||||
import html
|
||||
import json
|
||||
import copy
|
||||
import uuid
|
||||
import glob
|
||||
import shutil
|
||||
import zipfile
|
||||
import jsonschema
|
||||
import pydantic
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from ..version import __version__
|
||||
from ..schemas.topology import TOPOLOGY_SCHEMA
|
||||
from ..schemas import dynamips_vm
|
||||
from ..utils.qt import qt_font_to_style
|
||||
from ..compute.dynamips import PLATFORMS_DEFAULT_RAM
|
||||
from .controller_error import ControllerError
|
||||
|
||||
from gns3server.controller.schemas.topology import Topology
|
||||
from gns3server.endpoints.schemas.dynamips_nodes import DynamipsCreate, NodeStatus
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -40,29 +41,21 @@ log = logging.getLogger(__name__)
|
||||
GNS3_FILE_FORMAT_REVISION = 9
|
||||
|
||||
|
||||
class DynamipsNodeValidation(DynamipsCreate):
|
||||
name: Optional[str] = None
|
||||
|
||||
|
||||
def _check_topology_schema(topo):
|
||||
try:
|
||||
jsonschema.validate(topo, TOPOLOGY_SCHEMA)
|
||||
Topology.parse_obj(topo)
|
||||
|
||||
# Check the nodes property against compute schemas
|
||||
for node in topo["topology"].get("nodes", []):
|
||||
schema = None
|
||||
if node["node_type"] == "dynamips":
|
||||
schema = copy.deepcopy(dynamips_vm.VM_CREATE_SCHEMA)
|
||||
DynamipsNodeValidation.parse_obj(node.get("properties", {}))
|
||||
|
||||
if schema:
|
||||
# Properties send to compute but in an other place in topology
|
||||
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))
|
||||
except pydantic.ValidationError as e:
|
||||
error = "Invalid data in topology file: {}".format(e)
|
||||
log.critical(error)
|
||||
raise ControllerError(error)
|
||||
|
||||
|
@ -27,13 +27,14 @@ log = logging.getLogger(__name__)
|
||||
|
||||
from fastapi import APIRouter, Request, Response, HTTPException, status
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from typing import Union, List
|
||||
from typing import List
|
||||
from uuid import UUID
|
||||
|
||||
from gns3server.endpoints.schemas.common import ErrorMessage
|
||||
from gns3server.endpoints import schemas
|
||||
from gns3server.controller import Controller
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
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",
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
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 .vmware_nodes import VMwareCreate, VMwareUpdate, VMware
|
||||
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]
|
||||
name: str
|
||||
connected: bool = Field(..., 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)
|
||||
memory_usage_percent: float = Field(..., 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)
|
||||
connected: Optional[bool] = Field(None, description="Whether the controller is connected to the compute or not")
|
||||
cpu_usage_percent: Optional[float] = Field(None, description="CPU 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: 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")
|
||||
capabilities: Capabilities
|
||||
capabilities: Optional[Capabilities] = None
|
||||
|
||||
|
||||
class AutoIdlePC(BaseModel):
|
||||
|
@ -25,6 +25,20 @@ from uuid import UUID
|
||||
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):
|
||||
"""
|
||||
Supported Dynamips Network Modules.
|
||||
@ -56,6 +70,7 @@ class DynamipsAdapters(str, Enum):
|
||||
gt96100_fe = "GT96100-FE"
|
||||
leopard_2fe = "Leopard-2FE"
|
||||
|
||||
|
||||
class DynamipsWics(str, Enum):
|
||||
"""
|
||||
Supported Dynamips WICs.
|
||||
@ -108,7 +123,7 @@ class DynamipsBase(BaseModel):
|
||||
node_id: Optional[UUID] = None
|
||||
name: Optional[str] = None
|
||||
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")
|
||||
nvram: Optional[int] = Field(None, description="Amount of NVRAM in KB")
|
||||
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")
|
||||
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")
|
||||
slot0: Optional[str] = Field(None, description="Network module slot 0")
|
||||
slot1: Optional[str] = Field(None, description="Network module slot 1")
|
||||
slot2: Optional[str] = Field(None, description="Network module slot 2")
|
||||
slot3: Optional[str] = Field(None, description="Network module slot 3")
|
||||
slot4: Optional[str] = Field(None, description="Network module slot 4")
|
||||
slot5: Optional[str] = Field(None, description="Network module slot 5")
|
||||
slot6: Optional[str] = Field(None, description="Network module slot 6")
|
||||
wic0: Optional[str] = Field(None, description="Network module WIC slot 0")
|
||||
wic1: Optional[str] = Field(None, description="Network module WIC slot 1")
|
||||
wic2: Optional[str] = Field(None, description="Network module WIC slot 2")
|
||||
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")
|
||||
npe: Optional[DynamipsNPE] = Field(None, description="NPE model")
|
||||
midplane: Optional[DynamipsMidplane] = Field(None, description="Midplane model")
|
||||
sensors: Optional[List] = Field(None, description="Temperature sensors")
|
||||
|
@ -35,7 +35,7 @@ class ProjectStatus(str, Enum):
|
||||
class Supplier(BaseModel):
|
||||
|
||||
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):
|
||||
|
@ -104,6 +104,54 @@ class QemuProcessPriority(str, Enum):
|
||||
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):
|
||||
"""
|
||||
Common Qemu node properties.
|
||||
@ -121,16 +169,16 @@ class QemuBase(BaseModel):
|
||||
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_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_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_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_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_md5sum: Optional[str] = Field(None, description="QEMU cdrom image checksum")
|
||||
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_md5sum: Optional[str] = Field(None, description="QEMU kernel image checksum")
|
||||
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")
|
||||
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")
|
||||
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})$")
|
||||
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")
|
||||
|
@ -45,8 +45,8 @@ class TemplateBase(BaseModel):
|
||||
symbol: Optional[str] = None
|
||||
builtin: Optional[bool] = None
|
||||
template_type: Optional[NodeType] = None
|
||||
usage: Optional[str] = None
|
||||
compute_id: Optional[str] = None
|
||||
usage: Optional[str] = ""
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
@ -42,6 +42,16 @@ class VirtualBoxOnCloseAction(str, Enum):
|
||||
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):
|
||||
"""
|
||||
Common VirtualBox node properties.
|
||||
@ -54,14 +64,14 @@ class VirtualBoxBase(BaseModel):
|
||||
usage: Optional[str] = Field(None, description="How to use the node")
|
||||
# 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")
|
||||
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")
|
||||
console: Optional[int] = Field(None, gt=0, le=65535, description="Console TCP port")
|
||||
console_type: Optional[VirtualBoxConsoleType] = Field(None, description="Console type")
|
||||
ram: Optional[int] = Field(None, ge=0, le=65535, description="Amount of RAM in MB")
|
||||
headless: Optional[bool] = Field(None, description="Headless mode")
|
||||
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):
|
||||
|
@ -43,6 +43,21 @@ class VMwareOnCloseAction(str, Enum):
|
||||
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):
|
||||
"""
|
||||
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")
|
||||
# 10 adapters is the maximum supported by VMware VMs.
|
||||
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")
|
||||
custom_adapters: Optional[List[CustomAdapter]] = Field(None, description="Custom adpaters")
|
||||
|
||||
|
@ -23,7 +23,7 @@ from uuid import UUID
|
||||
from .nodes import NodeStatus, CustomAdapter
|
||||
|
||||
|
||||
class VPCSConsoleType(str, Enum):
|
||||
class ConsoleType(str, Enum):
|
||||
"""
|
||||
Supported console types.
|
||||
"""
|
||||
@ -41,7 +41,7 @@ class VPCSBase(BaseModel):
|
||||
node_id: Optional[UUID]
|
||||
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_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")
|
||||
|
||||
|
||||
|
@ -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 = {
|
||||
'logo': 'logo.png'
|
||||
'logo': 'logo.png',
|
||||
'url': 'http://acme.com'
|
||||
}
|
||||
|
||||
drawing = await project.add_drawing()
|
||||
|
@ -16,7 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import jsonschema
|
||||
import pydantic
|
||||
|
||||
from gns3server.controller.template import Template
|
||||
|
||||
@ -39,7 +39,7 @@ def test_template_json():
|
||||
|
||||
def test_template_json_with_not_known_category():
|
||||
|
||||
with pytest.raises(jsonschema.ValidationError):
|
||||
with pytest.raises(pydantic.ValidationError):
|
||||
Template(None, {
|
||||
"node_type": "qemu",
|
||||
"name": "Test",
|
||||
|
@ -908,7 +908,12 @@ async def test_cloud_template_create(controller_api):
|
||||
"compute_id": "local",
|
||||
"default_name_format": "Cloud{0}",
|
||||
"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():
|
||||
assert response.json.get(item) == value
|
||||
|
Loading…
Reference in New Issue
Block a user