diff --git a/.github/workflows/publish_api_documentation.yml b/.github/workflows/publish_api_documentation.yml
index 9f6fa41e..348ebe16 100644
--- a/.github/workflows/publish_api_documentation.yml
+++ b/.github/workflows/publish_api_documentation.yml
@@ -15,10 +15,15 @@ jobs:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- ref: "3.0"
+ ref: "gh-pages"
- uses: actions/setup-python@v2
with:
python-version: 3.6
+ - name: Merge changes from 3.0 branch
+ run: |
+ git config user.name github-actions
+ git config user.email github-actions@github.com
+ git merge origin/3.0 -X theirs
- name: Install dependencies
run: |
python -m pip install --upgrade pip
@@ -32,11 +37,7 @@ jobs:
python3 publish_api_documentation.py
- name: Publish the API documentation
run: |
- git config user.name github-actions
- git config user.email github-actions@github.com
git add docs
git status
git commit -m "Publish API documentation"
- git checkout gh-pages
- git merge 3.0 -X theirs
git push
diff --git a/docs/swagger.html b/docs/redoc.html
similarity index 100%
rename from docs/swagger.html
rename to docs/redoc.html
diff --git a/gns3server/app.py b/gns3server/app.py
index 0cc3d035..bdf41541 100644
--- a/gns3server/app.py
+++ b/gns3server/app.py
@@ -49,7 +49,7 @@ log = logging.getLogger(__name__)
app = FastAPI(title="GNS3 controller API",
description="This page describes the public controller API for GNS3",
- version="v2")
+ version="v3")
origins = [
"http://127.0.0.1",
@@ -71,8 +71,8 @@ app.add_middleware(
)
app.include_router(index.router, tags=["Index"])
-app.include_router(controller.router, prefix="/v2")
-app.mount("/v2/compute", compute_api)
+app.include_router(controller.router, prefix="/v3")
+app.mount("/v3/compute", compute_api)
@app.exception_handler(ControllerError)
diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py
index 64e5c637..68bd9e75 100644
--- a/gns3server/compute/qemu/qemu_vm.py
+++ b/gns3server/compute/qemu/qemu_vm.py
@@ -44,11 +44,11 @@ from ..error import NodeError, ImageMissingError
from ..nios.nio_udp import NIOUDP
from ..nios.nio_tap import NIOTAP
from ..base_node import BaseNode
-from ...schemas.qemu import QEMU_OBJECT_SCHEMA, QEMU_PLATFORMS
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
import logging
log = logging.getLogger(__name__)
@@ -216,7 +216,10 @@ class QemuVM(BaseNode):
self._platform = "i386"
else:
self._platform = re.sub(r'^qemu-system-(.*)$', r'\1', qemu_bin, re.IGNORECASE)
- if self._platform.split(".")[0] not in QEMU_PLATFORMS:
+
+ try:
+ QemuPlatform(self._platform.split(".")[0])
+ except ValueError:
raise QemuError("Platform {} is unknown".format(self._platform))
log.info('QEMU VM "{name}" [{id}] has set the QEMU path to {qemu_path}'.format(name=self._name,
id=self._id,
@@ -2288,7 +2291,7 @@ class QemuVM(BaseNode):
"node_directory": self.working_path
}
# Qemu has a long list of options. The JSON schema is the single source of information
- for field in QEMU_OBJECT_SCHEMA["required"]:
+ for field in Qemu.schema()["properties"]:
if field not in answer:
try:
answer[field] = getattr(self, field)
diff --git a/gns3server/controller/compute.py b/gns3server/controller/compute.py
index 1db7933d..0323037e 100644
--- a/gns3server/controller/compute.py
+++ b/gns3server/controller/compute.py
@@ -497,7 +497,7 @@ class Compute:
host = "[{}]".format(host)
elif host == "0.0.0.0":
host = "127.0.0.1"
- return "{}://{}:{}/v2/compute{}".format(self._protocol, host, self._port, path)
+ return "{}://{}:{}/v3/compute{}".format(self._protocol, host, self._port, path)
def get_url(self, path):
""" Returns URL for specific path at Compute"""
diff --git a/gns3server/controller/gns3vm/virtualbox_gns3_vm.py b/gns3server/controller/gns3vm/virtualbox_gns3_vm.py
index fb9fbc99..e06828de 100644
--- a/gns3server/controller/gns3vm/virtualbox_gns3_vm.py
+++ b/gns3server/controller/gns3vm/virtualbox_gns3_vm.py
@@ -310,7 +310,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
remaining_try = 300
while remaining_try > 0:
try:
- async with HTTPClient.get(f"http://127.0.0.1:{api_port}/v2/compute/network/interfaces") as resp:
+ async with HTTPClient.get(f"http://127.0.0.1:{api_port}/v3/compute/network/interfaces") as resp:
if resp.status < 300:
try:
json_data = await resp.json()
diff --git a/gns3server/controller/link.py b/gns3server/controller/link.py
index 6d02adee..8e461858 100644
--- a/gns3server/controller/link.py
+++ b/gns3server/controller/link.py
@@ -345,11 +345,12 @@ class Link:
node_id = self.capture_node["node"].id
adapter_number = self.capture_node["adapter_number"]
port_number = self.capture_node["port_number"]
- url = "/projects/{project_id}/{node_type}/nodes/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap".format(project_id=self.project.id,
- node_type=node_type,
- node_id=node_id,
- adapter_number=adapter_number,
- port_number=port_number)
+ url = "/projects/{project_id}/{node_type}/nodes/{node_id}/adapters/{adapter_number}/" \
+ "ports/{port_number}/capture/stream".format(project_id=self.project.id,
+ node_type=node_type,
+ node_id=node_id,
+ adapter_number=adapter_number,
+ port_number=port_number)
return compute._getUrl(url)
diff --git a/gns3server/controller/template.py b/gns3server/controller/template.py
index fd800c21..a5c725de 100644
--- a/gns3server/controller/template.py
+++ b/gns3server/controller/template.py
@@ -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 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.
diff --git a/gns3server/controller/template_manager.py b/gns3server/controller/template_manager.py
index ddd857bf..663d63e1 100644
--- a/gns3server/controller/template_manager.py
+++ b/gns3server/controller/template_manager.py
@@ -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
diff --git a/gns3server/controller/topology.py b/gns3server/controller/topology.py
index 91eca0b7..f934b569 100644
--- a/gns3server/controller/topology.py
+++ b/gns3server/controller/topology.py
@@ -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.schemas.topology import Topology
+from gns3server.schemas.dynamips_nodes import DynamipsCreate
+
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)
diff --git a/gns3server/endpoints/compute/__init__.py b/gns3server/endpoints/compute/__init__.py
index b75d8de9..04c1bfe3 100644
--- a/gns3server/endpoints/compute/__init__.py
+++ b/gns3server/endpoints/compute/__init__.py
@@ -51,7 +51,7 @@ from . import vpcs_nodes
compute_api = FastAPI(title="GNS3 compute API",
description="This page describes the private compute API for GNS3. PLEASE DO NOT USE DIRECTLY!",
- version="v2")
+ version="v3")
@compute_api.exception_handler(ComputeError)
diff --git a/gns3server/endpoints/compute/atm_switch_nodes.py b/gns3server/endpoints/compute/atm_switch_nodes.py
index 01fefef8..7b09a5fb 100644
--- a/gns3server/endpoints/compute/atm_switch_nodes.py
+++ b/gns3server/endpoints/compute/atm_switch_nodes.py
@@ -26,7 +26,7 @@ from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.dynamips import Dynamips
from gns3server.compute.dynamips.nodes.atm_switch import ATMSwitch
@@ -186,7 +186,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: ATMSwitch = De
await nio.delete()
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -202,7 +202,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop_capture",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: ATMSwitch = Depends(dep_node)):
@@ -214,7 +214,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: ATMSwitch =
await node.stop_capture(port_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: ATMSwitch = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/capabilities.py b/gns3server/endpoints/compute/capabilities.py
index bf930c38..67f0d567 100644
--- a/gns3server/endpoints/compute/capabilities.py
+++ b/gns3server/endpoints/compute/capabilities.py
@@ -27,7 +27,7 @@ from fastapi import APIRouter
from gns3server.version import __version__
from gns3server.compute import MODULES
from gns3server.utils.path import get_default_project_directory
-from gns3server.endpoints import schemas
+from gns3server import schemas
router = APIRouter()
diff --git a/gns3server/endpoints/compute/cloud_nodes.py b/gns3server/endpoints/compute/cloud_nodes.py
index af22cfa3..631c0341 100644
--- a/gns3server/endpoints/compute/cloud_nodes.py
+++ b/gns3server/endpoints/compute/cloud_nodes.py
@@ -27,7 +27,7 @@ from fastapi.responses import StreamingResponse
from typing import Union
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.builtin import Builtin
from gns3server.compute.builtin.nodes.cloud import Cloud
@@ -197,7 +197,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: Cloud = Depend
await node.remove_nio(port_number)
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -213,7 +213,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: Cloud = Depends(dep_node)):
diff --git a/gns3server/endpoints/compute/compute.py b/gns3server/endpoints/compute/compute.py
index 225c9bd9..854428e0 100644
--- a/gns3server/endpoints/compute/compute.py
+++ b/gns3server/endpoints/compute/compute.py
@@ -33,7 +33,7 @@ from gns3server.utils.interfaces import interfaces
from gns3server.compute.qemu import Qemu
from gns3server.compute.virtualbox import VirtualBox
from gns3server.compute.vmware import VMware
-from gns3server.endpoints import schemas
+from gns3server import schemas
from fastapi import APIRouter, HTTPException, Body, status
from fastapi.encoders import jsonable_encoder
diff --git a/gns3server/endpoints/compute/docker_nodes.py b/gns3server/endpoints/compute/docker_nodes.py
index 199c1664..e88664ef 100644
--- a/gns3server/endpoints/compute/docker_nodes.py
+++ b/gns3server/endpoints/compute/docker_nodes.py
@@ -26,7 +26,7 @@ from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.docker import Docker
from gns3server.compute.docker.docker_vm import DockerVM
@@ -262,7 +262,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: DockerVM = Dep
await node.adapter_remove_nio_binding(adapter_number)
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -278,7 +278,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": str(pcap_file_path)}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: DockerVM = Depends(dep_node)):
@@ -290,7 +290,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: DockerVM = D
await node.stop_capture(adapter_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: DockerVM = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/dynamips_nodes.py b/gns3server/endpoints/compute/dynamips_nodes.py
index bee788ba..6ba57047 100644
--- a/gns3server/endpoints/compute/dynamips_nodes.py
+++ b/gns3server/endpoints/compute/dynamips_nodes.py
@@ -31,7 +31,7 @@ from uuid import UUID
from gns3server.compute.dynamips import Dynamips
from gns3server.compute.dynamips.nodes.router import Router
from gns3server.compute.dynamips.dynamips_error import DynamipsError
-from gns3server.endpoints import schemas
+from gns3server import schemas
router = APIRouter()
@@ -219,7 +219,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: Router = Depen
await nio.delete()
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -242,7 +242,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: Router = Depends(dep_node)):
@@ -253,7 +253,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: Router = Dep
await node.stop_capture(adapter_number, port_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: Router = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/ethernet_hub_nodes.py b/gns3server/endpoints/compute/ethernet_hub_nodes.py
index bfb7aef1..06c46248 100644
--- a/gns3server/endpoints/compute/ethernet_hub_nodes.py
+++ b/gns3server/endpoints/compute/ethernet_hub_nodes.py
@@ -28,7 +28,7 @@ from uuid import UUID
from gns3server.compute.dynamips import Dynamips
from gns3server.compute.dynamips.nodes.ethernet_hub import EthernetHub
-from gns3server.endpoints import schemas
+from gns3server import schemas
router = APIRouter()
@@ -187,7 +187,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: EthernetHub =
await nio.delete()
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -203,7 +203,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: EthernetHub = Depends(dep_node)):
@@ -215,7 +215,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: EthernetHub
await node.stop_capture(port_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: EthernetHub = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/ethernet_switch_nodes.py b/gns3server/endpoints/compute/ethernet_switch_nodes.py
index be7e37aa..051338e3 100644
--- a/gns3server/endpoints/compute/ethernet_switch_nodes.py
+++ b/gns3server/endpoints/compute/ethernet_switch_nodes.py
@@ -28,7 +28,7 @@ from uuid import UUID
from gns3server.compute.dynamips import Dynamips
from gns3server.compute.dynamips.nodes.ethernet_switch import EthernetSwitch
-from gns3server.endpoints import schemas
+from gns3server import schemas
router = APIRouter()
@@ -186,7 +186,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: EthernetSwitch
await nio.delete()
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -202,7 +202,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int,port_number: int, node: EthernetSwitch = Depends(dep_node)):
@@ -214,7 +214,7 @@ async def stop_capture(adapter_number: int,port_number: int, node: EthernetSwitc
await node.stop_capture(port_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: EthernetSwitch = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/frame_relay_switch_nodes.py b/gns3server/endpoints/compute/frame_relay_switch_nodes.py
index 911c6f08..2728e81b 100644
--- a/gns3server/endpoints/compute/frame_relay_switch_nodes.py
+++ b/gns3server/endpoints/compute/frame_relay_switch_nodes.py
@@ -26,7 +26,7 @@ from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.dynamips import Dynamips
from gns3server.compute.dynamips.nodes.frame_relay_switch import FrameRelaySwitch
@@ -188,7 +188,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: FrameRelaySwit
await nio.delete()
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -204,7 +204,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: FrameRelaySwitch = Depends(dep_node)):
@@ -216,7 +216,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: FrameRelaySw
await node.stop_capture(port_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: FrameRelaySwitch = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/iou_nodes.py b/gns3server/endpoints/compute/iou_nodes.py
index 667bb9e4..be3320d9 100644
--- a/gns3server/endpoints/compute/iou_nodes.py
+++ b/gns3server/endpoints/compute/iou_nodes.py
@@ -27,7 +27,7 @@ from fastapi.responses import StreamingResponse
from typing import Union
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.iou import IOU
from gns3server.compute.iou.iou_vm import IOUVM
@@ -237,7 +237,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: IOUVM = Depend
await node.adapter_remove_nio_binding(adapter_number, port_number)
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -252,7 +252,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": str(pcap_file_path)}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)):
@@ -263,7 +263,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: IOUVM = Depe
await node.stop_capture(adapter_number, port_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: IOUVM = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/nat_nodes.py b/gns3server/endpoints/compute/nat_nodes.py
index a2c40f89..de255126 100644
--- a/gns3server/endpoints/compute/nat_nodes.py
+++ b/gns3server/endpoints/compute/nat_nodes.py
@@ -27,7 +27,7 @@ from fastapi.responses import StreamingResponse
from typing import Union
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.builtin import Builtin
from gns3server.compute.builtin.nodes.nat import Nat
@@ -192,7 +192,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: Nat = Depends(
await node.remove_nio(port_number)
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -208,7 +208,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: Nat = Depends(dep_node)):
@@ -220,7 +220,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: Nat = Depend
await node.stop_capture(port_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: Nat = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/projects.py b/gns3server/endpoints/compute/projects.py
index 8d392da9..dda59bc7 100644
--- a/gns3server/endpoints/compute/projects.py
+++ b/gns3server/endpoints/compute/projects.py
@@ -32,7 +32,7 @@ from uuid import UUID
from gns3server.compute.project_manager import ProjectManager
from gns3server.compute.project import Project
-from gns3server.endpoints import schemas
+from gns3server import schemas
router = APIRouter()
diff --git a/gns3server/endpoints/compute/qemu_nodes.py b/gns3server/endpoints/compute/qemu_nodes.py
index 222ac001..5e8ca4d0 100644
--- a/gns3server/endpoints/compute/qemu_nodes.py
+++ b/gns3server/endpoints/compute/qemu_nodes.py
@@ -27,7 +27,7 @@ from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.project_manager import ProjectManager
from gns3server.compute.qemu import Qemu
from gns3server.compute.qemu.qemu_vm import QemuVM
@@ -252,7 +252,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: QemuVM = Depen
await node.adapter_remove_nio_binding(adapter_number)
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -268,7 +268,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": str(pcap_file_path)}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: QemuVM = Depends(dep_node)):
@@ -280,7 +280,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: QemuVM = Dep
await node.stop_capture(adapter_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: QemuVM = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/virtualbox_nodes.py b/gns3server/endpoints/compute/virtualbox_nodes.py
index 661560cf..42b1df5c 100644
--- a/gns3server/endpoints/compute/virtualbox_nodes.py
+++ b/gns3server/endpoints/compute/virtualbox_nodes.py
@@ -26,7 +26,7 @@ from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.virtualbox import VirtualBox
from gns3server.compute.virtualbox.virtualbox_error import VirtualBoxError
from gns3server.compute.project_manager import ProjectManager
@@ -260,7 +260,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: VirtualBoxVM =
await node.adapter_remove_nio_binding(adapter_number)
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -276,7 +276,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": str(pcap_file_path)}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: VirtualBoxVM = Depends(dep_node)):
@@ -288,7 +288,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: VirtualBoxVM
await node.stop_capture(adapter_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: VirtualBoxVM = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/vmware_nodes.py b/gns3server/endpoints/compute/vmware_nodes.py
index b456ca0c..2c706b77 100644
--- a/gns3server/endpoints/compute/vmware_nodes.py
+++ b/gns3server/endpoints/compute/vmware_nodes.py
@@ -26,7 +26,7 @@ from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.vmware import VMware
from gns3server.compute.project_manager import ProjectManager
from gns3server.compute.vmware.vmware_vm import VMwareVM
@@ -225,7 +225,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: VMwareVM = Dep
await node.adapter_remove_nio_binding(adapter_number)
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -241,7 +241,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: VMwareVM = Depends(dep_node)):
@@ -253,7 +253,7 @@ async def stop_capture(adapter_number: int, port_number: int, node: VMwareVM = D
await node.stop_capture(adapter_number)
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: VMwareVM = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/compute/vpcs_nodes.py b/gns3server/endpoints/compute/vpcs_nodes.py
index abd64930..ed1483ad 100644
--- a/gns3server/endpoints/compute/vpcs_nodes.py
+++ b/gns3server/endpoints/compute/vpcs_nodes.py
@@ -26,7 +26,7 @@ from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse
from uuid import UUID
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.compute.vpcs import VPCS
from gns3server.compute.vpcs.vpcs_vm import VPCSVM
@@ -208,7 +208,7 @@ async def delete_nio(adapter_number: int, port_number: int, node: VPCSVM = Depen
await node.port_remove_nio_binding(port_number)
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/start_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/start",
responses=responses)
async def start_capture(adapter_number: int,
port_number: int,
@@ -224,7 +224,7 @@ async def start_capture(adapter_number: int,
return {"pcap_file_path": pcap_file_path}
-@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/stop_capture",
+@router.post("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stop",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
async def stop_capture(adapter_number: int, port_number: int, node: VPCSVM = Depends(dep_node)):
@@ -244,7 +244,7 @@ async def reset_console(node: VPCSVM = Depends(dep_node)):
await node.reset_console()
-@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap",
+@router.get("/{node_id}/adapters/{adapter_number}/ports/{port_number}/capture/stream",
responses=responses)
async def stream_pcap_file(adapter_number: int, port_number: int, node: VPCSVM = Depends(dep_node)):
"""
diff --git a/gns3server/endpoints/controller/computes.py b/gns3server/endpoints/controller/computes.py
index 8a76b239..8d33e4b6 100644
--- a/gns3server/endpoints/controller/computes.py
+++ b/gns3server/endpoints/controller/computes.py
@@ -25,22 +25,21 @@ from typing import List, Union
from uuid import UUID
from gns3server.controller import Controller
-from gns3server.endpoints.schemas.common import ErrorMessage
-from gns3server.endpoints import schemas
+from gns3server import schemas
router = APIRouter()
responses = {
- 404: {"model": ErrorMessage, "description": "Compute not found"}
+ 404: {"model": schemas.ErrorMessage, "description": "Compute not found"}
}
@router.post("",
status_code=status.HTTP_201_CREATED,
response_model=schemas.Compute,
- responses={404: {"model": ErrorMessage, "description": "Could not connect to compute"},
- 409: {"model": ErrorMessage, "description": "Could not create compute"},
- 401: {"model": ErrorMessage, "description": "Invalid authentication for compute"}})
+ responses={404: {"model": schemas.ErrorMessage, "description": "Could not connect to compute"},
+ 409: {"model": schemas.ErrorMessage, "description": "Could not create compute"},
+ 401: {"model": schemas.ErrorMessage, "description": "Invalid authentication for compute"}})
async def create_compute(compute_data: schemas.ComputeCreate):
"""
Create a new compute on the controller.
diff --git a/gns3server/endpoints/controller/controller.py b/gns3server/endpoints/controller/controller.py
index a1e3d0c9..458eb9e5 100644
--- a/gns3server/endpoints/controller/controller.py
+++ b/gns3server/endpoints/controller/controller.py
@@ -26,8 +26,7 @@ from gns3server.config import Config
from gns3server.controller import Controller
from gns3server.version import __version__
from gns3server.controller.controller_error import ControllerError, ControllerForbiddenError
-from gns3server.endpoints.schemas.common import ErrorMessage
-from gns3server.endpoints import schemas
+from gns3server import schemas
import logging
@@ -38,7 +37,7 @@ router = APIRouter()
@router.post("/shutdown",
status_code=status.HTTP_204_NO_CONTENT,
- responses={403: {"model": ErrorMessage, "description": "Server shutdown not allowed"}})
+ responses={403: {"model": schemas.ErrorMessage, "description": "Server shutdown not allowed"}})
async def shutdown():
"""
Shutdown the local server
@@ -85,7 +84,7 @@ def version():
@router.post("/version",
response_model=schemas.Version,
response_model_exclude_defaults=True,
- responses={409: {"model": ErrorMessage, "description": "Invalid version"}})
+ responses={409: {"model": schemas.ErrorMessage, "description": "Invalid version"}})
def check_version(version: schemas.Version):
"""
Check if version is the same as the server.
diff --git a/gns3server/endpoints/controller/drawings.py b/gns3server/endpoints/controller/drawings.py
index fbb3967c..2baf14db 100644
--- a/gns3server/endpoints/controller/drawings.py
+++ b/gns3server/endpoints/controller/drawings.py
@@ -25,18 +25,17 @@ from typing import List
from uuid import UUID
from gns3server.controller import Controller
-from gns3server.endpoints.schemas.common import ErrorMessage
-from gns3server.endpoints.schemas.drawings import Drawing
+from gns3server import schemas
router = APIRouter()
responses = {
- 404: {"model": ErrorMessage, "description": "Project or drawing not found"}
+ 404: {"model": schemas.ErrorMessage, "description": "Project or drawing not found"}
}
@router.get("",
- response_model=List[Drawing],
+ response_model=List[schemas.Drawing],
response_model_exclude_unset=True)
async def get_drawings(project_id: UUID):
"""
@@ -49,9 +48,9 @@ async def get_drawings(project_id: UUID):
@router.post("",
status_code=status.HTTP_201_CREATED,
- response_model=Drawing,
+ response_model=schemas.Drawing,
responses=responses)
-async def create_drawing(project_id: UUID, drawing_data: Drawing):
+async def create_drawing(project_id: UUID, drawing_data: schemas.Drawing):
"""
Create a new drawing.
"""
@@ -62,7 +61,7 @@ async def create_drawing(project_id: UUID, drawing_data: Drawing):
@router.get("/{drawing_id}",
- response_model=Drawing,
+ response_model=schemas.Drawing,
response_model_exclude_unset=True,
responses=responses)
async def get_drawing(project_id: UUID, drawing_id: UUID):
@@ -76,10 +75,10 @@ async def get_drawing(project_id: UUID, drawing_id: UUID):
@router.put("/{drawing_id}",
- response_model=Drawing,
+ response_model=schemas.Drawing,
response_model_exclude_unset=True,
responses=responses)
-async def update_drawing(project_id: UUID, drawing_id: UUID, drawing_data: Drawing):
+async def update_drawing(project_id: UUID, drawing_id: UUID, drawing_data: schemas.Drawing):
"""
Update a drawing.
"""
diff --git a/gns3server/endpoints/controller/gns3vm.py b/gns3server/endpoints/controller/gns3vm.py
index 16669350..9910df6b 100644
--- a/gns3server/endpoints/controller/gns3vm.py
+++ b/gns3server/endpoints/controller/gns3vm.py
@@ -23,7 +23,7 @@ from fastapi import APIRouter
from fastapi.encoders import jsonable_encoder
from gns3server.controller import Controller
-from gns3server.endpoints.schemas.gns3vm import GNS3VM
+from gns3server import schemas
router = APIRouter()
@@ -48,7 +48,7 @@ async def get_vms(engine: str):
return vms
-@router.get("", response_model=GNS3VM)
+@router.get("", response_model=schemas.GNS3VM)
async def get_gns3vm_settings():
"""
Return the GNS3 VM settings.
@@ -57,8 +57,8 @@ async def get_gns3vm_settings():
return Controller.instance().gns3vm.__json__()
-@router.put("", response_model=GNS3VM, response_model_exclude_unset=True)
-async def update_gns3vm_settings(gns3vm_data: GNS3VM):
+@router.put("", response_model=schemas.GNS3VM, response_model_exclude_unset=True)
+async def update_gns3vm_settings(gns3vm_data: schemas.GNS3VM):
"""
Update the GNS3 VM settings.
"""
diff --git a/gns3server/endpoints/controller/links.py b/gns3server/endpoints/controller/links.py
index ff1c393d..0a3730aa 100644
--- a/gns3server/endpoints/controller/links.py
+++ b/gns3server/endpoints/controller/links.py
@@ -32,8 +32,7 @@ from gns3server.controller import Controller
from gns3server.controller.controller_error import ControllerError
from gns3server.controller.link import Link
from gns3server.utils.http_client import HTTPClient
-from gns3server.endpoints.schemas.common import ErrorMessage
-from gns3server.endpoints import schemas
+from gns3server import schemas
import logging
log = logging.getLogger(__name__)
@@ -41,7 +40,7 @@ log = logging.getLogger(__name__)
router = APIRouter()
responses = {
- 404: {"model": ErrorMessage, "description": "Could not find project or link"}
+ 404: {"model": schemas.ErrorMessage, "description": "Could not find project or link"}
}
@@ -70,8 +69,8 @@ async def get_links(project_id: UUID):
@router.post("",
status_code=status.HTTP_201_CREATED,
response_model=schemas.Link,
- responses={404: {"model": ErrorMessage, "description": "Could not find project"},
- 409: {"model": ErrorMessage, "description": "Could not create link"}})
+ responses={404: {"model": schemas.ErrorMessage, "description": "Could not find project"},
+ 409: {"model": schemas.ErrorMessage, "description": "Could not create link"}})
async def create_link(project_id: UUID, link_data: schemas.Link):
"""
Create a new link.
@@ -137,31 +136,6 @@ async def update_link(link_data: schemas.Link, link: Link = Depends(dep_link)):
return link.__json__()
-@router.post("/{link_id}/start_capture",
- status_code=status.HTTP_201_CREATED,
- response_model=schemas.Link,
- responses=responses)
-async def start_capture(capture_data: dict, link: Link = Depends(dep_link)):
- """
- Start packet capture on the link.
- """
-
- await link.start_capture(data_link_type=capture_data.get("data_link_type", "DLT_EN10MB"),
- capture_file_name=capture_data.get("capture_file_name"))
- return link.__json__()
-
-
-@router.post("/{link_id}/stop_capture",
- status_code=status.HTTP_204_NO_CONTENT,
- responses=responses)
-async def stop_capture(link: Link = Depends(dep_link)):
- """
- Stop packet capture on the link.
- """
-
- await link.stop_capture()
-
-
@router.delete("/{link_id}",
status_code=status.HTTP_204_NO_CONTENT,
responses=responses)
@@ -186,9 +160,34 @@ async def reset_link(link: Link = Depends(dep_link)):
return link.__json__()
-@router.get("/{link_id}/pcap",
+@router.post("/{link_id}/capture/start",
+ status_code=status.HTTP_201_CREATED,
+ response_model=schemas.Link,
+ responses=responses)
+async def start_capture(capture_data: dict, link: Link = Depends(dep_link)):
+ """
+ Start packet capture on the link.
+ """
+
+ await link.start_capture(data_link_type=capture_data.get("data_link_type", "DLT_EN10MB"),
+ capture_file_name=capture_data.get("capture_file_name"))
+ return link.__json__()
+
+
+@router.post("/{link_id}/capture/stop",
+ status_code=status.HTTP_204_NO_CONTENT,
+ responses=responses)
+async def stop_capture(link: Link = Depends(dep_link)):
+ """
+ Stop packet capture on the link.
+ """
+
+ await link.stop_capture()
+
+
+@router.get("/{link_id}/capture/stream",
responses=responses)
-async def pcap(request: Request, link: Link = Depends(dep_link)):
+async def stream_pcap(request: Request, link: Link = Depends(dep_link)):
"""
Stream the PCAP capture file from compute.
"""
diff --git a/gns3server/endpoints/controller/nodes.py b/gns3server/endpoints/controller/nodes.py
index c2f6cca0..20c7b303 100644
--- a/gns3server/endpoints/controller/nodes.py
+++ b/gns3server/endpoints/controller/nodes.py
@@ -34,8 +34,7 @@ from gns3server.controller.project import Project
from gns3server.utils import force_unix_path
from gns3server.utils.http_client import HTTPClient
from gns3server.controller.controller_error import ControllerForbiddenError
-from gns3server.endpoints.schemas.common import ErrorMessage
-from gns3server.endpoints import schemas
+from gns3server import schemas
import logging
log = logging.getLogger(__name__)
@@ -80,7 +79,7 @@ class NodeConcurrency(APIRoute):
router = APIRouter(route_class=NodeConcurrency)
responses = {
- 404: {"model": ErrorMessage, "description": "Could not find project or node"}
+ 404: {"model": schemas.ErrorMessage, "description": "Could not find project or node"}
}
@@ -105,8 +104,8 @@ async def dep_node(node_id: UUID, project: Project = Depends(dep_project)):
@router.post("",
status_code=status.HTTP_201_CREATED,
response_model=schemas.Node,
- responses={404: {"model": ErrorMessage, "description": "Could not find project"},
- 409: {"model": ErrorMessage, "description": "Could not create node"}})
+ responses={404: {"model": schemas.ErrorMessage, "description": "Could not find project"},
+ 409: {"model": schemas.ErrorMessage, "description": "Could not create node"}})
async def create_node(node_data: schemas.Node, project: Project = Depends(dep_project)):
"""
Create a new node.
@@ -212,7 +211,7 @@ async def update_node(node_data: schemas.NodeUpdate, node: Node = Depends(dep_no
@router.delete("/{node_id}",
status_code=status.HTTP_204_NO_CONTENT,
responses={**responses,
- 409: {"model": ErrorMessage, "description": "Cannot delete node"}})
+ 409: {"model": schemas.ErrorMessage, "description": "Cannot delete node"}})
async def delete_node(node_id: UUID, project: Project = Depends(dep_project)):
"""
Delete a node from a project.
@@ -381,7 +380,7 @@ async def ws_console(websocket: WebSocket, node: Node = Depends(dep_node)):
compute = node.compute
await websocket.accept()
log.info(f"New client {websocket.client.host}:{websocket.client.port} has connected to controller console WebSocket")
- ws_console_compute_url = f"ws://{compute.host}:{compute.port}/v2/compute/projects/" \
+ ws_console_compute_url = f"ws://{compute.host}:{compute.port}/v3/compute/projects/" \
f"{node.project.id}/{node.node_type}/nodes/{node.id}/console/ws"
async def ws_receive(ws_console_compute):
diff --git a/gns3server/endpoints/controller/projects.py b/gns3server/endpoints/controller/projects.py
index a4bd174d..6e965833 100644
--- a/gns3server/endpoints/controller/projects.py
+++ b/gns3server/endpoints/controller/projects.py
@@ -37,8 +37,7 @@ from typing import List, Optional
from uuid import UUID
from pathlib import Path
-from gns3server.endpoints.schemas.common import ErrorMessage
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.controller import Controller
from gns3server.controller.project import Project
from gns3server.controller.controller_error import ControllerError, ControllerForbiddenError
@@ -51,7 +50,7 @@ from gns3server.config import Config
router = APIRouter()
responses = {
- 404: {"model": ErrorMessage, "description": "Could not find project"}
+ 404: {"model": schemas.ErrorMessage, "description": "Could not find project"}
}
@@ -83,7 +82,7 @@ def get_projects():
status_code=status.HTTP_201_CREATED,
response_model=schemas.Project,
response_model_exclude_unset=True,
- responses={409: {"model": ErrorMessage, "description": "Could not create project"}})
+ responses={409: {"model": schemas.ErrorMessage, "description": "Could not create project"}})
async def create_project(project_data: schemas.ProjectCreate):
"""
Create a new project.
@@ -145,7 +144,7 @@ def get_project_stats(project: Project = Depends(dep_project)):
status_code=status.HTTP_204_NO_CONTENT,
responses={
**responses,
- 409: {"model": ErrorMessage, "description": "Could not close project"}
+ 409: {"model": schemas.ErrorMessage, "description": "Could not close project"}
})
async def close_project(project: Project = Depends(dep_project)):
"""
@@ -160,7 +159,7 @@ async def close_project(project: Project = Depends(dep_project)):
response_model=schemas.Project,
responses={
**responses,
- 409: {"model": ErrorMessage, "description": "Could not open project"}
+ 409: {"model": schemas.ErrorMessage, "description": "Could not open project"}
})
async def open_project(project: Project = Depends(dep_project)):
"""
@@ -176,7 +175,7 @@ async def open_project(project: Project = Depends(dep_project)):
response_model=schemas.Project,
responses={
**responses,
- 409: {"model": ErrorMessage, "description": "Could not load project"}
+ 409: {"model": schemas.ErrorMessage, "description": "Could not load project"}
})
async def load_project(path: str = Body(..., embed=True)):
"""
@@ -346,7 +345,7 @@ async def import_project(project_id: UUID, request: Request, path: Optional[Path
response_model=schemas.Project,
responses={
**responses,
- 409: {"model": ErrorMessage, "description": "Could not duplicate project"}
+ 409: {"model": schemas.ErrorMessage, "description": "Could not duplicate project"}
})
async def duplicate(project_data: schemas.ProjectDuplicate, project: Project = Depends(dep_project)):
"""
diff --git a/gns3server/endpoints/controller/snapshots.py b/gns3server/endpoints/controller/snapshots.py
index c7c57725..19c08419 100644
--- a/gns3server/endpoints/controller/snapshots.py
+++ b/gns3server/endpoints/controller/snapshots.py
@@ -27,14 +27,13 @@ from typing import List
from uuid import UUID
from gns3server.controller.project import Project
-from gns3server.endpoints.schemas.common import ErrorMessage
-from gns3server.endpoints import schemas
+from gns3server import schemas
from gns3server.controller import Controller
router = APIRouter()
responses = {
- 404: {"model": ErrorMessage, "description": "Could not find project or snapshot"}
+ 404: {"model": schemas.ErrorMessage, "description": "Could not find project or snapshot"}
}
diff --git a/gns3server/endpoints/controller/symbols.py b/gns3server/endpoints/controller/symbols.py
index d6555143..c4d9c0d8 100644
--- a/gns3server/endpoints/controller/symbols.py
+++ b/gns3server/endpoints/controller/symbols.py
@@ -25,7 +25,7 @@ from fastapi import APIRouter, Request, status
from fastapi.responses import FileResponse
from gns3server.controller import Controller
-from gns3server.endpoints.schemas.common import ErrorMessage
+from gns3server import schemas
from gns3server.controller.controller_error import ControllerError, ControllerNotFoundError
import logging
@@ -43,7 +43,7 @@ def get_symbols():
@router.get("/{symbol_id:path}/raw",
- responses={404: {"model": ErrorMessage, "description": "Could not find symbol"}})
+ responses={404: {"model": schemas.ErrorMessage, "description": "Could not find symbol"}})
async def get_symbol(symbol_id: str):
"""
Download a symbol file.
diff --git a/gns3server/endpoints/controller/templates.py b/gns3server/endpoints/controller/templates.py
index b4edd434..cf14f8cb 100644
--- a/gns3server/endpoints/controller/templates.py
+++ b/gns3server/endpoints/controller/templates.py
@@ -27,25 +27,20 @@ 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 import schemas
from gns3server.controller import Controller
+
router = APIRouter()
responses = {
- 404: {"model": ErrorMessage, "description": "Could not find template"}
+ 404: {"model": schemas.ErrorMessage, "description": "Could not find template"}
}
-#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)
@@ -138,7 +133,7 @@ async def duplicate_template(template_id: UUID):
@router.post("/projects/{project_id}/templates/{template_id}",
response_model=schemas.Node,
status_code=status.HTTP_201_CREATED,
- responses={404: {"model": ErrorMessage, "description": "Could not find project or template"}})
+ responses={404: {"model": schemas.ErrorMessage, "description": "Could not find project or template"}})
async def create_node_from_template(project_id: UUID, template_id: UUID, template_usage: schemas.TemplateUsage):
"""
Create a new node from a template.
diff --git a/gns3server/endpoints/schemas/__init__.py b/gns3server/endpoints/schemas/__init__.py
deleted file mode 100644
index bf8a68b0..00000000
--- a/gns3server/endpoints/schemas/__init__.py
+++ /dev/null
@@ -1,45 +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 .
-
-
-from .version import Version
-from .iou_license import IOULicense
-from .links import Link
-from .common import ErrorMessage
-from .computes import ComputeCreate, ComputeUpdate, Compute, AutoIdlePC
-from .nodes import NodeUpdate, NodeDuplicate, NodeCapture, Node
-from .projects import ProjectCreate, ProjectUpdate, ProjectDuplicate, Project, ProjectFile
-from .snapshots import SnapshotCreate, Snapshot
-from .templates import TemplateCreate, TemplateUpdate, TemplateUsage, Template
-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 .iou_nodes import IOUCreate, IOUUpdate, IOUStart, IOU
-from .nat_nodes import NATCreate, NATUpdate, NAT
-from .qemu_nodes import QemuCreate, QemuUpdate, Qemu, QemuDiskResize, QemuImageCreate, QemuImageUpdate
-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
diff --git a/gns3server/endpoints/schemas/capabilities.py b/gns3server/endpoints/schemas/capabilities.py
deleted file mode 100644
index 6197d93e..00000000
--- a/gns3server/endpoints/schemas/capabilities.py
+++ /dev/null
@@ -1,35 +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 .
-
-
-from pydantic import BaseModel, Field
-from typing import List
-
-from .nodes import NodeType
-
-
-class Capabilities(BaseModel):
- """
- Capabilities properties.
- """
-
- version: str = Field(..., description="Compute version number")
- node_types: List[NodeType] = Field(..., description="Node types supported by the compute")
- platform: str = Field(..., description="Platform where the compute is running")
- cpus: int = Field(..., description="Number of CPUs on this compute")
- memory: int = Field(..., description="Amount of memory on this compute")
- disk_size: int = Field(..., description="Disk size on this compute")
diff --git a/gns3server/endpoints/schemas/version.py b/gns3server/endpoints/schemas/version.py
deleted file mode 100644
index cb92d953..00000000
--- a/gns3server/endpoints/schemas/version.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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 .
-
-from pydantic import BaseModel, Field
-from typing import Optional
-
-
-class Version(BaseModel):
-
- version: str = Field(..., description="Version number")
- local: Optional[bool] = Field(None, description="Whether this is a local server or not")
diff --git a/gns3server/schemas/__init__.py b/gns3server/schemas/__init__.py
index e69de29b..875ed06c 100644
--- a/gns3server/schemas/__init__.py
+++ b/gns3server/schemas/__init__.py
@@ -0,0 +1,64 @@
+# -*- 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 .
+
+
+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 .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 (
+ DynamipsTemplate,
+ C1700DynamipsTemplate,
+ C2600DynamipsTemplate,
+ C2691DynamipsTemplate,
+ C3600DynamipsTemplate,
+ C3725DynamipsTemplate,
+ C3745DynamipsTemplate,
+ C7200DynamipsTemplate
+)
diff --git a/gns3server/endpoints/schemas/atm_switch_nodes.py b/gns3server/schemas/atm_switch_nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/atm_switch_nodes.py
rename to gns3server/schemas/atm_switch_nodes.py
diff --git a/gns3server/schemas/capabilities.py b/gns3server/schemas/capabilities.py
index 61378299..6197d93e 100644
--- a/gns3server/schemas/capabilities.py
+++ b/gns3server/schemas/capabilities.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2015 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
@@ -15,40 +15,21 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from .node import NODE_TYPE_SCHEMA
+
+from pydantic import BaseModel, Field
+from typing import List
+
+from .nodes import NodeType
-CAPABILITIES_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Get what a server support",
- "type": "object",
- "required": ["version", "node_types"],
- "properties": {
- "version": {
- "description": "Version number",
- "type": ["string", "null"],
- },
- "node_types": {
- "type": "array",
- "items": NODE_TYPE_SCHEMA,
- "description": "Node type supported by the compute"
- },
- "platform": {
- "type": "string",
- "description": "Platform where the compute is running"
- },
- "cpus": {
- "description": "Number of CPUs on this compute. Read only",
- "type": ["integer", "null"],
- },
- "memory": {
- "description": "Amount of memory on this compute. Read only",
- "type": ["integer", "null"],
- },
- "disk_size": {
- "description": "Disk size on this compute. Read only",
- "type": ["integer", "null"],
- },
- },
- "additionalProperties": False
-}
+class Capabilities(BaseModel):
+ """
+ Capabilities properties.
+ """
+
+ version: str = Field(..., description="Compute version number")
+ node_types: List[NodeType] = Field(..., description="Node types supported by the compute")
+ platform: str = Field(..., description="Platform where the compute is running")
+ cpus: int = Field(..., description="Number of CPUs on this compute")
+ memory: int = Field(..., description="Amount of memory on this compute")
+ disk_size: int = Field(..., description="Disk size on this compute")
diff --git a/gns3server/endpoints/schemas/cloud_nodes.py b/gns3server/schemas/cloud_nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/cloud_nodes.py
rename to gns3server/schemas/cloud_nodes.py
diff --git a/gns3server/schemas/cloud_template.py b/gns3server/schemas/cloud_template.py
deleted file mode 100644
index b6840074..00000000
--- a/gns3server/schemas/cloud_template.py
+++ /dev/null
@@ -1,66 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-from .port import PORT_OBJECT_SCHEMA
-
-
-CLOUD_TEMPLATE_PROPERTIES = {
- "ports_mapping": {
- "type": "array",
- "items": [PORT_OBJECT_SCHEMA],
- "default": []
- },
- "remote_console_host": {
- "description": "Remote console host or IP",
- "type": ["string"],
- "minLength": 1,
- "default": "127.0.0.1"
- },
- "remote_console_port": {
- "description": "Console TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": "integer",
- "default": 23
- },
- "remote_console_type": {
- "description": "Console type",
- "enum": ["telnet", "vnc", "spice", "http", "https", "none"],
- "default": "none"
- },
- "remote_console_http_path": {
- "description": "Path of the remote web interface",
- "type": "string",
- "minLength": 1,
- "default": "/"
- },
-}
-
-CLOUD_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-CLOUD_TEMPLATE_PROPERTIES["category"]["default"] = "guest"
-CLOUD_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "Cloud{0}"
-CLOUD_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/cloud.svg"
-
-CLOUD_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A cloud template object",
- "type": "object",
- "properties": CLOUD_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
diff --git a/gns3server/endpoints/schemas/cloud_templates.py b/gns3server/schemas/cloud_templates.py
similarity index 57%
rename from gns3server/endpoints/schemas/cloud_templates.py
rename to gns3server/schemas/cloud_templates.py
index 3ce0e05b..99d12322 100644
--- a/gns3server/endpoints/schemas/cloud_templates.py
+++ b/gns3server/schemas/cloud_templates.py
@@ -17,29 +17,13 @@
from .templates import Category, TemplateBase
-from .cloud_nodes import EthernetPort, TAPPort, UDPPort
+from .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")
diff --git a/gns3server/endpoints/schemas/common.py b/gns3server/schemas/common.py
similarity index 100%
rename from gns3server/endpoints/schemas/common.py
rename to gns3server/schemas/common.py
diff --git a/gns3server/schemas/compute.py b/gns3server/schemas/compute.py
deleted file mode 100644
index 3de0fb70..00000000
--- a/gns3server/schemas/compute.py
+++ /dev/null
@@ -1,188 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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 .
-
-import copy
-from .capabilities import CAPABILITIES_SCHEMA
-
-COMPUTE_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to register a GNS3 compute instance",
- "type": "object",
- "properties": {
- "compute_id": {
- "description": "Server identifier",
- "type": "string"
- },
- "name": {
- "description": "Server name",
- "type": "string"
- },
- "protocol": {
- "description": "Server protocol",
- "enum": ["http", "https"]
- },
- "host": {
- "description": "Server host",
- "type": "string"
- },
- "port": {
- "description": "Server port",
- "type": "integer"
- },
- "user": {
- "description": "User for authentication",
- "type": ["string", "null"]
- },
- "password": {
- "description": "Password for authentication",
- "type": ["string", "null"]
- }
- },
- "additionalProperties": False,
- "required": ["protocol", "host", "port"]
-}
-
-COMPUTE_UPDATE_SCHEMA = copy.deepcopy(COMPUTE_CREATE_SCHEMA)
-del COMPUTE_UPDATE_SCHEMA["required"]
-
-COMPUTE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to a GNS3 compute object instance",
- "type": "object",
- "properties": {
- "compute_id": {
- "description": "Server identifier",
- "type": "string"
- },
- "name": {
- "description": "Server name",
- "type": "string"
- },
- "protocol": {
- "description": "Server protocol",
- "enum": ["http", "https"]
- },
- "host": {
- "description": "Server host",
- "type": "string"
- },
- "port": {
- "description": "Server port",
- "type": "integer"
- },
- "user": {
- "description": "User for authentication",
- "type": ["string", "null"]
- },
- "connected": {
- "description": "Whether the controller is connected to the compute or not",
- "type": "boolean"
- },
- "cpu_usage_percent": {
- "description": "CPU usage of the compute. Read only",
- "type": ["number", "null"],
- "maximum": 100,
- "minimum": 0
- },
- "memory_usage_percent": {
- "description": "RAM usage of the compute. Read only",
- "type": ["number", "null"],
- "maximum": 100,
- "minimum": 0
- },
- "disk_usage_percent": {
- "description": "Disk usage of the compute. Read only",
- "type": ["number", "null"],
- "maximum": 100,
- "minimum": 0
- },
- "last_error": {
- "description": "Last error on the compute",
- "type": ["string", "null"]
- },
- "capabilities": CAPABILITIES_SCHEMA
- },
- "additionalProperties": False,
- "required": ["compute_id", "protocol", "host", "port", "name"]
-}
-
-COMPUTE_ENDPOINT_OUTPUT_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Output schema for obtaining endpoint on compute",
- "type": "object",
- "properties": {
- "endpoint": {
- "description": "URL to endpoint on specific compute and to particular action",
- "type": "string"
- },
- },
- "additionalProperties": False,
-}
-
-COMPUTE_PORTS_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Output schema for open ports on a compute",
- "type": "object",
- "properties": {
- "console_port_range": {
- "description": "Console port range",
- "type": "array",
- "uniqueItems": True,
- "minItems": 2,
- "maxItems": 2,
- "items": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "console_ports": {
- "description": "Console ports used by the compute",
- "type": "array",
- "uniqueItems": True,
- "items": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "udp_port_range": {
- "description": "UDP port range",
- "type": "array",
- "uniqueItems": True,
- "minItems": 2,
- "maxItems": 2,
- "items": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "udp_ports": {
- "description": "UDP ports used by the compute",
- "type": "array",
- "uniqueItems": True,
- "items": {
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- },
- "additionalProperties": False,
-}
-
diff --git a/gns3server/endpoints/schemas/computes.py b/gns3server/schemas/computes.py
similarity index 87%
rename from gns3server/endpoints/schemas/computes.py
rename to gns3server/schemas/computes.py
index f903e970..92fa5305 100644
--- a/gns3server/endpoints/schemas/computes.py
+++ b/gns3server/schemas/computes.py
@@ -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):
diff --git a/gns3server/schemas/custom_adapters.py b/gns3server/schemas/custom_adapters.py
deleted file mode 100644
index f3472540..00000000
--- a/gns3server/schemas/custom_adapters.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-#
-# 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 .
-
-CUSTOM_ADAPTERS_ARRAY_SCHEMA = {
- "type": "array",
- "default": [],
- "items": {
- "type": "object",
- "description": "Custom properties",
- "properties": {
- "adapter_number": {
- "type": "integer",
- "description": "Adapter number"
- },
- "port_name": {
- "type": "string",
- "description": "Custom port name",
- "minLength": 1,
- },
- "adapter_type": {
- "type": "string",
- "description": "Custom adapter type",
- "minLength": 1,
- },
- "mac_address": {
- "description": "Custom MAC address",
- "type": "string",
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"
- },
- },
- "additionalProperties": False,
- "required": ["adapter_number"]
- },
-}
diff --git a/gns3server/endpoints/schemas/docker_nodes.py b/gns3server/schemas/docker_nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/docker_nodes.py
rename to gns3server/schemas/docker_nodes.py
diff --git a/gns3server/schemas/docker_template.py b/gns3server/schemas/docker_template.py
deleted file mode 100644
index 5f25d17f..00000000
--- a/gns3server/schemas/docker_template.py
+++ /dev/null
@@ -1,115 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA
-
-
-DOCKER_TEMPLATE_PROPERTIES = {
- "image": {
- "description": "Docker image name",
- "type": "string",
- "minLength": 1
- },
- "adapters": {
- "description": "Number of adapters",
- "type": "integer",
- "minimum": 0,
- "maximum": 99,
- "default": 1
- },
- "start_command": {
- "description": "Docker CMD entry",
- "type": "string",
- "default": ""
- },
- "environment": {
- "description": "Docker environment variables",
- "type": "string",
- "default": ""
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "vnc", "http", "https", "none"],
- "default": "telnet"
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "none"],
- "default": "none"
- },
- "console_auto_start": {
- "description": "Automatically start the console when the node has started",
- "type": "boolean",
- "default": False,
- },
- "console_http_port": {
- "description": "Internal port in the container for the HTTP server",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535,
- "default": 80
- },
- "console_http_path": {
- "description": "Path of the web interface",
- "type": "string",
- "minLength": 1,
- "default": "/"
- },
- "console_resolution": {
- "description": "Console resolution for VNC",
- "type": "string",
- "pattern": "^[0-9]+x[0-9]+$",
- "default": "1024x768"
- },
- "extra_hosts": {
- "description": "Docker extra hosts (added to /etc/hosts)",
- "type": "string",
- "default": ""
- },
- "extra_volumes": {
- "description": "Additional directories to make persistent",
- "type": "array",
- "default": []
- },
- "memory": {
- "description": "Maximum amount of memory the container can use in MB",
- "type": "integer",
- "default": 0
- },
- "cpus": {
- "description": "Maximum amount of CPU resources the container can use",
- "type": "number",
- "default": 0
- },
- "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA
-}
-
-DOCKER_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-DOCKER_TEMPLATE_PROPERTIES["category"]["default"] = "guest"
-DOCKER_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}"
-DOCKER_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/docker_guest.svg"
-
-DOCKER_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A Docker template object",
- "type": "object",
- "properties": DOCKER_TEMPLATE_PROPERTIES,
- "required": ["image"],
- "additionalProperties": False
-}
diff --git a/gns3server/schemas/docker_templates.py b/gns3server/schemas/docker_templates.py
new file mode 100644
index 00000000..1a4784e4
--- /dev/null
+++ b/gns3server/schemas/docker_templates.py
@@ -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 .
+
+
+from .templates import Category, TemplateBase
+from .nodes import CustomAdapter
+from .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")
diff --git a/gns3server/schemas/drawing.py b/gns3server/schemas/drawing.py
deleted file mode 100644
index 37f8fd6c..00000000
--- a/gns3server/schemas/drawing.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/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 .
-
-
-DRAWING_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "An drawing object",
- "type": "object",
- "properties": {
- "drawing_id": {
- "description": "Drawing UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "project_id": {
- "description": "Project UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "x": {
- "description": "X property",
- "type": "integer"
- },
- "y": {
- "description": "Y property",
- "type": "integer"
- },
- "z": {
- "description": "Z property",
- "type": "integer"
- },
- "locked": {
- "description": "Whether the element locked or not",
- "type": "boolean"
- },
- "rotation": {
- "description": "Rotation of the element",
- "type": "integer",
- "minimum": -359,
- "maximum": 360
- },
- "svg": {
- "description": "SVG content of the drawing",
- "type": "string"
- }
- },
- "additionalProperties": False
-}
diff --git a/gns3server/endpoints/schemas/drawings.py b/gns3server/schemas/drawings.py
similarity index 100%
rename from gns3server/endpoints/schemas/drawings.py
rename to gns3server/schemas/drawings.py
diff --git a/gns3server/endpoints/schemas/dynamips_nodes.py b/gns3server/schemas/dynamips_nodes.py
similarity index 82%
rename from gns3server/endpoints/schemas/dynamips_nodes.py
rename to gns3server/schemas/dynamips_nodes.py
index 3f9e244e..24f05a27 100644
--- a/gns3server/endpoints/schemas/dynamips_nodes.py
+++ b/gns3server/schemas/dynamips_nodes.py
@@ -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")
diff --git a/gns3server/schemas/dynamips_template.py b/gns3server/schemas/dynamips_template.py
deleted file mode 100644
index 19f8dc19..00000000
--- a/gns3server/schemas/dynamips_template.py
+++ /dev/null
@@ -1,404 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-from .dynamips_vm import DYNAMIPS_ADAPTERS, DYNAMIPS_WICS
-
-
-DYNAMIPS_TEMPLATE_PROPERTIES = {
- "platform": {
- "description": "Platform type",
- "enum": ["c7200", "c3745", "c3725", "c3600", "c2691", "c2600", "c1700"]
- },
- "image": {
- "description": "Path to the IOS image",
- "type": "string",
- "minLength": 1
- },
- "mmap": {
- "description": "MMAP feature",
- "type": "boolean",
- "default": True
- },
- "exec_area": {
- "description": "Exec area value",
- "type": "integer",
- "default": 64
- },
- "mac_addr": {
- "description": "Base MAC address",
- "type": "string",
- "anyOf": [
- {"pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$"},
- {"pattern": "^$"}
- ],
- "default": ""
- },
- "system_id": {
- "description": "System ID",
- "type": "string",
- "minLength": 1,
- "default": "FTX0945W0MY"
- },
- "startup_config": {
- "description": "IOS startup configuration file",
- "type": "string",
- "default": "ios_base_startup-config.txt"
- },
- "private_config": {
- "description": "IOS private configuration file",
- "type": "string",
- "default": ""
- },
- "idlepc": {
- "description": "Idle-PC value",
- "type": "string",
- "pattern": "^(0x[0-9a-fA-F]+)?$",
- "default": ""
- },
- "idlemax": {
- "description": "Idlemax value",
- "type": "integer",
- "default": 500
- },
- "idlesleep": {
- "description": "Idlesleep value",
- "type": "integer",
- "default": 30
- },
- "disk0": {
- "description": "Disk0 size in MB",
- "type": "integer",
- "default": 0
- },
- "disk1": {
- "description": "Disk1 size in MB",
- "type": "integer",
- "default": 0
- },
- "auto_delete_disks": {
- "description": "Automatically delete nvram and disk files",
- "type": "boolean",
- "default": False
- },
- "wic0": DYNAMIPS_WICS,
- "wic1": DYNAMIPS_WICS,
- "wic2": DYNAMIPS_WICS,
- "slot0": DYNAMIPS_ADAPTERS,
- "slot1": DYNAMIPS_ADAPTERS,
- "slot2": DYNAMIPS_ADAPTERS,
- "slot3": DYNAMIPS_ADAPTERS,
- "slot4": DYNAMIPS_ADAPTERS,
- "slot5": DYNAMIPS_ADAPTERS,
- "slot6": DYNAMIPS_ADAPTERS,
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"],
- "default": "telnet"
- },
- "console_auto_start": {
- "description": "Automatically start the console when the node has started",
- "type": "boolean",
- "default": False
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "none"],
- "default": "none"
- }
-}
-
-DYNAMIPS_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-DYNAMIPS_TEMPLATE_PROPERTIES["category"]["default"] = "router"
-DYNAMIPS_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "R{0}"
-DYNAMIPS_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/router.svg"
-
-DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A Dynamips template object",
- "type": "object",
- "properties": DYNAMIPS_TEMPLATE_PROPERTIES,
- "required": ["platform", "image"],
-}
-
-C7200_DYNAMIPS_TEMPLATE_PROPERTIES = {
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer",
- "default": 512
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer",
- "default": 512
- },
- "npe": {
- "description": "NPE model",
- "enum": ["npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300", "npe-400", "npe-g2"],
- "default": "npe-400"
- },
- "midplane": {
- "description": "Midplane model",
- "enum": ["std", "vxr"],
- "default": "vxr"
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean",
- "default": True
- }
-}
-
-C7200_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES)
-
-C7200_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A c7200 Dynamips template object",
- "type": "object",
- "properties": C7200_DYNAMIPS_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
-
-C3745_DYNAMIPS_TEMPLATE_PROPERTIES = {
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer",
- "default": 256
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer",
- "default": 256
- },
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100,
- "default": 5
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean",
- "default": True
- }
-}
-
-C3745_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES)
-
-C3745_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A c3745 Dynamips template object",
- "type": "object",
- "properties": C3745_DYNAMIPS_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
-
-C3725_DYNAMIPS_TEMPLATE_PROPERTIES = {
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer",
- "default": 128
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer",
- "default": 256
- },
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100,
- "default": 5
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean",
- "default": True
- }
-}
-
-C3725_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES)
-
-C3725_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A c3725 Dynamips template object",
- "type": "object",
- "properties": C3725_DYNAMIPS_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
-
-C3600_DYNAMIPS_TEMPLATE_PROPERTIES = {
- "chassis": {
- "description": "Chassis type",
- "enum": ["3620", "3640", "3660"],
- "default": "3660"
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer",
- "default": 192
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer",
- "default": 128
- },
-
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100,
- "default": 5
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean",
- "default": True
- }
-}
-
-C3600_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES)
-
-C3600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A c3600 Dynamips template object",
- "type": "object",
- "properties": C3600_DYNAMIPS_TEMPLATE_PROPERTIES,
- "required": ["chassis"],
- "additionalProperties": False
-}
-
-C2691_DYNAMIPS_TEMPLATE_PROPERTIES = {
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer",
- "default": 192
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer",
- "default": 256
- },
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100,
- "default": 5
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean",
- "default": True
- }
-}
-
-C2691_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES)
-
-C2691_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A c2691 Dynamips template object",
- "type": "object",
- "properties": C2691_DYNAMIPS_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
-
-C2600_DYNAMIPS_TEMPLATE_PROPERTIES = {
- "chassis": {
- "description": "Chassis type",
- "enum": ["2610", "2620", "2610XM", "2620XM", "2650XM", "2621", "2611XM", "2621XM", "2651XM"],
- "default": "2651XM"
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer",
- "default": 160
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer",
- "default": 128
- },
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100,
- "default": 15
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean",
- "default": True
- }
-}
-
-C2600_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES)
-
-C2600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A c2600 Dynamips template object",
- "type": "object",
- "properties": C2600_DYNAMIPS_TEMPLATE_PROPERTIES,
- "required": ["chassis"],
- "additionalProperties": False
-}
-
-C1700_DYNAMIPS_TEMPLATE_PROPERTIES = {
- "chassis": {
- "description": "Chassis type",
- "enum": ["1720", "1721", "1750", "1751", "1760"],
- "default": "1760"
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer",
- "default": 160
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer",
- "default": 128
- },
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100,
- "default": 15
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean",
- "default": False
- }
-}
-
-C1700_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES)
-
-C1700_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A c1700 Dynamips template object",
- "type": "object",
- "properties": C1700_DYNAMIPS_TEMPLATE_PROPERTIES,
- "required": ["chassis"],
- "additionalProperties": False
-}
diff --git a/gns3server/schemas/dynamips_templates.py b/gns3server/schemas/dynamips_templates.py
new file mode 100644
index 00000000..3e09702b
--- /dev/null
+++ b/gns3server/schemas/dynamips_templates.py
@@ -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 .
+
+from .templates import Category, TemplateBase
+from .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")
diff --git a/gns3server/schemas/dynamips_vm.py b/gns3server/schemas/dynamips_vm.py
deleted file mode 100644
index 2e0b32f9..00000000
--- a/gns3server/schemas/dynamips_vm.py
+++ /dev/null
@@ -1,774 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 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 .
-
-
-DYNAMIPS_ADAPTERS = {
- "description": "Dynamips Network Module",
- "enum": ["C7200-IO-2FE",
- "C7200-IO-FE",
- "C7200-IO-GE-E",
- "NM-16ESW",
- "NM-1E",
- "NM-1FE-TX",
- "NM-4E",
- "NM-4T",
- "PA-2FE-TX",
- "PA-4E",
- "PA-4T+",
- "PA-8E",
- "PA-8T",
- "PA-A1",
- "PA-FE-TX",
- "PA-GE",
- "PA-POS-OC3",
- "C2600-MB-2FE",
- "C2600-MB-1E",
- "C1700-MB-1FE",
- "C2600-MB-2E",
- "C2600-MB-1FE",
- "C1700-MB-WIC1",
- "GT96100-FE",
- "Leopard-2FE",
- ""]
-}
-
-DYNAMIPS_WICS = {
- "description": "Dynamips WIC",
- "enum": ["WIC-1ENET",
- "WIC-1T",
- "WIC-2T",
- ""]
-}
-
-#TODO: improve schema for Dynamips (match platform specific options, e.g. NPE allowd only for c7200)
-VM_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new Dynamips VM instance",
- "type": "object",
- "properties": {
- "node_id": {
- "description": "Node UUID",
- "oneOf": [
- {"type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"},
- {"type": "integer"} # for legacy projects
- ]
- },
- "dynamips_id": {
- "description": "Dynamips ID",
- "type": ["integer", "null"]
- },
- "name": {
- "description": "Dynamips VM instance name",
- "type": "string",
- "minLength": 1,
- },
- "usage": {
- "description": "How to use the Dynamips VM",
- "type": "string",
- },
- "platform": {
- "description": "Cisco router platform",
- "type": "string",
- "minLength": 1,
- "pattern": "^c[0-9]{4}$"
- },
- "chassis": {
- "description": "Cisco router chassis model",
- "type": "string",
- "minLength": 1,
- "pattern": "^[0-9]{4}(XM)?$"
- },
- "image": {
- "description": "Path to the IOS image",
- "type": "string",
- "minLength": 1,
- },
- "image_md5sum": {
- "description": "Checksum of the IOS image",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "startup_config_content": {
- "description": "Content of IOS startup configuration file",
- "type": "string",
- },
- "private_config_content": {
- "description": "Content of IOS private configuration file",
- "type": "string",
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer"
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer"
- },
- "mmap": {
- "description": "MMAP feature",
- "type": "boolean"
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean"
- },
- "clock_divisor": {
- "description": "Clock divisor",
- "type": "integer"
- },
- "idlepc": {
- "description": "Idle-PC value",
- "type": "string",
- "pattern": "^(0x[0-9a-fA-F]+)?$"
- },
- "idlemax": {
- "description": "Idlemax value",
- "type": "integer",
- },
- "idlesleep": {
- "description": "Idlesleep value",
- "type": "integer",
- },
- "exec_area": {
- "description": "Exec area value",
- "type": "integer",
- },
- "disk0": {
- "description": "Disk0 size in MB",
- "type": "integer"
- },
- "disk1": {
- "description": "Disk1 size in MB",
- "type": "integer"
- },
- "auto_delete_disks": {
- "description": "Automatically delete nvram and disk files",
- "type": "boolean"
- },
- "console": {
- "description": "Console TCP port",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 65535
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"]
- },
- "aux": {
- "description": "Auxiliary console TCP port",
- "type": ["null", "integer"],
- "minimum": 1,
- "maximum": 65535
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "none"]
- },
- "mac_addr": {
- "description": "Base MAC address",
- "type": ["null", "string"],
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$"
- },
- "system_id": {
- "description": "System ID",
- "type": "string",
- "minLength": 1,
- },
- "slot0": {
- "description": "Network module slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot1": {
- "description": "Network module slot 1",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot2": {
- "description": "Network module slot 2",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot3": {
- "description": "Network module slot 3",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot4": {
- "description": "Network module slot 4",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot5": {
- "description": "Network module slot 5",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot6": {
- "description": "Network module slot 6",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic0": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic1": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic2": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- # C7200 properties
- "npe": {
- "description": "NPE model",
- "enum": ["npe-100",
- "npe-150",
- "npe-175",
- "npe-200",
- "npe-225",
- "npe-300",
- "npe-400",
- "npe-g2"]
- },
- "midplane": {
- "description": "Midplane model",
- "enum": ["std", "vxr"]
- },
- "sensors": {
- "description": "Temperature sensors",
- "type": "array"
- },
- "power_supplies": {
- "description": "Power supplies status",
- "type": "array"
- },
- # I/O memory property for all platforms but C7200
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100
- },
- },
- "additionalProperties": False,
- "required": ["name", "platform", "image", "ram"]
-}
-
-VM_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update a Dynamips VM instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "Dynamips VM instance name",
- "type": "string",
- "minLength": 1,
- },
- "usage": {
- "description": "How to use the Dynamips VM",
- "type": "string",
- },
- "platform": {
- "description": "Cisco router platform",
- "type": "string",
- "minLength": 1,
- "pattern": "^c[0-9]{4}$"
- },
- "chassis": {
- "description": "Cisco router chassis model",
- "type": "string",
- "minLength": 1,
- "pattern": "^[0-9]{4}(XM)?$"
- },
- "image": {
- "description": "Path to the IOS image",
- "type": "string",
- "minLength": 1,
- },
- "image_md5sum": {
- "description": "Checksum of the IOS image",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "dynamips_id": {
- "description": "Dynamips ID",
- "type": "integer"
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer"
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer"
- },
- "mmap": {
- "description": "MMAP feature",
- "type": "boolean"
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean"
- },
- "clock_divisor": {
- "description": "Clock divisor",
- "type": "integer"
- },
- "idlepc": {
- "description": "Idle-PC value",
- "type": "string",
- "pattern": "^(0x[0-9a-fA-F]+)?$"
- },
- "idlemax": {
- "description": "Idlemax value",
- "type": "integer",
- },
- "idlesleep": {
- "description": "Idlesleep value",
- "type": "integer",
- },
- "exec_area": {
- "description": "Exec area value",
- "type": "integer",
- },
- "disk0": {
- "description": "Disk0 size in MB",
- "type": "integer"
- },
- "disk1": {
- "description": "Disk1 size in MB",
- "type": "integer"
- },
- "auto_delete_disks": {
- "description": "Automatically delete nvram and disk files",
- "type": "boolean"
- },
- "console": {
- "description": "Console TCP port",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 65535
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"]
- },
- "aux": {
- "description": "Auxiliary console TCP port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "none"]
- },
- "mac_addr": {
- "description": "Base MAC address",
- "type": ["null", "string"],
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$"
- },
- "system_id": {
- "description": "System ID",
- "type": "string",
- "minLength": 1,
- },
- "slot0": {
- "description": "Network module slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot1": {
- "description": "Network module slot 1",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot2": {
- "description": "Network module slot 2",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot3": {
- "description": "Network module slot 3",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot4": {
- "description": "Network module slot 4",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot5": {
- "description": "Network module slot 5",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot6": {
- "description": "Network module slot 6",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic0": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic1": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic2": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- # C7200 properties
- "npe": {
- "description": "NPE model",
- "enum": ["npe-100",
- "npe-150",
- "npe-175",
- "npe-200",
- "npe-225",
- "npe-300",
- "npe-400",
- "npe-g2"]
- },
- "midplane": {
- "description": "Midplane model",
- "enum": ["std", "vxr"]
- },
- "sensors": {
- "description": "Temperature sensors",
- "type": "array"
- },
- "power_supplies": {
- "description": "Power supplies status",
- "type": "array"
- },
- # I/O memory property for all platforms but C7200
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100
- },
- },
- "additionalProperties": False,
-}
-
-
-VM_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Dynamips VM instance",
- "type": "object",
- "properties": {
- "dynamips_id": {
- "description": "ID to use with Dynamips",
- "type": "integer"
- },
- "node_id": {
- "description": "Node UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "node_directory": {
- "description": "Path to the vm working directory",
- "type": "string"
- },
- "project_id": {
- "description": "Project UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "name": {
- "description": "Dynamips VM instance name",
- "type": "string",
- "minLength": 1,
- },
- "usage": {
- "description": "How to use the Dynamips VM",
- "type": "string",
- },
- "status": {
- "description": "VM status",
- "enum": ["started", "stopped", "suspended"]
- },
- "platform": {
- "description": "Cisco router platform",
- "type": "string",
- "minLength": 1,
- "pattern": "^c[0-9]{4}$"
- },
- "chassis": {
- "description": "Cisco router chassis model",
- "type": "string",
- "minLength": 1,
- "pattern": "^[0-9]{4}(XM)?$"
- },
- "image": {
- "description": "Path to the IOS image",
- "type": "string",
- "minLength": 1,
- },
- "image_md5sum": {
- "description": "Checksum of the IOS image",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer"
- },
- "nvram": {
- "description": "Amount of NVRAM in KB",
- "type": "integer"
- },
- "mmap": {
- "description": "MMAP feature",
- "type": "boolean"
- },
- "sparsemem": {
- "description": "Sparse memory feature",
- "type": "boolean"
- },
- "clock_divisor": {
- "description": "Clock divisor",
- "type": "integer"
- },
- "idlepc": {
- "description": "Idle-PC value",
- "type": "string",
- "pattern": "^(0x[0-9a-fA-F]+)?$"
- },
- "idlemax": {
- "description": "Idlemax value",
- "type": "integer",
- },
- "idlesleep": {
- "description": "Idlesleep value",
- "type": "integer",
- },
- "exec_area": {
- "description": "Exec area value",
- "type": "integer",
- },
- "disk0": {
- "description": "Disk0 size in MB",
- "type": "integer"
- },
- "disk1": {
- "description": "Disk1 size in MB",
- "type": "integer"
- },
- "auto_delete_disks": {
- "description": "Automatically delete nvram and disk files",
- "type": "boolean"
- },
- "console": {
- "description": "Console TCP port",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 65535
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"]
- },
- "aux": {
- "description": "Auxiliary console TCP port",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 65535
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "none"]
- },
- "mac_addr": {
- "description": "Base MAC address",
- "type": ["null", "string"]
- #"minLength": 1,
- #"pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$"
- },
- "system_id": {
- "description": "System ID",
- "type": "string",
- "minLength": 1,
- },
- "slot0": {
- "description": "Network module slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot1": {
- "description": "Network module slot 1",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot2": {
- "description": "Network module slot 2",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot3": {
- "description": "Network module slot 3",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot4": {
- "description": "Network module slot 4",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot5": {
- "description": "Network module slot 5",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot6": {
- "description": "Network module slot 6",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic0": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic1": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic2": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- # C7200 properties
- "npe": {
- "description": "NPE model",
- "enum": ["npe-100",
- "npe-150",
- "npe-175",
- "npe-200",
- "npe-225",
- "npe-300",
- "npe-400",
- "npe-g2"]
- },
- "midplane": {
- "description": "Midplane model",
- "enum": ["std", "vxr"]
- },
- "sensors": {
- "description": "Temperature sensors",
- "type": "array"
- },
- "power_supplies": {
- "description": "Power supplies status",
- "type": "array"
- },
- # I/O memory property for all platforms but C7200
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100
- },
- },
- "additionalProperties": False,
- "required": ["name", "node_id", "project_id", "dynamips_id", "console", "console_type"]
-}
diff --git a/gns3server/endpoints/schemas/ethernet_hub_nodes.py b/gns3server/schemas/ethernet_hub_nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/ethernet_hub_nodes.py
rename to gns3server/schemas/ethernet_hub_nodes.py
diff --git a/gns3server/schemas/ethernet_hub_template.py b/gns3server/schemas/ethernet_hub_template.py
deleted file mode 100644
index f7a5edcd..00000000
--- a/gns3server/schemas/ethernet_hub_template.py
+++ /dev/null
@@ -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 .
-
-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
-}
diff --git a/gns3server/schemas/ethernet_hub_templates.py b/gns3server/schemas/ethernet_hub_templates.py
new file mode 100644
index 00000000..0ca7542c
--- /dev/null
+++ b/gns3server/schemas/ethernet_hub_templates.py
@@ -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 .
+
+
+from .templates import Category, TemplateBase
+from .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")
diff --git a/gns3server/endpoints/schemas/ethernet_switch_nodes.py b/gns3server/schemas/ethernet_switch_nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/ethernet_switch_nodes.py
rename to gns3server/schemas/ethernet_switch_nodes.py
diff --git a/gns3server/schemas/ethernet_switch_template.py b/gns3server/schemas/ethernet_switch_template.py
deleted file mode 100644
index e2473220..00000000
--- a/gns3server/schemas/ethernet_switch_template.py
+++ /dev/null
@@ -1,127 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-
-
-ETHERNET_SWITCH_TEMPLATE_PROPERTIES = {
- "ports_mapping": {
- "type": "array",
- "default": [{"ethertype": "",
- "name": "Ethernet0",
- "vlan": 1,
- "type": "access",
- "port_number": 0
- },
- {"ethertype": "",
- "name": "Ethernet1",
- "vlan": 1,
- "type": "access",
- "port_number": 1
- },
- {"ethertype": "",
- "name": "Ethernet2",
- "vlan": 1,
- "type": "access",
- "port_number": 2
- },
- {"ethertype": "",
- "name": "Ethernet3",
- "vlan": 1,
- "type": "access",
- "port_number": 3
- },
- {"ethertype": "",
- "name": "Ethernet4",
- "vlan": 1,
- "type": "access",
- "port_number": 4
- },
- {"ethertype": "",
- "name": "Ethernet5",
- "vlan": 1,
- "type": "access",
- "port_number": 5
- },
- {"ethertype": "",
- "name": "Ethernet6",
- "vlan": 1,
- "type": "access",
- "port_number": 6
- },
- {"ethertype": "",
- "name": "Ethernet7",
- "vlan": 1,
- "type": "access",
- "port_number": 7
- }
- ],
- "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
- },
- "type": {
- "description": "Port type",
- "enum": ["access", "dot1q", "qinq"],
- },
- "vlan": {"description": "VLAN number",
- "type": "integer",
- "minimum": 1
- },
- "ethertype": {
- "description": "QinQ Ethertype",
- "enum": ["", "0x8100", "0x88A8", "0x9100", "0x9200"],
- },
- },
- "required": ["name", "port_number", "type"],
- "additionalProperties": False
- },
- ]},
- ]
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"],
- "default": "none"
- },
-}
-
-ETHERNET_SWITCH_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-ETHERNET_SWITCH_TEMPLATE_PROPERTIES["category"]["default"] = "switch"
-ETHERNET_SWITCH_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "Switch{0}"
-ETHERNET_SWITCH_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/ethernet_switch.svg"
-
-ETHERNET_SWITCH_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "An Ethernet switch template object",
- "type": "object",
- "properties": ETHERNET_SWITCH_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
diff --git a/gns3server/schemas/ethernet_switch_templates.py b/gns3server/schemas/ethernet_switch_templates.py
new file mode 100644
index 00000000..f605d4fe
--- /dev/null
+++ b/gns3server/schemas/ethernet_switch_templates.py
@@ -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 .
+
+
+from .templates import Category, TemplateBase
+from .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")
diff --git a/gns3server/schemas/filter.py b/gns3server/schemas/filter.py
deleted file mode 100644
index d7f09972..00000000
--- a/gns3server/schemas/filter.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 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 .
-
-
-FILTER_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Packet filter. This allow to simulate latency and errors",
- "type": "object"
-}
diff --git a/gns3server/endpoints/schemas/filters.py b/gns3server/schemas/filters.py
similarity index 100%
rename from gns3server/endpoints/schemas/filters.py
rename to gns3server/schemas/filters.py
diff --git a/gns3server/endpoints/schemas/frame_relay_switch_nodes.py b/gns3server/schemas/frame_relay_switch_nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/frame_relay_switch_nodes.py
rename to gns3server/schemas/frame_relay_switch_nodes.py
diff --git a/gns3server/endpoints/schemas/gns3vm.py b/gns3server/schemas/gns3vm.py
similarity index 100%
rename from gns3server/endpoints/schemas/gns3vm.py
rename to gns3server/schemas/gns3vm.py
diff --git a/gns3server/endpoints/schemas/iou_license.py b/gns3server/schemas/iou_license.py
similarity index 100%
rename from gns3server/endpoints/schemas/iou_license.py
rename to gns3server/schemas/iou_license.py
diff --git a/gns3server/endpoints/schemas/iou_nodes.py b/gns3server/schemas/iou_nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/iou_nodes.py
rename to gns3server/schemas/iou_nodes.py
diff --git a/gns3server/schemas/iou_template.py b/gns3server/schemas/iou_template.py
deleted file mode 100644
index aadfaf97..00000000
--- a/gns3server/schemas/iou_template.py
+++ /dev/null
@@ -1,92 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-
-
-IOU_TEMPLATE_PROPERTIES = {
- "path": {
- "description": "Path of IOU executable",
- "type": "string",
- "minLength": 1
- },
- "ethernet_adapters": {
- "description": "Number of ethernet adapters",
- "type": "integer",
- "default": 2
- },
- "serial_adapters": {
- "description": "Number of serial adapters",
- "type": "integer",
- "default": 2
- },
- "ram": {
- "description": "RAM in MB",
- "type": "integer",
- "default": 256
- },
- "nvram": {
- "description": "NVRAM in KB",
- "type": "integer",
- "default": 128
- },
- "use_default_iou_values": {
- "description": "Use default IOU values",
- "type": "boolean",
- "default": True
- },
- "startup_config": {
- "description": "Startup-config of IOU",
- "type": "string",
- "default": "iou_l3_base_startup-config.txt"
- },
- "private_config": {
- "description": "Private-config of IOU",
- "type": "string",
- "default": ""
- },
- "l1_keepalives": {
- "description": "Always keep up Ethernet interface (does not always work)",
- "type": "boolean",
- "default": False
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"],
- "default": "telnet"
- },
- "console_auto_start": {
- "description": "Automatically start the console when the node has started",
- "type": "boolean",
- "default": False
- },
-}
-
-IOU_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-IOU_TEMPLATE_PROPERTIES["category"]["default"] = "router"
-IOU_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "IOU{0}"
-IOU_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/multilayer_switch.svg"
-
-IOU_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A IOU template object",
- "type": "object",
- "properties": IOU_TEMPLATE_PROPERTIES,
- "required": ["path"],
- "additionalProperties": False
-}
diff --git a/gns3server/endpoints/schemas/iou_templates.py b/gns3server/schemas/iou_templates.py
similarity index 76%
rename from gns3server/endpoints/schemas/iou_templates.py
rename to gns3server/schemas/iou_templates.py
index eaf90182..aef82181 100644
--- a/gns3server/endpoints/schemas/iou_templates.py
+++ b/gns3server/schemas/iou_templates.py
@@ -17,30 +17,18 @@
from .templates import Category, TemplateBase
+from .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]
diff --git a/gns3server/schemas/label.py b/gns3server/schemas/label.py
deleted file mode 100644
index 503ea64b..00000000
--- a/gns3server/schemas/label.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-#
-# 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 .
-
-LABEL_OBJECT_SCHEMA = {
- "type": "object",
- "properties": {
- "text": {"type": "string"},
- "style": {
- "description": "SVG style attribute. Apply default style if null",
- "type": ["string", "null"]
- },
- "x": {
- "description": "Relative X position of the label. Center it if null",
- "type": ["integer", "null"]
- },
- "y": {
- "description": "Relative Y position of the label",
- "type": "integer"
- },
- "rotation": {
- "description": "Rotation of the label",
- "type": "integer",
- "minimum": -359,
- "maximum": 360
- },
- },
- "required": [
- "text"
- ],
- "additionalProperties": False
-}
diff --git a/gns3server/schemas/link.py b/gns3server/schemas/link.py
deleted file mode 100644
index 6dd5ffe4..00000000
--- a/gns3server/schemas/link.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/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 .
-
-from .label import LABEL_OBJECT_SCHEMA
-from .filter import FILTER_OBJECT_SCHEMA
-
-LINK_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A link object",
- "type": "object",
- "properties": {
- "link_id": {
- "description": "Link UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "project_id": {
- "description": "Project UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "nodes": {
- "description": "List of the VMS",
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "node_id": {
- "description": "Node UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "adapter_number": {
- "description": "Adapter number",
- "type": "integer"
- },
- "port_number": {
- "description": "Port number",
- "type": "integer"
- },
- "label": LABEL_OBJECT_SCHEMA
- },
- "required": ["node_id", "adapter_number", "port_number"],
- "additionalProperties": False
- }
- },
- "suspend": {
- "type": "boolean",
- "description": "Suspend the link"
- },
- "filters": FILTER_OBJECT_SCHEMA,
- "capturing": {
- "description": "Read only property. True if a capture running on the link",
- "type": "boolean"
- },
- "capture_file_name": {
- "description": "Read only property. The name of the capture file if a capture is running",
- "type": ["string", "null"]
- },
- "capture_file_path": {
- "description": "Read only property. The full path of the capture file if a capture is running",
- "type": ["string", "null"]
- },
- "capture_compute_id": {
- "description": "Read only property. The compute identifier where a capture is running",
- "type": ["string", "null"]
- },
- "link_type": {
- "description": "Type of link",
- "enum": ["ethernet", "serial"]
- }
- },
- "additionalProperties": False
-}
-
-
-LINK_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a packet capture on a link",
- "type": "object",
- "properties": {
- "data_link_type": {
- "description": "PCAP data link type (http://www.tcpdump.org/linktypes.html)",
- "enum": ["DLT_ATM_RFC1483", "DLT_EN10MB", "DLT_FRELAY", "DLT_C_HDLC", "DLT_PPP_SERIAL"]
- },
- "capture_file_name": {
- "description": "Read only property. The name of the capture file if capture is running",
- "type": "string"
- }
- },
- "additionalProperties": False
-}
diff --git a/gns3server/endpoints/schemas/links.py b/gns3server/schemas/links.py
similarity index 100%
rename from gns3server/endpoints/schemas/links.py
rename to gns3server/schemas/links.py
diff --git a/gns3server/endpoints/schemas/nat_nodes.py b/gns3server/schemas/nat_nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/nat_nodes.py
rename to gns3server/schemas/nat_nodes.py
diff --git a/gns3server/schemas/nio.py b/gns3server/schemas/nio.py
deleted file mode 100644
index edee0eab..00000000
--- a/gns3server/schemas/nio.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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 .
-
-from .filter import FILTER_OBJECT_SCHEMA
-
-
-NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to add a NIO for a VM instance",
- "type": "object",
- "definitions": {
- "UDP": {
- "description": "UDP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_udp"]
- },
- "lport": {
- "description": "Local port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "rhost": {
- "description": "Remote host",
- "type": "string",
- "minLength": 1
- },
- "rport": {
- "description": "Remote port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "suspend": {
- "type": "boolean",
- "description": "Suspend the link"
- },
- "filters": FILTER_OBJECT_SCHEMA
- },
- "required": ["type", "lport", "rhost", "rport"],
- "additionalProperties": False
- },
- "Ethernet": {
- "description": "Generic Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_generic_ethernet", "nio_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "LinuxEthernet": {
- "description": "Linux Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_linux_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "NAT": {
- "description": "NAT Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_nat"]
- },
- },
- "required": ["type"],
- "additionalProperties": False
- },
- "TAP": {
- "description": "TAP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_tap"]
- },
- "tap_device": {
- "description": "TAP device name e.g. tap0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "tap_device"],
- "additionalProperties": False
- },
- "UNIX": {
- "description": "UNIX Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_unix"]
- },
- "local_file": {
- "description": "path to the UNIX socket file (local)",
- "type": "string",
- "minLength": 1
- },
- "remote_file": {
- "description": "path to the UNIX socket file (remote)",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "local_file", "remote_file"],
- "additionalProperties": False
- },
- "VDE": {
- "description": "VDE Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_vde"]
- },
- "control_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- "local_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "control_file", "local_file"],
- "additionalProperties": False
- },
- "VMNET": {
- "description": "VMNET Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_vmnet"]
- },
- "vmnet": {
- "description": "VMnet interface name e.g. vmnet12",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "vmnet"],
- "additionalProperties": False
- },
- "NULL": {
- "description": "NULL Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_null"]
- },
- },
- "required": ["type"],
- "additionalProperties": False
- },
- },
- "oneOf": [
- {"$ref": "#/definitions/UDP"},
- {"$ref": "#/definitions/Ethernet"},
- {"$ref": "#/definitions/LinuxEthernet"},
- {"$ref": "#/definitions/NAT"},
- {"$ref": "#/definitions/TAP"},
- {"$ref": "#/definitions/UNIX"},
- {"$ref": "#/definitions/VDE"},
- {"$ref": "#/definitions/VMNET"},
- {"$ref": "#/definitions/NULL"},
- ],
- "additionalProperties": True,
- "required": ["type"]
-}
diff --git a/gns3server/endpoints/schemas/nios.py b/gns3server/schemas/nios.py
similarity index 100%
rename from gns3server/endpoints/schemas/nios.py
rename to gns3server/schemas/nios.py
diff --git a/gns3server/schemas/node.py b/gns3server/schemas/node.py
deleted file mode 100644
index d7d92583..00000000
--- a/gns3server/schemas/node.py
+++ /dev/null
@@ -1,301 +0,0 @@
-#!/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 .
-
-import copy
-from .label import LABEL_OBJECT_SCHEMA
-from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA
-
-NODE_TYPE_SCHEMA = {
- "description": "Type of node",
- "enum": [
- "cloud",
- "nat",
- "ethernet_hub",
- "ethernet_switch",
- "frame_relay_switch",
- "atm_switch",
- "docker",
- "dynamips",
- "vpcs",
- "traceng",
- "virtualbox",
- "vmware",
- "iou",
- "qemu"
- ]
-}
-
-NODE_LIST_IMAGES_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "List of binary images",
- "type": "array",
- "items": [
- {
- "type": "object",
- "properties": {
- "filename": {
- "description": "Image filename",
- "type": "string",
- "minLength": 1
- },
- "path": {
- "description": "Image path",
- "type": "string",
- "minLength": 1
- },
- "md5sum": {
- "description": "md5sum of the image if available",
- "type": ["string", "null"],
- "minLength": 1
- },
- "filesize": {
- "description": "size of the image if available",
- "type": ["integer", "null"],
- "minimum": 0
- }
- },
- "required": ["filename", "path"],
- "additionalProperties": False
- }
- ],
- "additionalProperties": False,
-}
-
-
-NODE_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a packet capture on a port",
- "type": "object",
- "properties": {
- "capture_file_name": {
- "description": "Capture file name",
- "type": "string",
- "minLength": 1,
- },
- "data_link_type": {
- "description": "PCAP data link type (http://www.tcpdump.org/linktypes.html)",
- "enum": ["DLT_ATM_RFC1483", "DLT_EN10MB", "DLT_FRELAY", "DLT_C_HDLC", "DLT_PPP_SERIAL"]
- }
- },
- "additionalProperties": False,
- "required": ["capture_file_name"]
-}
-
-
-NODE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A node object",
- "type": "object",
- "properties": {
- "compute_id": {
- "description": "Compute identifier",
- "type": "string"
- },
- "project_id": {
- "description": "Project UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "node_id": {
- "description": "Node UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "template_id": {
- "description": "Template UUID from which the node has been created. Read only",
- "type": ["null", "string"],
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "node_type": NODE_TYPE_SCHEMA,
- "node_directory": {
- "description": "Working directory of the node. Read only",
- "type": ["null", "string"]
- },
- "command_line": {
- "description": "Command line use to start the node",
- "type": ["null", "string"]
- },
- "name": {
- "description": "Node name",
- "type": "string",
- "minLength": 1,
- },
- "console": {
- "description": "Console TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": ["integer", "null"]
- },
- "console_host": {
- "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.",
- "type": "string",
- "minLength": 1,
- },
- "console_type": {
- "description": "Console type",
- "enum": ["vnc", "telnet", "http", "https", "spice", "spice+agent", "none", None]
- },
- "console_auto_start": {
- "description": "Automatically start the console when the node has started",
- "type": "boolean"
- },
- "aux": {
- "description": "Auxiliary console TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": ["integer", "null"]
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["vnc", "telnet", "http", "https", "spice", "spice+agent", "none", None]
- },
- "properties": {
- "description": "Properties specific to an emulator",
- "type": "object"
- },
- "status": {
- "description": "Status of the node",
- "enum": ["stopped", "started", "suspended"]
- },
- "label": LABEL_OBJECT_SCHEMA,
- "symbol": {
- "description": "Symbol of the node",
- "type": ["string", "null"],
- "minLength": 1
- },
- "width": {
- "description": "Width of the node (Read only)",
- "type": "integer"
- },
- "height": {
- "description": "Height of the node (Read only)",
- "type": "integer"
- },
- "x": {
- "description": "X position of the node",
- "type": "integer"
- },
- "y": {
- "description": "Y position of the node",
- "type": "integer"
- },
- "z": {
- "description": "Z position of the node",
- "type": "integer"
- },
- "locked": {
- "description": "Whether the element locked or not",
- "type": "boolean"
- },
- "port_name_format": {
- "description": "Formating for port name {0} will be replace by port number",
- "type": "string"
- },
- "port_segment_size": {
- "description": "Size of the port segment",
- "type": "integer",
- "minimum": 0
- },
- "first_port_name": {
- "description": "Name of the first port",
- "type": ["string", "null"],
- },
- "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA,
- "ports": {
- "description": "List of node ports READ only",
- "type": "array",
- "items": {
- "type": "object",
- "description": "A node port",
- "properties": {
- "name": {
- "type": "string",
- "description": "Port name",
- },
- "short_name": {
- "type": "string",
- "description": "Short version of port name",
- },
- "adapter_number": {
- "type": "integer",
- "description": "Adapter slot"
- },
- "adapter_type": {
- "description": "Adapter type",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "port_number": {
- "type": "integer",
- "description": "Port slot"
- },
- "link_type": {
- "description": "Type of link",
- "enum": ["ethernet", "serial"]
- },
- "data_link_types": {
- "type": "object",
- "description": "Available PCAP types for capture",
- "properties": {}
- },
- "mac_address": {
- "description": "MAC address (if available)",
- "type": ["string", "null"],
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"
- },
- },
- "additionalProperties": False
- }
- }
- },
- "additionalProperties": False,
- "required": ["name", "node_type", "compute_id"]
-}
-
-NODE_CREATE_SCHEMA = NODE_OBJECT_SCHEMA
-NODE_UPDATE_SCHEMA = copy.deepcopy(NODE_OBJECT_SCHEMA)
-del NODE_UPDATE_SCHEMA["required"]
-
-
-NODE_DUPLICATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Duplicate a node",
- "type": "object",
- "properties": {
- "x": {
- "description": "X position of the node",
- "type": "integer"
- },
- "y": {
- "description": "Y position of the node",
- "type": "integer"
- },
- "z": {
- "description": "Z position of the node",
- "type": "integer"
- }
- },
- "additionalProperties": False,
- "required": ["x", "y"]
-}
diff --git a/gns3server/endpoints/schemas/nodes.py b/gns3server/schemas/nodes.py
similarity index 100%
rename from gns3server/endpoints/schemas/nodes.py
rename to gns3server/schemas/nodes.py
diff --git a/gns3server/schemas/port.py b/gns3server/schemas/port.py
deleted file mode 100644
index 26c00913..00000000
--- a/gns3server/schemas/port.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env python
-#
-# 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 .
-
-
-PORT_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A port use in the cloud",
- "type": "object",
- "oneOf": [
- {
- "description": "Ethernet interface port",
- "properties": {
- "name": {
- "description": "Port name",
- "type": "string",
- "minLength": 1,
- },
- "port_number": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0
- },
- "type": {
- "description": "Port type",
- "enum": ["ethernet"]
- },
- "interface": {
- "description": "Ethernet interface name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["name", "port_number", "type", "interface"],
- "additionalProperties": False
- },
- {
- "description": "TAP interface port",
- "properties": {
- "name": {
- "description": "Port name",
- "type": "string",
- "minLength": 1,
- },
- "port_number": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0
- },
- "type": {
- "description": "Port type",
- "enum": ["tap"]
- },
- "interface": {
- "description": "TAP interface name e.g. tap0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["name", "port_number", "type", "interface"],
- "additionalProperties": False
- },
- {
- "description": "UDP tunnel port",
- "properties": {
- "name": {
- "description": "Port name",
- "type": "string",
- "minLength": 1,
- },
- "port_number": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0
- },
- "type": {
- "description": "Port type",
- "enum": ["udp"]
- },
- "lport": {
- "description": "Local UDP tunnel port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "rhost": {
- "description": "Remote UDP tunnel host",
- "type": "string",
- "minLength": 1
- },
- "rport": {
- "description": "Remote UDP tunnel port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "required": ["name", "port_number", "type", "lport", "rhost", "rport"],
- "additionalProperties": False
- }
- ]
-}
diff --git a/gns3server/schemas/project.py b/gns3server/schemas/project.py
deleted file mode 100644
index b65b745b..00000000
--- a/gns3server/schemas/project.py
+++ /dev/null
@@ -1,329 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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 .
-
-import copy
-
-SUPPLIER_OBJECT_SCHEMA = {
- "type": ["object", "null"],
- "description": "Supplier of the project",
- "properties": {
- "logo": {
- "type": "string",
- "description": "Path to the project supplier logo"
- },
- "url": {
- "type": "string",
- "description": "URL to the project supplier site"
- }
- }
-}
-
-
-VARIABLES_OBJECT_SCHEMA = {
- "type": ["array", "null"],
- "description": "Variables required to run the project",
- "items": {
- "properties": {
- "name": {
- "type": "string",
- "description": "Variable name",
- "minLength": 1
- },
- "value": {
- "type": "string",
- "description": "Variable value"
- }
- },
- "required": ["name"]
- }
-}
-
-
-PROJECT_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new Project instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "Project name",
- "type": ["string", "null"],
- "minLength": 1
- },
- "path": {
- "description": "Project directory",
- "type": ["string", "null"],
- "minLength": 1
- },
- "auto_close": {
- "description": "Project auto close",
- "type": "boolean"
- },
- "project_id": {
- "description": "Project UUID",
- "type": ["string", "null"],
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "scene_height": {
- "type": "integer",
- "description": "Height of the drawing area"
- },
- "scene_width": {
- "type": "integer",
- "description": "Width of the drawing area"
- },
- "zoom": {
- "type": "integer",
- "description": "Zoom of the drawing area"
- },
- "show_layers": {
- "type": "boolean",
- "description": "Show layers on the drawing area"
- },
- "snap_to_grid": {
- "type": "boolean",
- "description": "Snap to grid on the drawing area"
- },
- "show_grid": {
- "type": "boolean",
- "description": "Show the grid on the drawing area"
- },
- "grid_size": {
- "type": "integer",
- "description": "Grid size for the drawing area for nodes"
- },
- "drawing_grid_size": {
- "type": "integer",
- "description": "Grid size for the drawing area for drawings"
- },
- "show_interface_labels": {
- "type": "boolean",
- "description": "Show interface labels on the drawing area"
- },
- "supplier": SUPPLIER_OBJECT_SCHEMA,
- "variables": VARIABLES_OBJECT_SCHEMA
- },
- "additionalProperties": False,
- "required": ["name"]
-}
-
-# Create a project duplicate schema based on create schema and add "reset_mac_addresses" properties
-PROJECT_DUPLICATE_SCHEMA = copy.deepcopy(PROJECT_CREATE_SCHEMA)
-PROJECT_DUPLICATE_SCHEMA["description"] = "Request validation to duplicate a Project instance"
-PROJECT_DUPLICATE_SCHEMA["properties"].update({"reset_mac_addresses": {"type": "boolean",
- "description": "Reset MAC addresses for this project"
- }})
-
-PROJECT_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update a Project instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "Project name",
- "type": ["string", "null"],
- "minLength": 1
- },
- "path": {
- "description": "Path of the project on the server (work only with --local)",
- "type": ["string", "null"]
- },
- "auto_close": {
- "description": "Project auto close when client cut off the notifications feed",
- "type": "boolean"
- },
- "auto_open": {
- "description": "Project open when GNS3 start",
- "type": "boolean"
- },
- "auto_start": {
- "description": "Project start when opened",
- "type": "boolean"
- },
- "scene_height": {
- "type": "integer",
- "description": "Height of the drawing area"
- },
- "scene_width": {
- "type": "integer",
- "description": "Width of the drawing area"
- },
- "zoom": {
- "type": "integer",
- "description": "Zoom of the drawing area"
- },
- "show_layers": {
- "type": "boolean",
- "description": "Show layers on the drawing area"
- },
- "snap_to_grid": {
- "type": "boolean",
- "description": "Snap to grid on the drawing area"
- },
- "show_grid": {
- "type": "boolean",
- "description": "Show the grid on the drawing area"
- },
- "grid_size": {
- "type": "integer",
- "description": "Grid size for the drawing area for nodes"
- },
- "drawing_grid_size": {
- "type": "integer",
- "description": "Grid size for the drawing area for drawings"
- },
- "show_interface_labels": {
- "type": "boolean",
- "description": "Show interface labels on the drawing area"
- },
- "supplier": SUPPLIER_OBJECT_SCHEMA,
- "variables": VARIABLES_OBJECT_SCHEMA
- },
- "additionalProperties": False,
-}
-
-PROJECT_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Project instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "Project name",
- "type": ["string", "null"],
- "minLength": 1
- },
- "project_id": {
- "description": "Project UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "path": {
- "description": "Project directory",
- "type": ["string", "null"],
- "minLength": 1
- },
- "filename": {
- "description": "Project filename",
- "type": ["string", "null"],
- "minLength": 1
- },
- "status": {
- "description": "Project status Read only",
- "enum": ["opened", "closed"]
- },
- "auto_close": {
- "description": "Project auto close when client cut off the notifications feed",
- "type": "boolean"
- },
- "auto_open": {
- "description": "Project open when GNS3 start",
- "type": "boolean"
- },
- "auto_start": {
- "description": "Project start when opened",
- "type": "boolean"
- },
- "scene_height": {
- "type": "integer",
- "description": "Height of the drawing area"
- },
- "scene_width": {
- "type": "integer",
- "description": "Width of the drawing area"
- },
- "zoom": {
- "type": "integer",
- "description": "Zoom of the drawing area"
- },
- "show_layers": {
- "type": "boolean",
- "description": "Show layers on the drawing area"
- },
- "snap_to_grid": {
- "type": "boolean",
- "description": "Snap to grid on the drawing area"
- },
- "show_grid": {
- "type": "boolean",
- "description": "Show the grid on the drawing area"
- },
- "grid_size": {
- "type": "integer",
- "description": "Grid size for the drawing area for nodes"
- },
- "drawing_grid_size": {
- "type": "integer",
- "description": "Grid size for the drawing area for drawings"
- },
- "show_interface_labels": {
- "type": "boolean",
- "description": "Show interface labels on the drawing area"
- },
- "supplier": SUPPLIER_OBJECT_SCHEMA,
- "variables": VARIABLES_OBJECT_SCHEMA
- },
- "additionalProperties": False,
- "required": ["project_id"]
-}
-
-PROJECT_LOAD_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Load a project",
- "type": "object",
- "properties": {
- "path": {
- "description": ".gns3 path",
- "type": "string",
- "minLength": 1
- }
- },
- "additionalProperties": False,
- "required": ["path"]
-}
-
-PROJECT_LIST_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "List of projects",
- "type": "array",
- "items": PROJECT_OBJECT_SCHEMA
-}
-
-PROJECT_FILE_LIST_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "List files in the project",
- "type": "array",
- "items": [
- {
- "type": "object",
- "properties": {
- "path": {
- "description": "File path",
- "type": ["string"]
- },
- "md5sum": {
- "description": "MD5 hash of the file",
- "type": ["string"]
- },
-
- },
- }
- ],
- "additionalProperties": False,
-}
diff --git a/gns3server/endpoints/schemas/projects.py b/gns3server/schemas/projects.py
similarity index 97%
rename from gns3server/endpoints/schemas/projects.py
rename to gns3server/schemas/projects.py
index 9fc6b771..ec0c14b0 100644
--- a/gns3server/endpoints/schemas/projects.py
+++ b/gns3server/schemas/projects.py
@@ -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):
diff --git a/gns3server/schemas/qemu.py b/gns3server/schemas/qemu.py
deleted file mode 100644
index 41a79d50..00000000
--- a/gns3server/schemas/qemu.py
+++ /dev/null
@@ -1,886 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 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 .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA
-
-QEMU_PLATFORMS = ["aarch64", "alpha", "arm", "cris", "i386", "lm32", "m68k", "microblaze", "microblazeel", "mips", "mips64", "mips64el", "mipsel", "moxie", "or32", "ppc", "ppc64", "ppcemb", "s390x", "sh4", "sh4eb", "sparc", "sparc64", "tricore", "unicore32", "x86_64", "xtensa", "xtensaeb", ""]
-
-
-QEMU_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new QEMU VM instance",
- "type": "object",
- "properties": {
- "node_id": {
- "description": "Node UUID",
- "oneOf": [
- {"type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"},
- {"type": "integer"} # for legacy projects
- ]
- },
- "name": {
- "description": "QEMU VM instance name",
- "type": "string",
- "minLength": 1,
- },
- "usage": {
- "description": "How to use the Qemu VM",
- "type": "string",
- },
- "linked_clone": {
- "description": "Whether the VM is a linked clone or not",
- "type": "boolean"
- },
- "qemu_path": {
- "description": "Path to QEMU",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "platform": {
- "description": "Platform to emulate",
- "enum": QEMU_PLATFORMS + ["null"]
- },
- "console": {
- "description": "Console TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": ["integer", "null"]
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
- },
- "aux": {
- "description": "Auxiliary TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": ["integer", "null"]
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
- },
- "hda_disk_image": {
- "description": "QEMU hda disk image path",
- "type": "string",
- },
- "hda_disk_interface": {
- "description": "QEMU hda interface",
- "type": "string",
- },
- "hda_disk_image_md5sum": {
- "description": "QEMU hda disk image checksum",
- "type": ["string", "null"]
- },
- "hdb_disk_image": {
- "description": "QEMU hdb disk image path",
- "type": "string",
- },
- "hdb_disk_interface": {
- "description": "QEMU hdb interface",
- "type": "string",
- },
- "hdb_disk_image_md5sum": {
- "description": "QEMU hdb disk image checksum",
- "type": ["string", "null"],
- },
- "hdc_disk_image": {
- "description": "QEMU hdc disk image path",
- "type": "string",
- },
- "hdc_disk_interface": {
- "description": "QEMU hdc interface",
- "type": "string",
- },
- "hdc_disk_image_md5sum": {
- "description": "QEMU hdc disk image checksum",
- "type": ["string", "null"],
- },
- "hdd_disk_image": {
- "description": "QEMU hdd disk image path",
- "type": "string",
- },
- "hdd_disk_interface": {
- "description": "QEMU hdd interface",
- "type": "string",
- },
- "hdd_disk_image_md5sum": {
- "description": "QEMU hdd disk image checksum",
- "type": ["string", "null"],
- },
- "cdrom_image": {
- "description": "QEMU cdrom image path",
- "type": "string",
- },
- "cdrom_image_md5sum": {
- "description": "QEMU cdrom image checksum",
- "type": ["string", "null"],
- },
- "bios_image": {
- "description": "QEMU bios image path",
- "type": "string",
- },
- "bios_image_md5sum": {
- "description": "QEMU bios image checksum",
- "type": ["string", "null"],
- },
- "boot_priority": {
- "description": "QEMU boot priority",
- "enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"]
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": ["integer", "null"]
- },
- "cpus": {
- "description": "Number of vCPUs",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 255,
- },
- "maxcpus": {
- "description": "Maximum number of hotpluggable vCPUs",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 255,
- },
- "adapters": {
- "description": "Number of adapters",
- "type": ["integer", "null"],
- "minimum": 0,
- "maximum": 275,
- },
- "adapter_type": {
- "description": "QEMU adapter type",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "mac_address": {
- "description": "QEMU MAC address",
- "type": ["string", "null"],
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"
- },
- "initrd": {
- "description": "QEMU initrd path",
- "type": "string",
- },
- "initrd_md5sum": {
- "description": "QEMU initrd path",
- "type": ["string", "null"],
- },
- "kernel_image": {
- "description": "QEMU kernel image path",
- "type": "string",
- },
- "kernel_image_md5sum": {
- "description": "QEMU kernel image checksum",
- "type": ["string", "null"],
- },
- "kernel_command_line": {
- "description": "QEMU kernel command line",
- "type": ["string", "null"],
- },
- "legacy_networking": {
- "description": "Use QEMU legagy networking commands (-net syntax)",
- "type": ["boolean", "null"],
- },
- "replicate_network_connection_state": {
- "description": "Replicate the network connection state for links in Qemu",
- "type": ["boolean", "null"],
- },
- "create_config_disk": {
- "description": "Automatically create a config disk on HDD disk interface (secondary slave)",
- "type": ["boolean", "null"],
- },
- "on_close": {
- "description": "Action to execute on the VM is closed",
- "enum": ["power_off", "shutdown_signal", "save_vm_state"],
- },
- "cpu_throttling": {
- "description": "Percentage of CPU allowed for QEMU",
- "minimum": 0,
- "maximum": 800,
- "type": ["integer", "null"],
- },
- "process_priority": {
- "description": "Process priority for QEMU",
- "enum": ["realtime",
- "very high",
- "high",
- "normal",
- "low",
- "very low",
- "null"]
- },
- "options": {
- "description": "Additional QEMU options",
- "type": ["string", "null"],
- },
- "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA
- },
- "additionalProperties": False,
- "required": ["name"],
-}
-
-QEMU_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update a QEMU VM instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "QEMU VM instance name",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "usage": {
- "description": "How to use the QEMU VM",
- "type": "string",
- },
- "qemu_path": {
- "description": "Path to QEMU",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "platform": {
- "description": "Platform to emulate",
- "enum": QEMU_PLATFORMS + ["null"]
- },
- "console": {
- "description": "Console TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": ["integer", "null"]
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
- },
- "aux": {
- "description": "Auxiliary TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": ["integer", "null"]
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
- },
- "linked_clone": {
- "description": "Whether the VM is a linked clone or not",
- "type": "boolean"
- },
- "hda_disk_image": {
- "description": "QEMU hda disk image path",
- "type": "string",
- },
- "hda_disk_interface": {
- "description": "QEMU hda interface",
- "type": "string",
- },
- "hda_disk_image_md5sum": {
- "description": "QEMU hda disk image checksum",
- "type": ["string", "null"]
- },
- "hdb_disk_image": {
- "description": "QEMU hdb disk image path",
- "type": "string",
- },
- "hdb_disk_interface": {
- "description": "QEMU hdb interface",
- "type": "string",
- },
- "hdb_disk_image_md5sum": {
- "description": "QEMU hdb disk image checksum",
- "type": ["string", "null"],
- },
- "hdc_disk_image": {
- "description": "QEMU hdc disk image path",
- "type": "string",
- },
- "hdc_disk_interface": {
- "description": "QEMU hdc interface",
- "type": "string",
- },
- "hdc_disk_image_md5sum": {
- "description": "QEMU hdc disk image checksum",
- "type": ["string", "null"],
- },
- "hdd_disk_image": {
- "description": "QEMU hdd disk image path",
- "type": "string",
- },
- "hdd_disk_interface": {
- "description": "QEMU hdd interface",
- "type": "string",
- },
- "hdd_disk_image_md5sum": {
- "description": "QEMU hdd disk image checksum",
- "type": ["string", "null"],
- },
- "bios_image": {
- "description": "QEMU bios image path",
- "type": "string",
- },
- "bios_image_md5sum": {
- "description": "QEMU bios image checksum",
- "type": ["string", "null"],
- },
- "cdrom_image": {
- "description": "QEMU cdrom image path",
- "type": "string",
- },
- "cdrom_image_md5sum": {
- "description": "QEMU cdrom image checksum",
- "type": ["string", "null"],
- },
- "boot_priority": {
- "description": "QEMU boot priority",
- "enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"]
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": ["integer", "null"]
- },
- "cpus": {
- "description": "Number of vCPUs",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 255,
- },
- "maxcpus": {
- "description": "Maximum number of hotpluggable vCPUs",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 255,
- },
- "adapters": {
- "description": "Number of adapters",
- "type": ["integer", "null"],
- "minimum": 0,
- "maximum": 275,
- },
- "adapter_type": {
- "description": "QEMU adapter type",
- "type": ["string", "null"],
- "minLength": 1,
- },
- "mac_address": {
- "description": "QEMU MAC address",
- "type": ["string", "null"],
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"
- },
- "initrd": {
- "description": "QEMU initrd path",
- "type": "string",
- },
- "initrd_md5sum": {
- "description": "QEMU initrd path",
- "type": ["string", "null"],
- },
- "kernel_image": {
- "description": "QEMU kernel image path",
- "type": "string",
- },
- "kernel_image_md5sum": {
- "description": "QEMU kernel image checksum",
- "type": ["string", "null"],
- },
- "kernel_command_line": {
- "description": "QEMU kernel command line",
- "type": ["string", "null"],
- },
- "legacy_networking": {
- "description": "Use QEMU legagy networking commands (-net syntax)",
- "type": ["boolean", "null"],
- },
- "replicate_network_connection_state": {
- "description": "Replicate the network connection state for links in Qemu",
- "type": ["boolean", "null"],
- },
- "create_config_disk": {
- "description": "Automatically create a config disk on HDD disk interface (secondary slave)",
- "type": ["boolean", "null"],
- },
- "on_close": {
- "description": "Action to execute on the VM is closed",
- "enum": ["power_off", "shutdown_signal", "save_vm_state"],
- },
- "cpu_throttling": {
- "description": "Percentage of CPU allowed for QEMU",
- "minimum": 0,
- "maximum": 800,
- "type": ["integer", "null"],
- },
- "process_priority": {
- "description": "Process priority for QEMU",
- "enum": ["realtime",
- "very high",
- "high",
- "normal",
- "low",
- "very low",
- "null"]
- },
- "options": {
- "description": "Additional QEMU options",
- "type": ["string", "null"],
- },
- "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA
- },
- "additionalProperties": False,
-}
-
-QEMU_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation for a QEMU VM instance",
- "type": "object",
- "properties": {
- "node_id": {
- "description": "Node UUID",
- "type": "string",
- "minLength": 1,
- },
- "project_id": {
- "description": "Project UUID",
- "type": "string",
- "minLength": 1,
- },
- "name": {
- "description": "QEMU VM instance name",
- "type": "string",
- "minLength": 1,
- },
- "status": {
- "description": "VM status",
- "enum": ["started", "stopped", "suspended"]
- },
- "usage": {
- "description": "How to use the QEMU VM",
- "type": "string",
- },
- "qemu_path": {
- "description": "Path to QEMU",
- "type": "string",
- "minLength": 1,
- },
- "platform": {
- "description": "Platform to emulate",
- "enum": QEMU_PLATFORMS
- },
- "hda_disk_image": {
- "description": "QEMU hda disk image path",
- "type": "string",
- },
- "hda_disk_interface": {
- "description": "QEMU hda interface",
- "type": "string",
- },
- "hda_disk_image_md5sum": {
- "description": "QEMU hda disk image checksum",
- "type": ["string", "null"]
- },
- "hdb_disk_image": {
- "description": "QEMU hdb disk image path",
- "type": "string",
- },
- "hdb_disk_interface": {
- "description": "QEMU hdb interface",
- "type": "string",
- },
- "hdb_disk_image_md5sum": {
- "description": "QEMU hdb disk image checksum",
- "type": ["string", "null"],
- },
- "hdc_disk_image": {
- "description": "QEMU hdc disk image path",
- "type": "string",
- },
- "hdc_disk_interface": {
- "description": "QEMU hdc interface",
- "type": "string",
- },
- "hdc_disk_image_md5sum": {
- "description": "QEMU hdc disk image checksum",
- "type": ["string", "null"],
- },
- "hdd_disk_image": {
- "description": "QEMU hdd disk image path",
- "type": "string",
- },
- "hdd_disk_interface": {
- "description": "QEMU hdd interface",
- "type": "string",
- },
- "hdd_disk_image_md5sum": {
- "description": "QEMU hdd disk image checksum",
- "type": ["string", "null"],
- },
- "bios_image": {
- "description": "QEMU bios image path",
- "type": "string",
- },
- "bios_image_md5sum": {
- "description": "QEMU bios image checksum",
- "type": ["string", "null"],
- },
- "cdrom_image": {
- "description": "QEMU cdrom image path",
- "type": "string",
- },
- "cdrom_image_md5sum": {
- "description": "QEMU cdrom image checksum",
- "type": ["string", "null"],
- },
- "boot_priority": {
- "description": "QEMU boot priority",
- "enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"]
- },
- "node_directory": {
- "description": "Path to the VM working directory",
- "type": "string"
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer"
- },
- "cpus": {
- "description": "Number of vCPUs",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 255,
- },
- "maxcpus": {
- "description": "Maximum number of hotpluggable vCPUs",
- "type": ["integer", "null"],
- "minimum": 1,
- "maximum": 255,
- },
- "adapters": {
- "description": "Number of adapters",
- "type": "integer",
- "minimum": 0,
- "maximum": 275,
- },
- "adapter_type": {
- "description": "QEMU adapter type",
- "type": "string",
- "minLength": 1,
- },
- "mac_address": {
- "description": "QEMU MAC address",
- "type": "string",
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"
- },
- "console": {
- "description": "Console TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": ["integer", "null"]
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "vnc", "spice","spice+agent", "none"]
- },
- "aux": {
- "description": "Auxiliary TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": ["integer", "null"]
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
- },
- "initrd": {
- "description": "QEMU initrd path",
- "type": "string",
- },
- "initrd_md5sum": {
- "description": "QEMU initrd path",
- "type": ["string", "null"],
- },
- "kernel_image": {
- "description": "QEMU kernel image path",
- "type": "string",
- },
- "kernel_image_md5sum": {
- "description": "QEMU kernel image checksum",
- "type": ["string", "null"],
- },
- "kernel_command_line": {
- "description": "QEMU kernel command line",
- "type": "string",
- },
- "legacy_networking": {
- "description": "Use QEMU legagy networking commands (-net syntax)",
- "type": "boolean",
- },
- "replicate_network_connection_state": {
- "description": "Replicate the network connection state for links in Qemu",
- "type": "boolean",
- },
- "create_config_disk": {
- "description": "Automatically create a config disk on HDD disk interface (secondary slave)",
- "type": ["boolean", "null"],
- },
- "on_close": {
- "description": "Action to execute on the VM is closed",
- "enum": ["power_off", "shutdown_signal", "save_vm_state"],
- },
- "save_vm_state": {
- "description": "Save VM state support",
- "type": ["boolean", "null"],
- },
- "cpu_throttling": {
- "description": "Percentage of CPU allowed for QEMU",
- "minimum": 0,
- "maximum": 800,
- "type": "integer",
- },
- "process_priority": {
- "description": "Process priority for QEMU",
- "enum": ["realtime",
- "very high",
- "high",
- "normal",
- "low",
- "very low"]
- },
- "options": {
- "description": "Additional QEMU options",
- "type": "string",
- },
- "command_line": {
- "description": "Last command line used by GNS3 to start QEMU",
- "type": "string"
- }
- },
- "additionalProperties": False,
- "required": ["node_id",
- "project_id",
- "name",
- "usage",
- "qemu_path",
- "platform",
- "console_type",
- "aux_type",
- "hda_disk_image",
- "hdb_disk_image",
- "hdc_disk_image",
- "hdd_disk_image",
- "hda_disk_image_md5sum",
- "hdb_disk_image_md5sum",
- "hdc_disk_image_md5sum",
- "hdd_disk_image_md5sum",
- "hda_disk_interface",
- "hdb_disk_interface",
- "hdc_disk_interface",
- "hdd_disk_interface",
- "cdrom_image",
- "cdrom_image_md5sum",
- "bios_image",
- "bios_image_md5sum",
- "boot_priority",
- "ram",
- "cpus",
- "maxcpus",
- "adapters",
- "adapter_type",
- "mac_address",
- "console",
- "aux",
- "initrd",
- "kernel_image",
- "initrd_md5sum",
- "kernel_image_md5sum",
- "kernel_command_line",
- "legacy_networking",
- "replicate_network_connection_state",
- "create_config_disk",
- "on_close",
- "cpu_throttling",
- "process_priority",
- "options",
- "node_directory",
- "command_line",
- "status"]
-}
-
-QEMU_RESIZE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Resize a disk in a QEMU VM",
- "type": "object",
- "properties": {
- "drive_name": {
- "description": "Absolute or relative path of the image",
- "enum": ["hda", "hdb", "hdc", "hdd"]
- },
- "extend": {
- "description": "Number of Megabytes to extend the image",
- "type": "integer"
- },
- # TODO: support shrink? (could be dangerous)
- },
- "required": ["drive_name", "extend"],
- "additionalProperties": False
-}
-
-QEMU_BINARY_FILTER_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation for a list of QEMU capabilities",
- "properties": {
- "archs": {
- "description": "Architectures to filter binaries with",
- "type": "array",
- "items": {
- "enum": QEMU_PLATFORMS
- }
- }
- },
- "additionalProperties": False,
-}
-
-QEMU_BINARY_LIST_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation for a list of QEMU binaries",
- "type": "array",
- "items": {
- "$ref": "#/definitions/QemuPath"
- },
- "definitions": {
- "QemuPath": {
- "description": "Qemu path object",
- "properties": {
- "path": {
- "description": "Qemu path",
- "type": "string",
- },
- "version": {
- "description": "Qemu version",
- "type": "string",
- },
- },
- }
- },
- "additionalProperties": False,
-}
-
-QEMU_CAPABILITY_LIST_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation for a list of QEMU capabilities",
- "properties": {
- "kvm": {
- "description": "Architectures that KVM is enabled for",
- "type": "array",
- "items": {
- "enum": QEMU_PLATFORMS
- }
- }
- },
- "additionalProperties": False,
-}
-
-QEMU_IMAGE_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Create a new QEMU image. Options can be specific to a format. Read qemu-img manual for more information",
- "type": "object",
- "properties": {
- "qemu_img": {
- "description": "Path to the qemu-img binary",
- "type": "string"
- },
- "path": {
- "description": "Absolute or relative path of the image",
- "type": "string"
- },
- "format": {
- "description": "Image format type",
- "enum": ["qcow2", "qcow", "vpc", "vdi", "vmdk", "raw"]
- },
- "size": {
- "description": "Image size in Megabytes",
- "type": "integer"
- },
- "preallocation": {
- "enum": ["off", "metadata", "falloc", "full"]
- },
- "cluster_size": {
- "type": "integer"
- },
- "refcount_bits": {
- "type": "integer"
- },
- "lazy_refcounts": {
- "enum": ["on", "off"]
- },
- "subformat": {
- "enum": [
- "dynamic",
- "fixed",
- "streamOptimized",
- "twoGbMaxExtentSparse",
- "twoGbMaxExtentFlat",
- "monolithicSparse",
- "monolithicFlat",
- ]
- },
- "static": {
- "enum": ["on", "off"]
- },
- "zeroed_grain": {
- "enum": ["on", "off"]
- },
- "adapter_type": {
- "enum": [
- "ide",
- "lsilogic",
- "buslogic",
- "legacyESX"
- ]
- }
- },
- "required": ["qemu_img", "path", "format", "size"],
- "additionalProperties": False
-}
-
-QEMU_IMAGE_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Update an existing QEMU image",
- "type": "object",
- "properties": {
- "qemu_img": {
- "description": "Path to the qemu-img binary",
- "type": "string"
- },
- "path": {
- "description": "Absolute or relative path of the image",
- "type": "string"
- },
- "extend": {
- "description": "Number of Megabytes to extend the image",
- "type": "integer"
- },
- },
- "required": ["qemu_img", "path"],
- "additionalProperties": False
-}
diff --git a/gns3server/endpoints/schemas/qemu_nodes.py b/gns3server/schemas/qemu_nodes.py
similarity index 85%
rename from gns3server/endpoints/schemas/qemu_nodes.py
rename to gns3server/schemas/qemu_nodes.py
index 6fad2b5e..1d42ec07 100644
--- a/gns3server/endpoints/schemas/qemu_nodes.py
+++ b/gns3server/schemas/qemu_nodes.py
@@ -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")
diff --git a/gns3server/schemas/qemu_template.py b/gns3server/schemas/qemu_template.py
deleted file mode 100644
index 213c6e9e..00000000
--- a/gns3server/schemas/qemu_template.py
+++ /dev/null
@@ -1,234 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA
-from .qemu import QEMU_PLATFORMS
-
-
-QEMU_TEMPLATE_PROPERTIES = {
- "qemu_path": {
- "description": "Path to QEMU",
- "type": "string",
- "default": ""
- },
- "platform": {
- "description": "Platform to emulate",
- "enum": QEMU_PLATFORMS,
- "default": "i386"
- },
- "linked_clone": {
- "description": "Whether the VM is a linked clone or not",
- "type": "boolean",
- "default": True
- },
- "ram": {
- "description": "Amount of RAM in MB",
- "type": "integer",
- "default": 256
- },
- "cpus": {
- "description": "Number of vCPUs",
- "type": "integer",
- "minimum": 1,
- "maximum": 255,
- "default": 1
- },
- "maxcpus": {
- "description": "Maximum number of hotpluggable vCPUs",
- "type": "integer",
- "minimum": 1,
- "maximum": 255,
- "default": 1
- },
- "adapters": {
- "description": "Number of adapters",
- "type": "integer",
- "minimum": 0,
- "maximum": 275,
- "default": 1
- },
- "adapter_type": {
- "description": "QEMU adapter type",
- "type": "string",
- "enum": ["e1000", "e1000-82544gc", "e1000-82545em", "e1000e", "i82550", "i82551", "i82557a", "i82557b", "i82557c", "i82558a",
- "i82558b", "i82559a", "i82559b", "i82559c", "i82559er", "i82562", "i82801", "ne2k_pci", "pcnet", "rocker", "rtl8139",
- "virtio", "virtio-net-pci", "vmxnet3"],
- "default": "e1000"
- },
- "mac_address": {
- "description": "QEMU MAC address",
- "type": ["string", "null"],
- "anyOf": [
- {"pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"},
- {"pattern": "^$"}
- ],
- "default": "",
- },
- "first_port_name": {
- "description": "Optional name of the first networking port example: eth0",
- "type": "string",
- "default": ""
- },
- "port_name_format": {
- "description": "Optional formatting of the networking port example: eth{0}",
- "type": "string",
- "default": "Ethernet{0}"
- },
- "port_segment_size": {
- "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",
- "type": "integer",
- "default": 0
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "vnc", "spice", "spice+agent", "none"],
- "default": "telnet"
- },
- "console_auto_start": {
- "description": "Automatically start the console when the node has started",
- "type": "boolean",
- "default": False
- },
- "aux_type": {
- "description": "Auxiliary console type",
- "enum": ["telnet", "vnc", "spice", "spice+agent", "none"],
- "default": "none"
- },
- "boot_priority": {
- "description": "QEMU boot priority",
- "enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"],
- "default": "c"
- },
- "hda_disk_image": {
- "description": "QEMU hda disk image path",
- "type": "string",
- "default": ""
- },
- "hda_disk_interface": {
- "description": "QEMU hda interface",
- "enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"],
- "default": "none"
- },
- "hdb_disk_image": {
- "description": "QEMU hdb disk image path",
- "type": "string",
- "default": ""
- },
- "hdb_disk_interface": {
- "description": "QEMU hdb interface",
- "enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"],
- "default": "none"
- },
- "hdc_disk_image": {
- "description": "QEMU hdc disk image path",
- "type": "string",
- "default": ""
- },
- "hdc_disk_interface": {
- "description": "QEMU hdc interface",
- "enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"],
- "default": "none"
- },
- "hdd_disk_image": {
- "description": "QEMU hdd disk image path",
- "type": "string",
- "default": ""
- },
- "hdd_disk_interface": {
- "description": "QEMU hdd interface",
- "enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"],
- "default": "none"
- },
- "cdrom_image": {
- "description": "QEMU cdrom image path",
- "type": "string",
- "default": ""
- },
- "initrd": {
- "description": "QEMU initrd path",
- "type": "string",
- "default": ""
- },
- "kernel_image": {
- "description": "QEMU kernel image path",
- "type": "string",
- "default": ""
- },
- "bios_image": {
- "description": "QEMU bios image path",
- "type": "string",
- "default": ""
- },
- "kernel_command_line": {
- "description": "QEMU kernel command line",
- "type": "string",
- "default": ""
- },
- "legacy_networking": {
- "description": "Use QEMU legagy networking commands (-net syntax)",
- "type": "boolean",
- "default": False
- },
- "replicate_network_connection_state": {
- "description": "Replicate the network connection state for links in Qemu",
- "type": "boolean",
- "default": True
- },
- "create_config_disk": {
- "description": "Automatically create a config disk on HDD disk interface (secondary slave)",
- "type": "boolean",
- "default": False
- },
- "on_close": {
- "description": "Action to execute on the VM is closed",
- "enum": ["power_off", "shutdown_signal", "save_vm_state"],
- "default": "power_off"
- },
- "cpu_throttling": {
- "description": "Percentage of CPU allowed for QEMU",
- "minimum": 0,
- "maximum": 800,
- "type": "integer",
- "default": 0
- },
- "process_priority": {
- "description": "Process priority for QEMU",
- "enum": ["realtime", "very high", "high", "normal", "low", "very low"],
- "default": "normal"
- },
- "options": {
- "description": "Additional QEMU options",
- "type": "string",
- "default": ""
- },
- "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA
-}
-
-QEMU_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-QEMU_TEMPLATE_PROPERTIES["category"]["default"] = "guest"
-QEMU_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}"
-QEMU_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/qemu_guest.svg"
-
-QEMU_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A Qemu template object",
- "type": "object",
- "properties": QEMU_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
diff --git a/gns3server/schemas/qemu_templates.py b/gns3server/schemas/qemu_templates.py
new file mode 100644
index 00000000..636983bd
--- /dev/null
+++ b/gns3server/schemas/qemu_templates.py
@@ -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 .
+
+
+from .templates import Category, TemplateBase
+from .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")
diff --git a/gns3server/schemas/server_statistics.py b/gns3server/schemas/server_statistics.py
deleted file mode 100644
index 048799b3..00000000
--- a/gns3server/schemas/server_statistics.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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 .
-
-SERVER_STATISTICS_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "type": "object",
- "required": ["memory_total",
- "memory_free",
- "memory_used",
- "swap_total",
- "swap_free",
- "swap_used",
- "cpu_usage_percent",
- "memory_usage_percent",
- "swap_usage_percent",
- "disk_usage_percent",
- "load_average_percent"],
- "additionalProperties": False,
- "properties": {
- "memory_total": {
- "description": "Total physical memory (exclusive swap) in bytes",
- "type": "integer",
- },
- "memory_free": {
- "description": "Free memory in bytes",
- "type": "integer",
- },
- "memory_used": {
- "description": "Memory used in bytes",
- "type": "integer",
- },
- "swap_total": {
- "description": "Total swap memory in bytes",
- "type": "integer",
- },
- "swap_free": {
- "description": "Free swap memory in bytes",
- "type": "integer",
- },
- "swap_used": {
- "description": "Swap memory used in bytes",
- "type": "integer",
- },
- "cpu_usage_percent": {
- "description": "CPU usage in percent",
- "type": "integer",
- },
- "memory_usage_percent": {
- "description": "Memory usage in percent",
- "type": "integer",
- },
- "swap_usage_percent": {
- "description": "Swap usage in percent",
- "type": "integer",
- },
- "disk_usage_percent": {
- "description": "Disk usage in percent",
- "type": "integer",
- },
- "load_average_percent": {
- "description": "Average system load over the last 1, 5 and 15 minutes",
- "type": "array",
- "items": [{"type": "integer"}],
- "minItems": 3,
- "maxItems": 3
- },
- }
-}
diff --git a/gns3server/schemas/snapshot.py b/gns3server/schemas/snapshot.py
deleted file mode 100644
index 1c306cd2..00000000
--- a/gns3server/schemas/snapshot.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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 .
-
-
-SNAPSHOT_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new snapshot",
- "type": "object",
- "properties": {
- "name": {
- "description": "Snapshot name",
- "minLength": 1
- },
- },
- "additionalProperties": False,
- "required": ["name"]
-}
-
-SNAPSHOT_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update a Project instance",
- "type": "object",
- "properties": {
- "snapshot_id": {
- "description": "Snapshot UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "project_id": {
- "description": "Project UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "name": {
- "description": "Project name",
- "type": "string",
- "minLength": 1
- },
- "created_at": {
- "description": "Date of the snapshot (UTC timestamp)",
- "type": "integer"
- }
- },
- "additionalProperties": False,
- "required": ["snapshot_id", "name", "created_at", "project_id"]
-}
diff --git a/gns3server/endpoints/schemas/snapshots.py b/gns3server/schemas/snapshots.py
similarity index 100%
rename from gns3server/endpoints/schemas/snapshots.py
rename to gns3server/schemas/snapshots.py
diff --git a/gns3server/schemas/template.py b/gns3server/schemas/template.py
deleted file mode 100644
index 17d3c3d9..00000000
--- a/gns3server/schemas/template.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# 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 .
-
-import copy
-
-BASE_TEMPLATE_PROPERTIES = {
- "template_id": {
- "description": "Template UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "template_type": {
- "description": "Type of node",
- "enum": ["cloud", "ethernet_hub", "ethernet_switch", "docker", "dynamips", "vpcs", "traceng",
- "virtualbox", "vmware", "iou", "qemu"]
- },
- "name": {
- "description": "Template name",
- "type": "string",
- "minLength": 1,
- },
- "usage": {
- "description": "How to use this template",
- "type": "string",
- "default": ""
- },
- "compute_id": {
- "description": "Compute identifier",
- "type": ["null", "string"]
- },
- "default_name_format": {
- "description": "Default name format",
- "type": "string",
- "minLength": 1
- },
- "symbol": {
- "description": "Symbol of the template",
- "type": "string",
- "minLength": 1
- },
- "category": {
- "description": "Template category",
- "anyOf": [
- {"type": "integer"}, # old category support
- {"enum": ["router", "switch", "guest", "firewall"]}
- ]
- },
- "builtin": {
- "description": "Template is builtin",
- "type": "boolean"
- },
-}
-
-TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A template object",
- "type": "object",
- "properties": BASE_TEMPLATE_PROPERTIES,
- "required": ["name", "template_type", "template_id", "category", "compute_id", "default_name_format", "symbol", "builtin"]
-}
-
-TEMPLATE_CREATE_SCHEMA = copy.deepcopy(TEMPLATE_OBJECT_SCHEMA)
-
-# create schema
-# these properties are not required to create a template
-TEMPLATE_CREATE_SCHEMA["required"].remove("template_id")
-TEMPLATE_CREATE_SCHEMA["required"].remove("category")
-TEMPLATE_CREATE_SCHEMA["required"].remove("default_name_format")
-TEMPLATE_CREATE_SCHEMA["required"].remove("symbol")
-TEMPLATE_CREATE_SCHEMA["required"].remove("builtin")
-
-# update schema
-TEMPLATE_UPDATE_SCHEMA = copy.deepcopy(TEMPLATE_OBJECT_SCHEMA)
-del TEMPLATE_UPDATE_SCHEMA["required"]
-
-TEMPLATE_USAGE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to use a Template instance",
- "type": "object",
- "properties": {
- "x": {
- "description": "X position",
- "type": "integer"
- },
- "y": {
- "description": "Y position",
- "type": "integer"
- },
- "name": {
- "description": "Use this name to create a new node",
- "type": ["null", "string"]
- },
- "compute_id": {
- "description": "If the template don't have a default compute use this compute",
- "type": ["null", "string"]
- }
- },
- "additionalProperties": False,
- "required": ["x", "y"]
-}
diff --git a/gns3server/endpoints/schemas/templates.py b/gns3server/schemas/templates.py
similarity index 98%
rename from gns3server/endpoints/schemas/templates.py
rename to gns3server/schemas/templates.py
index 04e23697..af3dcec4 100644
--- a/gns3server/endpoints/schemas/templates.py
+++ b/gns3server/schemas/templates.py
@@ -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"
diff --git a/gns3server/schemas/topology.py b/gns3server/schemas/topology.py
index 21d5e6da..9cf882dc 100644
--- a/gns3server/schemas/topology.py
+++ b/gns3server/schemas/topology.py
@@ -19,136 +19,66 @@
# This file contains the validation for checking a .gns3 file
#
-from gns3server.schemas.compute import COMPUTE_OBJECT_SCHEMA
-from gns3server.schemas.drawing import DRAWING_OBJECT_SCHEMA
-from gns3server.schemas.link import LINK_OBJECT_SCHEMA
-from gns3server.schemas.node import NODE_OBJECT_SCHEMA
-from gns3server.schemas.project import VARIABLES_OBJECT_SCHEMA
-from gns3server.schemas.project import SUPPLIER_OBJECT_SCHEMA
+from .computes import Compute
+from .drawings import Drawing
+from .links import Link
+from .nodes import Node
+
+from .projects import (
+ Supplier,
+ Variable
+)
+
+from pydantic import BaseModel, Field
+from typing import Optional, List
+from enum import Enum
+from uuid import UUID
-TOPOLOGY_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "The topology",
- "type": "object",
- "properties": {
- "project_id": {
- "description": "Project UUID",
- "type": "string",
- "minLength": 36,
- "maxLength": 36,
- "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
- },
- "type": {
- "description": "Type of file. It's always topology",
- "enum": ["topology"]
- },
- "auto_start": {
- "description": "Start the topology when opened",
- "type": "boolean"
- },
- "auto_close": {
- "description": "Close the topology when no client is connected",
- "type": "boolean"
- },
- "auto_open": {
- "description": "Open the topology with GNS3",
- "type": "boolean"
- },
- "revision": {
- "description": "Version of the .gns3 specification.",
- "type": "integer"
- },
- "version": {
- "description": "Version of the GNS3 software which have update the file for the last time",
- "type": "string"
- },
- "name": {
- "type": "string",
- "description": "Name of the project"
- },
- "scene_height": {
- "type": "integer",
- "description": "Height of the drawing area"
- },
- "scene_width": {
- "type": "integer",
- "description": "Width of the drawing area"
- },
- "zoom": {
- "type": "integer",
- "description": "Zoom of the drawing area"
- },
- "show_layers": {
- "type": "boolean",
- "description": "Show layers on the drawing area"
- },
- "snap_to_grid": {
- "type": "boolean",
- "description": "Snap to grid on the drawing area"
- },
- "show_grid": {
- "type": "boolean",
- "description": "Show the grid on the drawing area"
- },
- "grid_size": {
- "type": "integer",
- "description": "Grid size for the drawing area for nodes"
- },
- "drawing_grid_size": {
- "type": "integer",
- "description": "Grid size for the drawing area for drawings"
- },
- "show_interface_labels": {
- "type": "boolean",
- "description": "Show interface labels on the drawing area"
- },
- "supplier": SUPPLIER_OBJECT_SCHEMA,
- "variables": VARIABLES_OBJECT_SCHEMA,
- "topology": {
- "description": "The topology content",
- "type": "object",
- "properties": {
- "computes": {
- "description": "Computes servers",
- "type": "array",
- "items": COMPUTE_OBJECT_SCHEMA
- },
- "drawings": {
- "description": "Drawings elements",
- "type": "array",
- "items": DRAWING_OBJECT_SCHEMA
- },
- "links": {
- "description": "Link elements",
- "type": "array",
- "items": LINK_OBJECT_SCHEMA
- },
- "nodes": {
- "description": "Nodes elements",
- "type": "array",
- "items": NODE_OBJECT_SCHEMA
- }
- },
- "required": ["nodes", "links", "drawings", "computes"],
- "additionalProperties": False
- }
- },
- "required": [
- "project_id", "type", "revision", "version", "name", "topology"
- ],
- "additionalProperties": False
-}
+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 jsonschema
+
import json
import sys
with open(sys.argv[1]) as f:
data = json.load(f)
- jsonschema.validate(data, TOPOLOGY_SCHEMA)
+ Topology.parse_obj(data)
if __name__ == '__main__':
diff --git a/gns3server/schemas/traceng_template.py b/gns3server/schemas/traceng_template.py
deleted file mode 100644
index 5c574685..00000000
--- a/gns3server/schemas/traceng_template.py
+++ /dev/null
@@ -1,51 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-
-
-TRACENG_TEMPLATE_PROPERTIES = {
- "ip_address": {
- "description": "Source IP address for tracing",
- "type": ["string"],
- "minLength": 1
- },
- "default_destination": {
- "description": "Default destination IP address or hostname for tracing",
- "type": ["string"],
- "minLength": 1
- },
- "console_type": {
- "description": "Console type",
- "enum": ["none"],
- "default": "none"
- },
-}
-
-TRACENG_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-TRACENG_TEMPLATE_PROPERTIES["category"]["default"] = "guest"
-TRACENG_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "TraceNG{0}"
-TRACENG_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/traceng.svg"
-
-TRACENG_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A TraceNG template object",
- "type": "object",
- "properties": TRACENG_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
diff --git a/gns3server/schemas/version.py b/gns3server/schemas/version.py
index ac739dd5..cb92d953 100644
--- a/gns3server/schemas/version.py
+++ b/gns3server/schemas/version.py
@@ -15,19 +15,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-VERSION_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "type": "object",
- 'required': ['version'],
- "additionalProperties": False,
- "properties": {
- "version": {
- "description": "Version number",
- "type": "string",
- },
- "local": {
- "description": "Whether this is a local server or not",
- "type": "boolean",
- }
- }
-}
+from pydantic import BaseModel, Field
+from typing import Optional
+
+
+class Version(BaseModel):
+
+ version: str = Field(..., description="Version number")
+ local: Optional[bool] = Field(None, description="Whether this is a local server or not")
diff --git a/gns3server/endpoints/schemas/virtualbox_nodes.py b/gns3server/schemas/virtualbox_nodes.py
similarity index 84%
rename from gns3server/endpoints/schemas/virtualbox_nodes.py
rename to gns3server/schemas/virtualbox_nodes.py
index 804f3825..56f26565 100644
--- a/gns3server/endpoints/schemas/virtualbox_nodes.py
+++ b/gns3server/schemas/virtualbox_nodes.py
@@ -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):
diff --git a/gns3server/schemas/virtualbox_template.py b/gns3server/schemas/virtualbox_template.py
deleted file mode 100644
index 36ff47c2..00000000
--- a/gns3server/schemas/virtualbox_template.py
+++ /dev/null
@@ -1,113 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA
-
-
-VIRTUALBOX_TEMPLATE_PROPERTIES = {
- "vmname": {
- "description": "VirtualBox VM name (in VirtualBox itself)",
- "type": "string",
- "minLength": 1,
- },
- "ram": {
- "description": "Amount of RAM",
- "minimum": 0,
- "maximum": 65535,
- "type": "integer",
- "default": 256
- },
- "linked_clone": {
- "description": "Whether the VM is a linked clone or not",
- "type": "boolean",
- "default": False
- },
- "adapters": {
- "description": "Number of adapters",
- "type": "integer",
- "minimum": 0,
- "maximum": 36, # maximum given by the ICH9 chipset in VirtualBox
- "default": 1
- },
- "use_any_adapter": {
- "description": "Allow GNS3 to use any VirtualBox adapter",
- "type": "boolean",
- "default": False
- },
- "adapter_type": {
- "description": "VirtualBox adapter type",
- "enum": ["PCnet-PCI II (Am79C970A)",
- "PCNet-FAST III (Am79C973)",
- "Intel PRO/1000 MT Desktop (82540EM)",
- "Intel PRO/1000 T Server (82543GC)",
- "Intel PRO/1000 MT Server (82545EM)",
- "Paravirtualized Network (virtio-net)"],
- "default": "Intel PRO/1000 MT Desktop (82540EM)"
- },
- "first_port_name": {
- "description": "Optional name of the first networking port example: eth0",
- "type": "string",
- "default": ""
- },
- "port_name_format": {
- "description": "Optional formatting of the networking port example: eth{0}",
- "type": "string",
- "default": "Ethernet{0}"
- },
- "port_segment_size": {
- "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",
- "type": "integer",
- "default": 0
- },
- "headless": {
- "description": "Headless mode",
- "type": "boolean",
- "default": False
- },
- "on_close": {
- "description": "Action to execute on the VM is closed",
- "enum": ["power_off", "shutdown_signal", "save_vm_state"],
- "default": "power_off"
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"],
- "default": "none"
- },
- "console_auto_start": {
- "description": "Automatically start the console when the node has started",
- "type": "boolean",
- "default": False
- },
- "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA
-}
-
-VIRTUALBOX_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-VIRTUALBOX_TEMPLATE_PROPERTIES["category"]["default"] = "guest"
-VIRTUALBOX_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}"
-VIRTUALBOX_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/vbox_guest.svg"
-
-VIRTUALBOX_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A VirtualBox template object",
- "type": "object",
- "properties": VIRTUALBOX_TEMPLATE_PROPERTIES,
- "required": ["vmname"],
- "additionalProperties": False
-}
diff --git a/gns3server/schemas/virtualbox_templates.py b/gns3server/schemas/virtualbox_templates.py
new file mode 100644
index 00000000..1f0af97e
--- /dev/null
+++ b/gns3server/schemas/virtualbox_templates.py
@@ -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 .
+
+from .templates import Category, TemplateBase
+from .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")
diff --git a/gns3server/endpoints/schemas/vmware_nodes.py b/gns3server/schemas/vmware_nodes.py
similarity index 88%
rename from gns3server/endpoints/schemas/vmware_nodes.py
rename to gns3server/schemas/vmware_nodes.py
index ca5aef75..fadb6701 100644
--- a/gns3server/endpoints/schemas/vmware_nodes.py
+++ b/gns3server/schemas/vmware_nodes.py
@@ -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")
diff --git a/gns3server/schemas/vmware_template.py b/gns3server/schemas/vmware_template.py
deleted file mode 100644
index c4c6ac88..00000000
--- a/gns3server/schemas/vmware_template.py
+++ /dev/null
@@ -1,101 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA
-
-
-VMWARE_TEMPLATE_PROPERTIES = {
- "vmx_path": {
- "description": "Path to the vmx file",
- "type": "string",
- "minLength": 1,
- },
- "linked_clone": {
- "description": "Whether the VM is a linked clone or not",
- "type": "boolean",
- "default": False
- },
- "first_port_name": {
- "description": "Optional name of the first networking port example: eth0",
- "type": "string",
- "default": ""
- },
- "port_name_format": {
- "description": "Optional formatting of the networking port example: eth{0}",
- "type": "string",
- "default": "Ethernet{0}"
- },
- "port_segment_size": {
- "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",
- "type": "integer",
- "default": 0
- },
- "adapters": {
- "description": "Number of adapters",
- "type": "integer",
- "minimum": 0,
- "maximum": 10, # maximum adapters support by VMware VMs,
- "default": 1
- },
- "adapter_type": {
- "description": "VMware adapter type",
- "enum": ["default", "e1000", "e1000e", "flexible", "vlance", "vmxnet", "vmxnet2", "vmxnet3"],
- "default": "e1000"
- },
- "use_any_adapter": {
- "description": "Allow GNS3 to use any VMware adapter",
- "type": "boolean",
- "default": False
- },
- "headless": {
- "description": "Headless mode",
- "type": "boolean",
- "default": False
- },
- "on_close": {
- "description": "Action to execute on the VM is closed",
- "enum": ["power_off", "shutdown_signal", "save_vm_state"],
- "default": "power_off"
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"],
- "default": "none"
- },
- "console_auto_start": {
- "description": "Automatically start the console when the node has started",
- "type": "boolean",
- "default": False
- },
- "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA
-}
-
-VMWARE_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-VMWARE_TEMPLATE_PROPERTIES["category"]["default"] = "guest"
-VMWARE_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}"
-VMWARE_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/vmware_guest.svg"
-
-VMWARE_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A VMware template object",
- "type": "object",
- "properties": VMWARE_TEMPLATE_PROPERTIES,
- "required": ["vmx_path"],
- "additionalProperties": False
-}
diff --git a/gns3server/schemas/vmware_templates.py b/gns3server/schemas/vmware_templates.py
new file mode 100644
index 00000000..6b85000f
--- /dev/null
+++ b/gns3server/schemas/vmware_templates.py
@@ -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 .
+
+
+from .templates import Category, TemplateBase
+from .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")
diff --git a/gns3server/endpoints/schemas/vpcs_nodes.py b/gns3server/schemas/vpcs_nodes.py
similarity index 94%
rename from gns3server/endpoints/schemas/vpcs_nodes.py
rename to gns3server/schemas/vpcs_nodes.py
index 4698413e..a09d40b3 100644
--- a/gns3server/endpoints/schemas/vpcs_nodes.py
+++ b/gns3server/schemas/vpcs_nodes.py
@@ -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")
diff --git a/gns3server/schemas/vpcs_template.py b/gns3server/schemas/vpcs_template.py
deleted file mode 100644
index e0726b24..00000000
--- a/gns3server/schemas/vpcs_template.py
+++ /dev/null
@@ -1,52 +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 .
-
-import copy
-from .template import BASE_TEMPLATE_PROPERTIES
-
-
-VPCS_TEMPLATE_PROPERTIES = {
- "base_script_file": {
- "description": "Script file",
- "type": "string",
- "minLength": 1,
- "default": "vpcs_base_config.txt"
- },
- "console_type": {
- "description": "Console type",
- "enum": ["telnet", "none"],
- "default": "telnet"
- },
- "console_auto_start": {
- "description": "Automatically start the console when the node has started",
- "type": "boolean",
- "default": False
- },
-}
-
-VPCS_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
-VPCS_TEMPLATE_PROPERTIES["category"]["default"] = "guest"
-VPCS_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "PC{0}"
-VPCS_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/vpcs_guest.svg"
-
-VPCS_TEMPLATE_OBJECT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "A VPCS template object",
- "type": "object",
- "properties": VPCS_TEMPLATE_PROPERTIES,
- "additionalProperties": False
-}
diff --git a/gns3server/endpoints/schemas/vpcs_templates.py b/gns3server/schemas/vpcs_templates.py
similarity index 66%
rename from gns3server/endpoints/schemas/vpcs_templates.py
rename to gns3server/schemas/vpcs_templates.py
index 6ee5f6a4..ba16f12d 100644
--- a/gns3server/endpoints/schemas/vpcs_templates.py
+++ b/gns3server/schemas/vpcs_templates.py
@@ -17,52 +17,17 @@
from .templates import Category, TemplateBase
+from .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]
diff --git a/gns3server/templates/compute.html b/gns3server/templates/compute.html
index dd563d26..2ef05621 100644
--- a/gns3server/templates/compute.html
+++ b/gns3server/templates/compute.html
@@ -2,7 +2,7 @@
{% block head %}