diff --git a/gns3server/api/routes/compute/__init__.py b/gns3server/api/routes/compute/__init__.py
index b60dfb7c..57b7225d 100644
--- a/gns3server/api/routes/compute/__init__.py
+++ b/gns3server/api/routes/compute/__init__.py
@@ -138,35 +138,103 @@ async def http_exception_handler(request: Request, exc: StarletteHTTPException):
)
-compute_api.include_router(capabilities.router, tags=["Capabilities"])
-compute_api.include_router(compute.router, tags=["Compute"])
-compute_api.include_router(notifications.router, tags=["Notifications"])
-compute_api.include_router(projects.router, tags=["Projects"])
-compute_api.include_router(images.router, tags=["Images"])
compute_api.include_router(
- atm_switch_nodes.router, prefix="/projects/{project_id}/atm_switch/nodes", tags=["ATM switch"]
+ capabilities.router,
+ tags=["Capabilities"]
)
-compute_api.include_router(cloud_nodes.router, prefix="/projects/{project_id}/cloud/nodes", tags=["Cloud nodes"])
-compute_api.include_router(docker_nodes.router, prefix="/projects/{project_id}/docker/nodes", tags=["Docker nodes"])
+
compute_api.include_router(
- dynamips_nodes.router, prefix="/projects/{project_id}/dynamips/nodes", tags=["Dynamips nodes"]
+ compute.router,
+ tags=["Compute"]
+)
+
+compute_api.include_router(
+ notifications.router,
+ tags=["Notifications"]
+)
+
+compute_api.include_router(
+ projects.router,
+ tags=["Projects"]
+)
+
+compute_api.include_router(
+ images.router,
+ tags=["Images"]
+)
+
+compute_api.include_router(
+ atm_switch_nodes.router,
+ prefix="/projects/{project_id}/atm_switch/nodes",
+ tags=["ATM switch"]
)
compute_api.include_router(
- ethernet_hub_nodes.router, prefix="/projects/{project_id}/ethernet_hub/nodes", tags=["Ethernet hub nodes"]
+ cloud_nodes.router,
+ prefix="/projects/{project_id}/cloud/nodes",
+ tags=["Cloud nodes"]
)
+
compute_api.include_router(
- ethernet_switch_nodes.router, prefix="/projects/{project_id}/ethernet_switch/nodes", tags=["Ethernet switch nodes"]
+ docker_nodes.router,
+ prefix="/projects/{project_id}/docker/nodes",
+ tags=["Docker nodes"]
)
+
+compute_api.include_router(
+ dynamips_nodes.router,
+ prefix="/projects/{project_id}/dynamips/nodes",
+ tags=["Dynamips nodes"]
+)
+
+compute_api.include_router(
+ ethernet_hub_nodes.router,
+ prefix="/projects/{project_id}/ethernet_hub/nodes",
+ tags=["Ethernet hub nodes"]
+)
+
+compute_api.include_router(
+ ethernet_switch_nodes.router,
+ prefix="/projects/{project_id}/ethernet_switch/nodes",
+ tags=["Ethernet switch nodes"]
+)
+
compute_api.include_router(
frame_relay_switch_nodes.router,
prefix="/projects/{project_id}/frame_relay_switch/nodes",
- tags=["Frame Relay switch nodes"],
+ tags=["Frame Relay switch nodes"]
)
-compute_api.include_router(iou_nodes.router, prefix="/projects/{project_id}/iou/nodes", tags=["IOU nodes"])
-compute_api.include_router(nat_nodes.router, prefix="/projects/{project_id}/nat/nodes", tags=["NAT nodes"])
-compute_api.include_router(qemu_nodes.router, prefix="/projects/{project_id}/qemu/nodes", tags=["Qemu nodes"])
+
compute_api.include_router(
- virtualbox_nodes.router, prefix="/projects/{project_id}/virtualbox/nodes", tags=["VirtualBox nodes"]
+ iou_nodes.router,
+ prefix="/projects/{project_id}/iou/nodes",
+ tags=["IOU nodes"])
+
+compute_api.include_router(
+ nat_nodes.router,
+ prefix="/projects/{project_id}/nat/nodes",
+ tags=["NAT nodes"]
+)
+
+compute_api.include_router(
+ qemu_nodes.router,
+ prefix="/projects/{project_id}/qemu/nodes",
+ tags=["Qemu nodes"]
+)
+
+compute_api.include_router(
+ virtualbox_nodes.router,
+ prefix="/projects/{project_id}/virtualbox/nodes",
+ tags=["VirtualBox nodes"]
+)
+
+compute_api.include_router(
+ vmware_nodes.router,
+ prefix="/projects/{project_id}/vmware/nodes",
+ tags=["VMware nodes"]
+)
+
+compute_api.include_router(
+ vpcs_nodes.router,
+ prefix="/projects/{project_id}/vpcs/nodes",
+ tags=["VPCS nodes"]
)
-compute_api.include_router(vmware_nodes.router, prefix="/projects/{project_id}/vmware/nodes", tags=["VMware nodes"])
-compute_api.include_router(vpcs_nodes.router, prefix="/projects/{project_id}/vpcs/nodes", tags=["VPCS nodes"])
diff --git a/gns3server/api/routes/compute/virtualbox_nodes.py b/gns3server/api/routes/compute/virtualbox_nodes.py
index f558a02e..7fa51d9e 100644
--- a/gns3server/api/routes/compute/virtualbox_nodes.py
+++ b/gns3server/api/routes/compute/virtualbox_nodes.py
@@ -149,11 +149,6 @@ async def start_virtualbox_node(node: VirtualBoxVM = Depends(dep_node)):
Start a VirtualBox node.
"""
- if await node.check_hw_virtualization():
- pm = ProjectManager.instance()
- if pm.check_hardware_virtualization(node) is False:
- pass # FIXME: check this
- # raise ComputeError("Cannot start VM with hardware acceleration (KVM/HAX) enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox")
await node.start()
diff --git a/gns3server/api/routes/compute/vmware_nodes.py b/gns3server/api/routes/compute/vmware_nodes.py
index 1d857f1e..2617f791 100644
--- a/gns3server/api/routes/compute/vmware_nodes.py
+++ b/gns3server/api/routes/compute/vmware_nodes.py
@@ -117,11 +117,6 @@ async def start_vmware_node(node: VMwareVM = Depends(dep_node)):
Start a VMware node.
"""
- if node.check_hw_virtualization():
- pm = ProjectManager.instance()
- if pm.check_hardware_virtualization(node) is False:
- pass # FIXME: check this
- # raise ComputeError("Cannot start VM with hardware acceleration (KVM/HAX) enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox")
await node.start()
diff --git a/gns3server/api/routes/controller/nodes.py b/gns3server/api/routes/controller/nodes.py
index e14dd334..93e2a28b 100644
--- a/gns3server/api/routes/controller/nodes.py
+++ b/gns3server/api/routes/controller/nodes.py
@@ -108,7 +108,7 @@ async def dep_node(node_id: UUID, project: Project = Depends(dep_project)):
409: {"model": schemas.ErrorMessage, "description": "Could not create node"},
},
)
-async def create_node(node_data: schemas.Node, project: Project = Depends(dep_project)):
+async def create_node(node_data: schemas.NodeCreate, project: Project = Depends(dep_project)):
"""
Create a new node.
"""
diff --git a/gns3server/compute/project_manager.py b/gns3server/compute/project_manager.py
index b657007c..d1f77cb8 100644
--- a/gns3server/compute/project_manager.py
+++ b/gns3server/compute/project_manager.py
@@ -120,18 +120,3 @@ class ProjectManager:
if project_id not in self._projects:
raise ComputeNotFoundError(f"Project ID {project_id} doesn't exist")
del self._projects[project_id]
-
- def check_hardware_virtualization(self, source_node):
- """
- Checks if hardware virtualization can be used.
-
- :returns: boolean
- """
-
- for project in self._projects.values():
- for node in project.nodes:
- if node == source_node:
- continue
- if node.hw_virtualization and node.__class__.__name__ != source_node.__class__.__name__:
- return False
- return True
diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py
index 7e618210..87f825bb 100644
--- a/gns3server/compute/qemu/qemu_vm.py
+++ b/gns3server/compute/qemu/qemu_vm.py
@@ -47,7 +47,7 @@ from ...utils.asyncio import monitor_process
from ...utils.images import md5sum
from ...utils import macaddress_to_int, int_to_macaddress
-from gns3server.schemas.qemu_nodes import Qemu, QemuPlatform
+from gns3server.schemas.compute.qemu_nodes import Qemu, QemuPlatform
import logging
diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py
index 46b3c966..f7976b90 100644
--- a/gns3server/controller/__init__.py
+++ b/gns3server/controller/__init__.py
@@ -353,6 +353,7 @@ class Controller:
self._computes[compute.id] = compute
# self.save()
if connect:
+ # call compute.connect() later to give time to the controller to be fully started
asyncio.get_event_loop().call_later(1, lambda: asyncio.ensure_future(compute.connect()))
self.notification.controller_emit("compute.created", compute.__json__())
return compute
diff --git a/gns3server/controller/drawing.py b/gns3server/controller/drawing.py
index a1a89809..83e174da 100644
--- a/gns3server/controller/drawing.py
+++ b/gns3server/controller/drawing.py
@@ -203,6 +203,7 @@ class Drawing:
"""
:param topology_dump: Filter to keep only properties require for saving on disk
"""
+
if topology_dump:
return {
"drawing_id": self._id,
diff --git a/gns3server/controller/topology.py b/gns3server/controller/topology.py
index 687f2b29..fa2a54d6 100644
--- a/gns3server/controller/topology.py
+++ b/gns3server/controller/topology.py
@@ -31,8 +31,8 @@ from ..utils.qt import qt_font_to_style
from ..compute.dynamips import PLATFORMS_DEFAULT_RAM
from .controller_error import ControllerError
-from gns3server.schemas.topology import Topology
-from gns3server.schemas.dynamips_nodes import DynamipsCreate
+from gns3server.schemas.controller.topology import Topology
+from gns3server.schemas.compute.dynamips_nodes import DynamipsCreate
import logging
diff --git a/gns3server/core/tasks.py b/gns3server/core/tasks.py
index 4623c487..5080c7d9 100644
--- a/gns3server/core/tasks.py
+++ b/gns3server/core/tasks.py
@@ -33,6 +33,10 @@ log = logging.getLogger(__name__)
def create_startup_handler(app: FastAPI) -> Callable:
+ """
+ Tasks to be performed when the server is starting.
+ """
+
async def start_app() -> None:
loop = asyncio.get_event_loop()
logger = logging.getLogger("asyncio")
@@ -77,6 +81,10 @@ def create_startup_handler(app: FastAPI) -> Callable:
def create_shutdown_handler(app: FastAPI) -> Callable:
+ """
+ Tasks to be performed when the server is shutdown.
+ """
+
async def shutdown_handler() -> None:
await HTTPClient.close_session()
await Controller.instance().stop()
diff --git a/gns3server/handlers/api/controller/symbol_handler.py b/gns3server/handlers/api/controller/symbol_handler.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/gns3server/schemas/__init__.py b/gns3server/schemas/__init__.py
index 022d428e..8ff9d6f0 100644
--- a/gns3server/schemas/__init__.py
+++ b/gns3server/schemas/__init__.py
@@ -14,46 +14,36 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+# General schemas
from .config import ServerConfig
-from .iou_license import IOULicense
-from .links import Link
from .common import ErrorMessage
from .version import Version
-from .computes import ComputeCreate, ComputeUpdate, AutoIdlePC, Compute
-from .templates import TemplateCreate, TemplateUpdate, TemplateUsage, Template
-from .drawings import Drawing
-from .gns3vm import GNS3VM
-from .nodes import NodeUpdate, NodeDuplicate, NodeCapture, Node
-from .projects import ProjectCreate, ProjectUpdate, ProjectDuplicate, Project, ProjectFile
-from .users import UserCreate, UserUpdate, User
-from .tokens import Token
-from .snapshots import SnapshotCreate, Snapshot
-from .capabilities import Capabilities
-from .nios import UDPNIO, TAPNIO, EthernetNIO
-from .atm_switch_nodes import ATMSwitchCreate, ATMSwitchUpdate, ATMSwitch
-from .cloud_nodes import CloudCreate, CloudUpdate, Cloud
-from .docker_nodes import DockerCreate, DockerUpdate, Docker
-from .dynamips_nodes import DynamipsCreate, DynamipsUpdate, Dynamips
-from .ethernet_hub_nodes import EthernetHubCreate, EthernetHubUpdate, EthernetHub
-from .ethernet_switch_nodes import EthernetSwitchCreate, EthernetSwitchUpdate, EthernetSwitch
-from .frame_relay_switch_nodes import FrameRelaySwitchCreate, FrameRelaySwitchUpdate, FrameRelaySwitch
-from .qemu_nodes import QemuCreate, QemuUpdate, QemuImageCreate, QemuImageUpdate, QemuDiskResize, Qemu
-from .iou_nodes import IOUCreate, IOUUpdate, IOUStart, IOU
-from .nat_nodes import NATCreate, NATUpdate, NAT
-from .vpcs_nodes import VPCSCreate, VPCSUpdate, VPCS
-from .vmware_nodes import VMwareCreate, VMwareUpdate, VMware
-from .virtualbox_nodes import VirtualBoxCreate, VirtualBoxUpdate, VirtualBox
-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 (
+# Controller schemas
+from .controller.links import Link
+from .controller.computes import ComputeCreate, ComputeUpdate, AutoIdlePC, Compute
+from .controller.templates import TemplateCreate, TemplateUpdate, TemplateUsage, Template
+from .controller.drawings import Drawing
+from .controller.gns3vm import GNS3VM
+from .controller.nodes import NodeCreate, NodeUpdate, NodeDuplicate, NodeCapture, Node
+from .controller.projects import ProjectCreate, ProjectUpdate, ProjectDuplicate, Project, ProjectFile
+from .controller.users import UserCreate, UserUpdate, User
+from .controller.tokens import Token
+from .controller.snapshots import SnapshotCreate, Snapshot
+from .controller.iou_license import IOULicense
+from .controller.capabilities import Capabilities
+
+# Controller template schemas
+from .controller.templates.vpcs_templates import VPCSTemplate
+from .controller.templates.cloud_templates import CloudTemplate
+from .controller.templates.iou_templates import IOUTemplate
+from .controller.templates.docker_templates import DockerTemplate
+from .controller.templates.ethernet_hub_templates import EthernetHubTemplate
+from .controller.templates.ethernet_switch_templates import EthernetSwitchTemplate
+from .controller.templates.virtualbox_templates import VirtualBoxTemplate
+from .controller.templates.vmware_templates import VMwareTemplate
+from .controller.templates.qemu_templates import QemuTemplate
+from .controller.templates.dynamips_templates import (
DynamipsTemplate,
C1700DynamipsTemplate,
C2600DynamipsTemplate,
@@ -63,3 +53,19 @@ from .dynamips_templates import (
C3745DynamipsTemplate,
C7200DynamipsTemplate,
)
+
+# Compute schemas
+from .compute.nios import UDPNIO, TAPNIO, EthernetNIO
+from .compute.atm_switch_nodes import ATMSwitchCreate, ATMSwitchUpdate, ATMSwitch
+from .compute.cloud_nodes import CloudCreate, CloudUpdate, Cloud
+from .compute.docker_nodes import DockerCreate, DockerUpdate, Docker
+from .compute.dynamips_nodes import DynamipsCreate, DynamipsUpdate, Dynamips
+from .compute.ethernet_hub_nodes import EthernetHubCreate, EthernetHubUpdate, EthernetHub
+from .compute.ethernet_switch_nodes import EthernetSwitchCreate, EthernetSwitchUpdate, EthernetSwitch
+from .compute.frame_relay_switch_nodes import FrameRelaySwitchCreate, FrameRelaySwitchUpdate, FrameRelaySwitch
+from .compute.qemu_nodes import QemuCreate, QemuUpdate, QemuImageCreate, QemuImageUpdate, QemuDiskResize, Qemu
+from .compute.iou_nodes import IOUCreate, IOUUpdate, IOUStart, IOU
+from .compute.nat_nodes import NATCreate, NATUpdate, NAT
+from .compute.vpcs_nodes import VPCSCreate, VPCSUpdate, VPCS
+from .compute.vmware_nodes import VMwareCreate, VMwareUpdate, VMware
+from .compute.virtualbox_nodes import VirtualBoxCreate, VirtualBoxUpdate, VirtualBox
diff --git a/gns3server/schemas/common.py b/gns3server/schemas/common.py
index 85ae01d3..e524384f 100644
--- a/gns3server/schemas/common.py
+++ b/gns3server/schemas/common.py
@@ -16,6 +16,7 @@
from pydantic import BaseModel, Field
from typing import Optional, Union
+from enum import Enum
class ErrorMessage(BaseModel):
@@ -26,14 +27,45 @@ class ErrorMessage(BaseModel):
message: str
-class Label(BaseModel):
+class NodeStatus(str, Enum):
"""
- Label data.
-
+ Supported node statuses.
"""
- text: str
- style: Optional[Union[str, None]] = Field(None, description="SVG style attribute. Apply default style if null")
- x: Optional[Union[int, None]] = Field(None, description="Relative X position of the label. Center it if null")
- y: Optional[int] = Field(None, description="Relative Y position of the label")
- rotation: Optional[int] = Field(None, ge=-359, le=360, description="Rotation of the label")
+ stopped = "stopped"
+ started = "started"
+ suspended = "suspended"
+
+
+class CustomAdapter(BaseModel):
+ """
+ Custom adapter data.
+ """
+
+ adapter_number: int
+ port_name: Optional[str] = None
+ adapter_type: Optional[str] = None
+ mac_address: Optional[str] = Field(None, regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
+
+
+class ConsoleType(str, Enum):
+ """
+ Supported console types.
+ """
+
+ vnc = "vnc"
+ telnet = "telnet"
+ http = "http"
+ https = "https"
+ spice = "spice"
+ spice_agent = "spice+agent"
+ none = "none"
+
+
+class AuxType(str, Enum):
+ """
+ Supported auxiliary console types.
+ """
+
+ telnet = "telnet"
+ none = "none"
diff --git a/gns3server/handlers/api/compute/ethernet_switch_handler.py b/gns3server/schemas/compute/__init__.py
similarity index 100%
rename from gns3server/handlers/api/compute/ethernet_switch_handler.py
rename to gns3server/schemas/compute/__init__.py
diff --git a/gns3server/schemas/atm_switch_nodes.py b/gns3server/schemas/compute/atm_switch_nodes.py
similarity index 97%
rename from gns3server/schemas/atm_switch_nodes.py
rename to gns3server/schemas/compute/atm_switch_nodes.py
index 6f9e55b1..836fbfa3 100644
--- a/gns3server/schemas/atm_switch_nodes.py
+++ b/gns3server/schemas/compute/atm_switch_nodes.py
@@ -18,7 +18,7 @@ from pydantic import BaseModel
from typing import Optional
from uuid import UUID
-from .nodes import NodeStatus
+from ..common import NodeStatus
class ATMSwitchBase(BaseModel):
diff --git a/gns3server/schemas/cloud_nodes.py b/gns3server/schemas/compute/cloud_nodes.py
similarity index 99%
rename from gns3server/schemas/cloud_nodes.py
rename to gns3server/schemas/compute/cloud_nodes.py
index 7ef0fe02..92d8aadd 100644
--- a/gns3server/schemas/cloud_nodes.py
+++ b/gns3server/schemas/compute/cloud_nodes.py
@@ -19,7 +19,7 @@ from typing import Optional, Union, List
from enum import Enum
from uuid import UUID
-from .nodes import NodeStatus
+from ..common import NodeStatus
class HostInterfaceType(Enum):
diff --git a/gns3server/schemas/docker_nodes.py b/gns3server/schemas/compute/docker_nodes.py
similarity index 97%
rename from gns3server/schemas/docker_nodes.py
rename to gns3server/schemas/compute/docker_nodes.py
index 4f033c85..7129aaae 100644
--- a/gns3server/schemas/docker_nodes.py
+++ b/gns3server/schemas/compute/docker_nodes.py
@@ -18,7 +18,7 @@ from pydantic import BaseModel, Field
from typing import Optional, List
from uuid import UUID
-from .nodes import CustomAdapter, ConsoleType, AuxType, NodeStatus
+from ..common import NodeStatus, CustomAdapter, ConsoleType, AuxType
class DockerBase(BaseModel):
diff --git a/gns3server/schemas/dynamips_nodes.py b/gns3server/schemas/compute/dynamips_nodes.py
similarity index 99%
rename from gns3server/schemas/dynamips_nodes.py
rename to gns3server/schemas/compute/dynamips_nodes.py
index 1289c013..64bc07c2 100644
--- a/gns3server/schemas/dynamips_nodes.py
+++ b/gns3server/schemas/compute/dynamips_nodes.py
@@ -20,7 +20,7 @@ from typing import Optional, List
from enum import Enum
from uuid import UUID
-from .nodes import NodeStatus
+from ..common import NodeStatus
class DynamipsPlatform(str, Enum):
diff --git a/gns3server/schemas/ethernet_hub_nodes.py b/gns3server/schemas/compute/ethernet_hub_nodes.py
similarity index 97%
rename from gns3server/schemas/ethernet_hub_nodes.py
rename to gns3server/schemas/compute/ethernet_hub_nodes.py
index e559a6d4..803be8f3 100644
--- a/gns3server/schemas/ethernet_hub_nodes.py
+++ b/gns3server/schemas/compute/ethernet_hub_nodes.py
@@ -18,7 +18,7 @@ from pydantic import BaseModel
from typing import Optional, List
from uuid import UUID
-from .nodes import NodeStatus
+from ..common import NodeStatus
class EthernetHubPort(BaseModel):
diff --git a/gns3server/schemas/ethernet_switch_nodes.py b/gns3server/schemas/compute/ethernet_switch_nodes.py
similarity index 98%
rename from gns3server/schemas/ethernet_switch_nodes.py
rename to gns3server/schemas/compute/ethernet_switch_nodes.py
index 9b1050ec..0edd7f1b 100644
--- a/gns3server/schemas/ethernet_switch_nodes.py
+++ b/gns3server/schemas/compute/ethernet_switch_nodes.py
@@ -19,7 +19,7 @@ from typing import Optional, List
from uuid import UUID
from enum import Enum
-from .nodes import NodeStatus
+from ..common import NodeStatus
class EthernetSwitchPortType(Enum):
diff --git a/gns3server/schemas/frame_relay_switch_nodes.py b/gns3server/schemas/compute/frame_relay_switch_nodes.py
similarity index 97%
rename from gns3server/schemas/frame_relay_switch_nodes.py
rename to gns3server/schemas/compute/frame_relay_switch_nodes.py
index fb6e580c..6b759eb4 100644
--- a/gns3server/schemas/frame_relay_switch_nodes.py
+++ b/gns3server/schemas/compute/frame_relay_switch_nodes.py
@@ -18,7 +18,7 @@ from pydantic import BaseModel
from typing import Optional
from uuid import UUID
-from .nodes import NodeStatus
+from ..common import NodeStatus
class FrameRelaySwitchBase(BaseModel):
diff --git a/gns3server/schemas/iou_nodes.py b/gns3server/schemas/compute/iou_nodes.py
similarity index 98%
rename from gns3server/schemas/iou_nodes.py
rename to gns3server/schemas/compute/iou_nodes.py
index f237fdd9..aa09323b 100644
--- a/gns3server/schemas/iou_nodes.py
+++ b/gns3server/schemas/compute/iou_nodes.py
@@ -18,7 +18,7 @@ from pydantic import BaseModel, Field
from typing import Optional
from uuid import UUID
-from .nodes import ConsoleType, NodeStatus
+from ..common import NodeStatus, ConsoleType
class IOUBase(BaseModel):
diff --git a/gns3server/schemas/nat_nodes.py b/gns3server/schemas/compute/nat_nodes.py
similarity index 98%
rename from gns3server/schemas/nat_nodes.py
rename to gns3server/schemas/compute/nat_nodes.py
index d2edabf2..755ac664 100644
--- a/gns3server/schemas/nat_nodes.py
+++ b/gns3server/schemas/compute/nat_nodes.py
@@ -19,7 +19,7 @@ from typing import Optional, Union, List
from enum import Enum
from uuid import UUID
-from .nodes import NodeStatus
+from ..common import NodeStatus
class HostInterfaceType(Enum):
diff --git a/gns3server/schemas/nios.py b/gns3server/schemas/compute/nios.py
similarity index 96%
rename from gns3server/schemas/nios.py
rename to gns3server/schemas/compute/nios.py
index 10514a3b..75ab4b5b 100644
--- a/gns3server/schemas/nios.py
+++ b/gns3server/schemas/compute/nios.py
@@ -16,9 +16,8 @@
from pydantic import BaseModel, Field
-from typing import Optional, Union, Generic
+from typing import Optional
from enum import Enum
-from uuid import UUID
class UDPNIOType(Enum):
diff --git a/gns3server/schemas/qemu_nodes.py b/gns3server/schemas/compute/qemu_nodes.py
similarity index 99%
rename from gns3server/schemas/qemu_nodes.py
rename to gns3server/schemas/compute/qemu_nodes.py
index 6433f5d9..de464fef 100644
--- a/gns3server/schemas/qemu_nodes.py
+++ b/gns3server/schemas/compute/qemu_nodes.py
@@ -19,7 +19,7 @@ from typing import Optional, List
from enum import Enum
from uuid import UUID
-from .nodes import CustomAdapter, NodeStatus
+from ..common import NodeStatus, CustomAdapter
class QemuPlatform(str, Enum):
diff --git a/gns3server/schemas/virtualbox_nodes.py b/gns3server/schemas/compute/virtualbox_nodes.py
similarity index 98%
rename from gns3server/schemas/virtualbox_nodes.py
rename to gns3server/schemas/compute/virtualbox_nodes.py
index 72fc1144..53f93975 100644
--- a/gns3server/schemas/virtualbox_nodes.py
+++ b/gns3server/schemas/compute/virtualbox_nodes.py
@@ -19,7 +19,7 @@ from typing import Optional, List
from enum import Enum
from uuid import UUID
-from .nodes import NodeStatus, CustomAdapter
+from ..common import NodeStatus, CustomAdapter
class VirtualBoxConsoleType(str, Enum):
diff --git a/gns3server/schemas/vmware_nodes.py b/gns3server/schemas/compute/vmware_nodes.py
similarity index 98%
rename from gns3server/schemas/vmware_nodes.py
rename to gns3server/schemas/compute/vmware_nodes.py
index 4a3f2fc9..a2fb26f2 100644
--- a/gns3server/schemas/vmware_nodes.py
+++ b/gns3server/schemas/compute/vmware_nodes.py
@@ -19,7 +19,7 @@ from typing import Optional, List
from enum import Enum
from uuid import UUID
-from .nodes import NodeStatus, CustomAdapter
+from ..common import NodeStatus, CustomAdapter
class VMwareConsoleType(str, Enum):
diff --git a/gns3server/schemas/vpcs_nodes.py b/gns3server/schemas/compute/vpcs_nodes.py
similarity index 97%
rename from gns3server/schemas/vpcs_nodes.py
rename to gns3server/schemas/compute/vpcs_nodes.py
index 324be1a7..6373182c 100644
--- a/gns3server/schemas/vpcs_nodes.py
+++ b/gns3server/schemas/compute/vpcs_nodes.py
@@ -19,7 +19,7 @@ from typing import Optional
from enum import Enum
from uuid import UUID
-from .nodes import NodeStatus, CustomAdapter
+from ..common import NodeStatus
class ConsoleType(str, Enum):
diff --git a/gns3server/schemas/config.py b/gns3server/schemas/config.py
index c30dada7..d692cf9e 100644
--- a/gns3server/schemas/config.py
+++ b/gns3server/schemas/config.py
@@ -15,7 +15,7 @@
# along with this program. If not, see .
from enum import Enum
-from pydantic import BaseModel, Field, SecretStr, FilePath, validator
+from pydantic import BaseModel, Field, SecretStr, FilePath, DirectoryPath, validator
from typing import List
@@ -113,7 +113,7 @@ class ServerSettings(BaseModel):
protocol: ServerProtocol = ServerProtocol.http
host: str = "0.0.0.0"
port: int = Field(3080, gt=0, le=65535)
- secrets_dir: str = None
+ secrets_dir: DirectoryPath = None
certfile: FilePath = None
certkey: FilePath = None
enable_ssl: bool = False
@@ -167,7 +167,7 @@ class ServerSettings(BaseModel):
if v is True:
if "user" not in values or not values["user"]:
- raise ValueError("HTTP authentication is enabled but no username is configured")
+ raise ValueError("HTTP authentication is enabled but user is not configured")
return v
@validator("enable_ssl")
diff --git a/gns3server/handlers/api/controller/link_handler.py b/gns3server/schemas/controller/__init__.py
similarity index 100%
rename from gns3server/handlers/api/controller/link_handler.py
rename to gns3server/schemas/controller/__init__.py
diff --git a/gns3server/schemas/base.py b/gns3server/schemas/controller/base.py
similarity index 100%
rename from gns3server/schemas/base.py
rename to gns3server/schemas/controller/base.py
diff --git a/gns3server/schemas/capabilities.py b/gns3server/schemas/controller/capabilities.py
similarity index 100%
rename from gns3server/schemas/capabilities.py
rename to gns3server/schemas/controller/capabilities.py
diff --git a/gns3server/schemas/computes.py b/gns3server/schemas/controller/computes.py
similarity index 100%
rename from gns3server/schemas/computes.py
rename to gns3server/schemas/controller/computes.py
diff --git a/gns3server/schemas/drawings.py b/gns3server/schemas/controller/drawings.py
similarity index 100%
rename from gns3server/schemas/drawings.py
rename to gns3server/schemas/controller/drawings.py
diff --git a/gns3server/schemas/gns3vm.py b/gns3server/schemas/controller/gns3vm.py
similarity index 100%
rename from gns3server/schemas/gns3vm.py
rename to gns3server/schemas/controller/gns3vm.py
diff --git a/gns3server/schemas/iou_license.py b/gns3server/schemas/controller/iou_license.py
similarity index 100%
rename from gns3server/schemas/iou_license.py
rename to gns3server/schemas/controller/iou_license.py
diff --git a/gns3server/schemas/filters.py b/gns3server/schemas/controller/labels.py
similarity index 51%
rename from gns3server/schemas/filters.py
rename to gns3server/schemas/controller/labels.py
index 52bafdd0..2eb77026 100644
--- a/gns3server/schemas/filters.py
+++ b/gns3server/schemas/controller/labels.py
@@ -1,6 +1,5 @@
-#!/usr/bin/env python
#
-# Copyright (C) 2020 GNS3 Technologies Inc.
+# Copyright (C) 2021 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
@@ -14,3 +13,18 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+
+from pydantic import BaseModel, Field
+from typing import Optional, Union
+
+
+class Label(BaseModel):
+ """
+ Label data.
+ """
+
+ text: str
+ style: Optional[Union[str, None]] = Field(None, description="SVG style attribute. Apply default style if null")
+ x: Optional[Union[int, None]] = Field(None, description="Relative X position of the label. Center it if null")
+ y: Optional[int] = Field(None, description="Relative Y position of the label")
+ rotation: Optional[int] = Field(None, ge=-359, le=360, description="Rotation of the label")
diff --git a/gns3server/schemas/links.py b/gns3server/schemas/controller/links.py
similarity index 98%
rename from gns3server/schemas/links.py
rename to gns3server/schemas/controller/links.py
index 98efba28..3a37ccbc 100644
--- a/gns3server/schemas/links.py
+++ b/gns3server/schemas/controller/links.py
@@ -19,7 +19,7 @@ from typing import List, Optional
from enum import Enum
from uuid import UUID
-from .common import Label
+from .labels import Label
class LinkNode(BaseModel):
diff --git a/gns3server/schemas/nodes.py b/gns3server/schemas/controller/nodes.py
similarity index 70%
rename from gns3server/schemas/nodes.py
rename to gns3server/schemas/controller/nodes.py
index 3a6f2802..1e59fef1 100644
--- a/gns3server/schemas/nodes.py
+++ b/gns3server/schemas/controller/nodes.py
@@ -14,12 +14,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from pydantic import BaseModel, Field
+from pydantic import BaseModel, Field, validator
from typing import List, Optional, Union
from enum import Enum
-from uuid import UUID
+from uuid import UUID, uuid4
-from .common import Label
+from .labels import Label
+from ..common import ConsoleType, NodeStatus, CustomAdapter
class NodeType(str, Enum):
@@ -74,39 +75,6 @@ class DataLinkType(str, Enum):
ppp = "DLT_PPP_SERIAL"
-class ConsoleType(str, Enum):
- """
- Supported console types.
- """
-
- vnc = "vnc"
- telnet = "telnet"
- http = "http"
- https = "https"
- spice = "spice"
- spice_agent = "spice+agent"
- none = "none"
-
-
-class AuxType(str, Enum):
- """
- Supported auxiliary console types.
- """
-
- telnet = "telnet"
- none = "none"
-
-
-class NodeStatus(str, Enum):
- """
- Supported node statuses.
- """
-
- stopped = "stopped"
- started = "started"
- suspended = "suspended"
-
-
class NodeCapture(BaseModel):
"""
Node capture data.
@@ -116,17 +84,6 @@ class NodeCapture(BaseModel):
data_link_type: Optional[DataLinkType] = None
-class CustomAdapter(BaseModel):
- """
- Custom adapter data.
- """
-
- adapter_number: int
- port_name: Optional[str] = None
- adapter_type: Optional[str] = None
- mac_address: Optional[str] = Field(None, regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
-
-
class NodePort(BaseModel):
"""
Node port data.
@@ -142,7 +99,7 @@ class NodePort(BaseModel):
mac_address: Union[str, None] = Field(None, regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
-class Node(BaseModel):
+class NodeBase(BaseModel):
"""
Node data.
"""
@@ -150,44 +107,56 @@ class Node(BaseModel):
compute_id: Union[UUID, str]
name: str
node_type: NodeType
- project_id: Optional[UUID] = None
+
node_id: Optional[UUID] = None
- template_id: Optional[UUID] = Field(
- None, description="Template UUID from which the node has been created. Read only"
- )
- node_directory: Optional[str] = Field(None, description="Working directory of the node. Read only")
- command_line: Optional[str] = Field(None, description="Command line use to start the node")
+
console: Optional[int] = Field(None, gt=0, le=65535, description="Console TCP port")
- 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",
- )
+
console_type: Optional[ConsoleType] = None
console_auto_start: Optional[bool] = Field(
- None, description="Automatically start the console when the node has started"
+ 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(None, description="Properties specific to an emulator")
- status: Optional[NodeStatus] = None
+ properties: Optional[dict] = Field(default_factory=dict, description="Properties specific to an emulator")
+
label: Optional[Label] = None
symbol: Optional[str] = None
- width: Optional[int] = Field(None, description="Width of the node (Read only)")
- height: Optional[int] = Field(None, description="Height of the node (Read only)")
- x: Optional[int] = None
- y: Optional[int] = None
- z: Optional[int] = None
- locked: Optional[bool] = Field(None, description="Whether the element locked or not")
+
+ 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, description="Formatting for port name {0} will be replace by port number"
+ 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
- ports: Optional[List[NodePort]] = Field(None, description="List of node ports (read only)")
+
+ @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 NodeUpdate(Node):
+class NodeCreate(NodeBase):
+
+ node_id: UUID = Field(default_factory=uuid4)
+
+
+class NodeUpdate(NodeBase):
"""
Data to update a node.
"""
@@ -197,6 +166,23 @@ class NodeUpdate(Node):
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.
diff --git a/gns3server/schemas/projects.py b/gns3server/schemas/controller/projects.py
similarity index 100%
rename from gns3server/schemas/projects.py
rename to gns3server/schemas/controller/projects.py
diff --git a/gns3server/schemas/snapshots.py b/gns3server/schemas/controller/snapshots.py
similarity index 100%
rename from gns3server/schemas/snapshots.py
rename to gns3server/schemas/controller/snapshots.py
diff --git a/gns3server/schemas/templates.py b/gns3server/schemas/controller/templates/__init__.py
similarity index 94%
rename from gns3server/schemas/templates.py
rename to gns3server/schemas/controller/templates/__init__.py
index f9de0b03..74866b2e 100644
--- a/gns3server/schemas/templates.py
+++ b/gns3server/schemas/controller/templates/__init__.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2020 GNS3 Technologies Inc.
+# Copyright (C) 2021 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
@@ -19,8 +19,8 @@ from typing import Optional, Union
from enum import Enum
from uuid import UUID
-from .nodes import NodeType
-from .base import DateTimeModelMixin
+from ..nodes import NodeType
+from ..base import DateTimeModelMixin
class Category(str, Enum):
diff --git a/gns3server/schemas/cloud_templates.py b/gns3server/schemas/controller/templates/cloud_templates.py
similarity index 90%
rename from gns3server/schemas/cloud_templates.py
rename to gns3server/schemas/controller/templates/cloud_templates.py
index 6ae199f1..37fd1942 100644
--- a/gns3server/schemas/cloud_templates.py
+++ b/gns3server/schemas/controller/templates/cloud_templates.py
@@ -15,8 +15,13 @@
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .cloud_nodes import EthernetPort, TAPPort, UDPPort, CloudConsoleType
+from . import Category, TemplateBase
+from gns3server.schemas.compute.cloud_nodes import (
+ EthernetPort,
+ TAPPort,
+ UDPPort,
+ CloudConsoleType
+)
from pydantic import Field
from typing import Optional, Union, List
diff --git a/gns3server/schemas/docker_templates.py b/gns3server/schemas/controller/templates/docker_templates.py
similarity index 95%
rename from gns3server/schemas/docker_templates.py
rename to gns3server/schemas/controller/templates/docker_templates.py
index 48f16e1a..ceb05040 100644
--- a/gns3server/schemas/docker_templates.py
+++ b/gns3server/schemas/controller/templates/docker_templates.py
@@ -15,9 +15,8 @@
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .nodes import CustomAdapter
-from .docker_nodes import ConsoleType, AuxType
+from . import Category, TemplateBase
+from ...common import ConsoleType, AuxType, CustomAdapter
from pydantic import Field
from typing import Optional, List
diff --git a/gns3server/schemas/dynamips_templates.py b/gns3server/schemas/controller/templates/dynamips_templates.py
similarity index 98%
rename from gns3server/schemas/dynamips_templates.py
rename to gns3server/schemas/controller/templates/dynamips_templates.py
index 308a90f5..9598505e 100644
--- a/gns3server/schemas/dynamips_templates.py
+++ b/gns3server/schemas/controller/templates/dynamips_templates.py
@@ -14,8 +14,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .dynamips_nodes import (
+from . import Category, TemplateBase
+
+from gns3server.schemas.compute.dynamips_nodes import (
DynamipsConsoleType,
DynamipsPlatform,
DynamipsAdapters,
diff --git a/gns3server/schemas/ethernet_hub_templates.py b/gns3server/schemas/controller/templates/ethernet_hub_templates.py
similarity index 92%
rename from gns3server/schemas/ethernet_hub_templates.py
rename to gns3server/schemas/controller/templates/ethernet_hub_templates.py
index 947d41db..7b61cd01 100644
--- a/gns3server/schemas/ethernet_hub_templates.py
+++ b/gns3server/schemas/controller/templates/ethernet_hub_templates.py
@@ -14,9 +14,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-from .templates import Category, TemplateBase
-from .ethernet_hub_nodes import EthernetHubPort
+from . import Category, TemplateBase
+from gns3server.schemas.compute.ethernet_hub_nodes import EthernetHubPort
from pydantic import Field
from typing import Optional, List
diff --git a/gns3server/schemas/ethernet_switch_templates.py b/gns3server/schemas/controller/templates/ethernet_switch_templates.py
similarity index 94%
rename from gns3server/schemas/ethernet_switch_templates.py
rename to gns3server/schemas/controller/templates/ethernet_switch_templates.py
index 51373e31..2e42aaa2 100644
--- a/gns3server/schemas/ethernet_switch_templates.py
+++ b/gns3server/schemas/controller/templates/ethernet_switch_templates.py
@@ -15,8 +15,8 @@
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .ethernet_switch_nodes import EthernetSwitchPort
+from . import Category, TemplateBase
+from gns3server.schemas.compute.ethernet_switch_nodes import EthernetSwitchPort
from pydantic import Field
from typing import Optional, List
diff --git a/gns3server/schemas/iou_templates.py b/gns3server/schemas/controller/templates/iou_templates.py
similarity index 95%
rename from gns3server/schemas/iou_templates.py
rename to gns3server/schemas/controller/templates/iou_templates.py
index 0c7100b9..f7bba8d4 100644
--- a/gns3server/schemas/iou_templates.py
+++ b/gns3server/schemas/controller/templates/iou_templates.py
@@ -15,8 +15,8 @@
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .iou_nodes import ConsoleType
+from . import Category, TemplateBase
+from gns3server.schemas.compute.iou_nodes import ConsoleType
from pydantic import Field
from typing import Optional
diff --git a/gns3server/schemas/qemu_templates.py b/gns3server/schemas/controller/templates/qemu_templates.py
similarity index 98%
rename from gns3server/schemas/qemu_templates.py
rename to gns3server/schemas/controller/templates/qemu_templates.py
index 8ab0d452..f69eb23a 100644
--- a/gns3server/schemas/qemu_templates.py
+++ b/gns3server/schemas/controller/templates/qemu_templates.py
@@ -15,8 +15,8 @@
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .qemu_nodes import (
+from . import Category, TemplateBase
+from gns3server.schemas.compute.qemu_nodes import (
QemuConsoleType,
QemuPlatform,
QemuAdapterType,
diff --git a/gns3server/schemas/virtualbox_templates.py b/gns3server/schemas/controller/templates/virtualbox_templates.py
similarity index 93%
rename from gns3server/schemas/virtualbox_templates.py
rename to gns3server/schemas/controller/templates/virtualbox_templates.py
index 967bea3d..82cd63f4 100644
--- a/gns3server/schemas/virtualbox_templates.py
+++ b/gns3server/schemas/controller/templates/virtualbox_templates.py
@@ -14,8 +14,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .virtualbox_nodes import VirtualBoxConsoleType, VirtualBoxAdapterType, VirtualBoxOnCloseAction, CustomAdapter
+from . import Category, TemplateBase
+from gns3server.schemas.compute.virtualbox_nodes import (
+ VirtualBoxConsoleType,
+ VirtualBoxAdapterType,
+ VirtualBoxOnCloseAction,
+ CustomAdapter
+)
from pydantic import Field
from typing import Optional, List
diff --git a/gns3server/schemas/vmware_templates.py b/gns3server/schemas/controller/templates/vmware_templates.py
similarity index 93%
rename from gns3server/schemas/vmware_templates.py
rename to gns3server/schemas/controller/templates/vmware_templates.py
index e0d6cef0..a8d604d8 100644
--- a/gns3server/schemas/vmware_templates.py
+++ b/gns3server/schemas/controller/templates/vmware_templates.py
@@ -15,8 +15,13 @@
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .vmware_nodes import VMwareConsoleType, VMwareAdapterType, VMwareOnCloseAction, CustomAdapter
+from . import Category, TemplateBase
+from gns3server.schemas.compute.vmware_nodes import (
+ VMwareConsoleType,
+ VMwareAdapterType,
+ VMwareOnCloseAction,
+ CustomAdapter
+)
from pydantic import Field
from typing import Optional, List
diff --git a/gns3server/schemas/vpcs_templates.py b/gns3server/schemas/controller/templates/vpcs_templates.py
similarity index 92%
rename from gns3server/schemas/vpcs_templates.py
rename to gns3server/schemas/controller/templates/vpcs_templates.py
index 18291c89..f75009ce 100644
--- a/gns3server/schemas/vpcs_templates.py
+++ b/gns3server/schemas/controller/templates/vpcs_templates.py
@@ -15,8 +15,8 @@
# along with this program. If not, see .
-from .templates import Category, TemplateBase
-from .vpcs_nodes import ConsoleType
+from . import Category, TemplateBase
+from gns3server.schemas.compute.vpcs_nodes import ConsoleType
from pydantic import Field
from typing import Optional
diff --git a/gns3server/schemas/tokens.py b/gns3server/schemas/controller/tokens.py
similarity index 100%
rename from gns3server/schemas/tokens.py
rename to gns3server/schemas/controller/tokens.py
diff --git a/gns3server/schemas/topology.py b/gns3server/schemas/controller/topology.py
similarity index 100%
rename from gns3server/schemas/topology.py
rename to gns3server/schemas/controller/topology.py
diff --git a/gns3server/schemas/users.py b/gns3server/schemas/controller/users.py
similarity index 100%
rename from gns3server/schemas/users.py
rename to gns3server/schemas/controller/users.py
diff --git a/gns3server/services/authentication.py b/gns3server/services/authentication.py
index e2a4b64f..021db36e 100644
--- a/gns3server/services/authentication.py
+++ b/gns3server/services/authentication.py
@@ -21,7 +21,7 @@ from passlib.context import CryptContext
from typing import Optional
from fastapi import HTTPException, status
-from gns3server.schemas.tokens import TokenData
+from gns3server.schemas.controller.tokens import TokenData
from gns3server.config import Config
from pydantic import ValidationError
diff --git a/tests/conftest.py b/tests/conftest.py
index 072c124e..7996955c 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -344,13 +344,27 @@ def run_around_tests(monkeypatch, config, port_manager):#port_manager, controlle
module._instance = None
config.settings.Controller.jwt_secret_key = DEFAULT_JWT_SECRET_KEY
- config.settings.Server.secrets_dir = os.path.join(tmppath, 'secrets')
- os.makedirs(os.path.join(tmppath, 'projects'))
- config.settings.Server.projects_path = os.path.join(tmppath, 'projects')
- config.settings.Server.symbols_path = os.path.join(tmppath, 'symbols')
- config.settings.Server.images_path = os.path.join(tmppath, 'images')
- config.settings.Server.appliances_path = os.path.join(tmppath, 'appliances')
+ secrets_dir = os.path.join(tmppath, 'secrets')
+ os.makedirs(secrets_dir)
+ config.settings.Server.secrets_dir = secrets_dir
+
+ projects_dir = os.path.join(tmppath, 'projects')
+ os.makedirs(projects_dir)
+ config.settings.Server.projects_path = projects_dir
+
+ symbols_dir = os.path.join(tmppath, 'symbols')
+ os.makedirs(symbols_dir)
+ config.settings.Server.symbols_path = symbols_dir
+
+ images_dir = os.path.join(tmppath, 'images')
+ os.makedirs(images_dir)
+ config.settings.Server.images_path = images_dir
+
+ appliances_dir = os.path.join(tmppath, 'appliances')
+ os.makedirs(appliances_dir)
+ config.settings.Server.appliances_path = appliances_dir
+
config.settings.Server.ubridge_path = os.path.join(tmppath, 'bin', 'ubridge')
config.settings.Server.local = True
config.settings.Server.enable_http_auth = False