Use pydantic for data validation (instead of jsonschema)

Fix/improve various pydantic shema models.
This commit is contained in:
grossmj committed 2020-10-31 15:07:12 +10:30
1 parent d6a65883ee
commit 81439c750a
29 files changed
+784 -350

No files matched your search

+2 -6
View File
@@ -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)
-3
View File
@@ -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
@@ -1,74 +0,0 @@
# -*- 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 .templates import Category, TemplateBase
from .cloud_nodes import EthernetPort, TAPPort, UDPPort
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):
category: Optional[Category] = "guest"
default_name_format: Optional[str] = "Cloud{0}"
symbol: Optional[str] = ":/symbols/cloud.svg"
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]
+5 -5
View File
@@ -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):
+26 -11
View File
@@ -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")
@@ -1,77 +0,0 @@
# -*- 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 .templates import Category, TemplateBase
from pydantic import Field
from pathlib import Path
from typing import Optional, Union
from enum import Enum
from .nodes import NodeType
class ConsoleType(str, Enum):
"""
Supported console types for IOU nodes
"""
none = "none"
telnet = "telnet"
class IOUTemplateBase(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")
ram: Optional[int] = Field(256, description="Amount of RAM in MB")
nvram: Optional[int] = Field(128, description="Amount of NVRAM in KB")
use_default_iou_values: Optional[bool] = Field(True, description="Use default IOU values")
startup_config: Optional[str] = Field("iou_l3_base_startup-config.txt", description="Startup-config of IOU")
private_config: Optional[str] = Field("", description="Private-config of IOU")
l1_keepalives: Optional[bool] = Field(False, description="Always keep up Ethernet interface (does not always work)")
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]
+1 -1
View File
@@ -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):
+54 -6
View File
@@ -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")
+1 -1
View File
@@ -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):
+16 -1
View File
@@ -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")
+2 -2
View File
@@ -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,68 +0,0 @@
# -*- 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 .templates import Category, TemplateBase
from pydantic import Field
from typing import Optional, Union
from enum import Enum
from .nodes import NodeType
class ConsoleType(str, Enum):
"""
Supported console types for VPCS nodes
"""
none = "none"
telnet = "telnet"
class VPCSTemplateBase(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]