# # 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 . from pydantic import BaseModel, Field, validator from typing import List, Optional, Union from enum import Enum from uuid import UUID, uuid4 from .labels import Label from ..common import ConsoleType, NodeStatus, CustomAdapter class NodeType(str, Enum): """ Supported node types. """ cloud = "cloud" nat = "nat" ethernet_hub = "ethernet_hub" ethernet_switch = "ethernet_switch" frame_relay_switch = "frame_relay_switch" atm_switch = "atm_switch" docker = "docker" dynamips = "dynamips" vpcs = "vpcs" virtualbox = "virtualbox" vmware = "vmware" iou = "iou" qemu = "qemu" class Image(BaseModel): """ Image data. """ filename: str path: str md5sum: Optional[str] = None filesize: Optional[int] = None class LinkType(str, Enum): """ Supported link types. """ ethernet = "ethernet" serial = "serial" class DataLinkType(str, Enum): """ Supported data link types. """ atm = "DLT_ATM_RFC1483" ethernet = "DLT_EN10MB" frame_relay = "DLT_FRELAY" cisco_hdlc = "DLT_C_HDLC" ppp = "DLT_PPP_SERIAL" class NodeCapture(BaseModel): """ Node capture data. """ capture_file_name: str data_link_type: Optional[DataLinkType] = None class NodePort(BaseModel): """ Node port data. """ name: str = Field(..., description="Port name") short_name: str = Field(..., description="Port name") adapter_number: int = Field(..., description="Adapter slot") adapter_type: Optional[str] = Field(None, description="Adapter type") port_number: int = Field(..., description="Port slot") link_type: LinkType = Field(..., description="Type of link") data_link_types: dict = Field(..., description="Available PCAP types for capture") mac_address: Union[str, None] = Field(None, regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$") class NodeBase(BaseModel): """ Node data. """ compute_id: Union[UUID, str] name: str node_type: NodeType node_id: Optional[UUID] = None console: Optional[int] = Field(None, gt=0, le=65535, description="Console TCP port") console_type: Optional[ConsoleType] = None console_auto_start: Optional[bool] = Field( False, description="Automatically start the console when the node has started" ) aux: Optional[int] = Field(None, gt=0, le=65535, description="Auxiliary console TCP port") aux_type: Optional[ConsoleType] properties: Optional[dict] = Field(default_factory=dict, description="Properties specific to an emulator") label: Optional[Label] = None symbol: Optional[str] = None x: Optional[int] = 0 y: Optional[int] = 0 z: Optional[int] = 1 locked: Optional[bool] = Field(False, description="Whether the element locked or not") port_name_format: Optional[str] = Field( None, descript_port_name_formation="Formatting for port name {0} will be replace by port number" ) port_segment_size: Optional[int] = Field(None, description="Size of the port segment") first_port_name: Optional[str] = Field(None, description="Name of the first port") custom_adapters: Optional[List[CustomAdapter]] = None @validator("port_name_format", pre=True, always=True) def default_port_name_format(cls, v, values): if v is None: if "node_type" in values and values["node_type"] == NodeType.iou: return "Ethernet{segment0}/{port0}" return "Ethernet{0}" return v @validator("port_segment_size", pre=True, always=True) def default_port_segment_size(cls, v, values): if v is None: if "node_type" in values and values["node_type"] == NodeType.iou: return 4 return 0 return v class NodeCreate(NodeBase): node_id: UUID = Field(default_factory=uuid4) class NodeUpdate(NodeBase): """ Data to update a node. """ compute_id: Optional[Union[UUID, str]] = None name: Optional[str] = None node_type: Optional[NodeType] = None class Node(NodeBase): template_id: Optional[UUID] = Field(None, description="Template UUID from which the node has been created. Read only") project_id: Optional[UUID] = None node_directory: Optional[str] = Field(None, description="Working directory of the node. Read only") status: Optional[NodeStatus] = Field(None, description="Node status. Read only") command_line: Optional[str] = Field(None, description="Command line use to start the node. Read only") width: Optional[int] = Field(None, description="Width of the node. Read only") height: Optional[int] = Field(None, description="Height of the node. Read only") ports: Optional[List[NodePort]] = Field(None, description="List of node ports. Read only") console_host: Optional[str] = Field( None, description="Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller", ) class NodeDuplicate(BaseModel): """ Data to duplicate a node. """ x: int y: int z: Optional[int] = 0