Merge remote-tracking branch 'origin/3.0' into gh-pages

This commit is contained in:
github-actions 2020-11-02 02:56:08 +00:00
commit 0697b467a2
123 changed files with 996 additions and 5516 deletions

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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"""

View File

@ -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()

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)):
"""

View File

@ -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()

View File

@ -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)):

View File

@ -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

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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()

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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)):
"""

View File

@ -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.

View File

@ -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.

View File

@ -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.
"""

View File

@ -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.
"""

View File

@ -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.
"""

View File

@ -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):

View File

@ -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)):
"""

View File

@ -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"}
}

View File

@ -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.

View File

@ -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.

View File

@ -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 <http://www.gnu.org/licenses/>.
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

View File

@ -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 <http://www.gnu.org/licenses/>.
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")

View File

@ -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 <http://www.gnu.org/licenses/>.
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")

View File

@ -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 <http://www.gnu.org/licenses/>.
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
)

View File

@ -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 <http://www.gnu.org/licenses/>.
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")

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -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")

View File

@ -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 <http://www.gnu.org/licenses/>.
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,
}

View File

@ -103,12 +103,12 @@ class Compute(ComputeBase):
compute_id: Union[str, UUID]
name: str
connected: bool = Field(..., description="Whether the controller is connected to the compute or not")
cpu_usage_percent: float = Field(..., description="CPU usage of the compute", ge=0, le=100)
memory_usage_percent: float = Field(..., description="Memory usage of the compute", ge=0, le=100)
disk_usage_percent: float = Field(..., description="Disk usage of the compute", ge=0, le=100)
connected: Optional[bool] = Field(None, description="Whether the controller is connected to the compute or not")
cpu_usage_percent: Optional[float] = Field(None, description="CPU usage of the compute", ge=0, le=100)
memory_usage_percent: Optional[float] = Field(None, description="Memory usage of the compute", ge=0, le=100)
disk_usage_percent: Optional[float] = Field(None, description="Disk usage of the compute", ge=0, le=100)
last_error: Optional[str] = Field(None, description="Last error found on the compute")
capabilities: Capabilities
capabilities: Optional[Capabilities] = None
class AutoIdlePC(BaseModel):

View File

@ -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 <http://www.gnu.org/licenses/>.
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"]
},
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .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")

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -25,6 +25,20 @@ from uuid import UUID
from .nodes import NodeStatus
class DynamipsPlatform(str, Enum):
"""
Supported Dynamips Platforms.
"""
c7200 = "c7200"
c3725 = "c3725"
c3745 = "c3745"
c3600 = "c3600"
c2691 = "c2691"
c2600 = "c2600"
c1700 = "c1700"
class DynamipsAdapters(str, Enum):
"""
Supported Dynamips Network Modules.
@ -56,6 +70,7 @@ class DynamipsAdapters(str, Enum):
gt96100_fe = "GT96100-FE"
leopard_2fe = "Leopard-2FE"
class DynamipsWics(str, Enum):
"""
Supported Dynamips WICs.
@ -108,7 +123,7 @@ class DynamipsBase(BaseModel):
node_id: Optional[UUID] = None
name: Optional[str] = None
dynamips_id: Optional[int] = Field(None, description="Dynamips internal ID")
platform: Optional[str] = Field(None, description="Cisco router platform", regex="^c[0-9]{4}$")
platform: Optional[DynamipsPlatform] = Field(None, description="Cisco router platform")
ram: Optional[int] = Field(None, description="Amount of RAM in MB")
nvram: Optional[int] = Field(None, description="Amount of NVRAM in KB")
image: Optional[Path] = Field(None, description="Path to the IOS image")
@ -133,16 +148,16 @@ class DynamipsBase(BaseModel):
aux_type: Optional[DynamipsConsoleType] = Field(None, description="Auxiliary console type")
mac_addr: Optional[str] = Field(None, description="Base MAC address", regex="^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$")
system_id: Optional[str] = Field(None, description="System ID")
slot0: Optional[str] = Field(None, description="Network module slot 0")
slot1: Optional[str] = Field(None, description="Network module slot 1")
slot2: Optional[str] = Field(None, description="Network module slot 2")
slot3: Optional[str] = Field(None, description="Network module slot 3")
slot4: Optional[str] = Field(None, description="Network module slot 4")
slot5: Optional[str] = Field(None, description="Network module slot 5")
slot6: Optional[str] = Field(None, description="Network module slot 6")
wic0: Optional[str] = Field(None, description="Network module WIC slot 0")
wic1: Optional[str] = Field(None, description="Network module WIC slot 1")
wic2: Optional[str] = Field(None, description="Network module WIC slot 2")
slot0: Optional[DynamipsAdapters] = Field(None, description="Network module slot 0")
slot1: Optional[DynamipsAdapters] = Field(None, description="Network module slot 1")
slot2: Optional[DynamipsAdapters] = Field(None, description="Network module slot 2")
slot3: Optional[DynamipsAdapters] = Field(None, description="Network module slot 3")
slot4: Optional[DynamipsAdapters] = Field(None, description="Network module slot 4")
slot5: Optional[DynamipsAdapters] = Field(None, description="Network module slot 5")
slot6: Optional[DynamipsAdapters] = Field(None, description="Network module slot 6")
wic0: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 0")
wic1: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 1")
wic2: Optional[DynamipsWics] = Field(None, description="Network module WIC slot 2")
npe: Optional[DynamipsNPE] = Field(None, description="NPE model")
midplane: Optional[DynamipsMidplane] = Field(None, description="Midplane model")
sensors: Optional[List] = Field(None, description="Temperature sensors")

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -0,0 +1,154 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .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")

View File

@ -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 <http://www.gnu.org/licenses/>.
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"]
}

View File

@ -1,80 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import copy
from .template import BASE_TEMPLATE_PROPERTIES
ETHERNET_HUB_TEMPLATE_PROPERTIES = {
"ports_mapping": {
"type": "array",
"default": [{"port_number": 0,
"name": "Ethernet0"
},
{"port_number": 1,
"name": "Ethernet1"
},
{"port_number": 2,
"name": "Ethernet2"
},
{"port_number": 3,
"name": "Ethernet3"
},
{"port_number": 4,
"name": "Ethernet4"
},
{"port_number": 5,
"name": "Ethernet5"
},
{"port_number": 6,
"name": "Ethernet6"
},
{"port_number": 7,
"name": "Ethernet7"
}
],
"items": [
{"type": "object",
"oneOf": [{"description": "Ethernet port",
"properties": {"name": {"description": "Port name",
"type": "string",
"minLength": 1},
"port_number": {
"description": "Port number",
"type": "integer",
"minimum": 0}
},
"required": ["name", "port_number"],
"additionalProperties": False}
],
}
]
}
}
ETHERNET_HUB_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES))
ETHERNET_HUB_TEMPLATE_PROPERTIES["category"]["default"] = "switch"
ETHERNET_HUB_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "Hub{0}"
ETHERNET_HUB_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/hub.svg"
ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "An Ethernet hub template object",
"type": "object",
"properties": ETHERNET_HUB_TEMPLATE_PROPERTIES,
"additionalProperties": False
}

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .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")

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .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")

View File

@ -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 <http://www.gnu.org/licenses/>.
FILTER_OBJECT_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Packet filter. This allow to simulate latency and errors",
"type": "object"
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -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]

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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"]
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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"]
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}
]
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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,
}

View File

@ -35,7 +35,7 @@ class ProjectStatus(str, Enum):
class Supplier(BaseModel):
logo: str = Field(..., description="Path to the project supplier logo")
url: HttpUrl = Field(..., description="URL to the project supplier site")
url: Optional[HttpUrl] = Field(None, description="URL to the project supplier site")
class Variable(BaseModel):

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -104,6 +104,54 @@ class QemuProcessPriority(str, Enum):
very_low = "very low"
class QemuAdapterType(str, Enum):
"""
Supported Qemu VM adapter types.
"""
e1000 = "e1000"
e1000_82544gc = "e1000-82544gc"
e1000_82545em = "e1000-82545em"
e1000e = "e1000e"
i82550 = "i82550"
i82551 = "i82551"
i82557a = "i82557a"
i82557b = "i82557b"
i82557c = "i82557c"
i82558a = "i82558a"
i82558b = "i82558b"
i82559a = "i82559a"
i82559b = "i82559b"
i82559c = "i82559c"
i82559er = "i82559er"
i82562 = "i82562"
i82801 = "i82801"
ne2k_pci = "ne2k_pci"
pcnet = "pcnet"
rocker = "rocker"
rtl8139 = "rtl8139"
virtio = "virtio"
virtio_net_pci = "virtio-net-pci"
vmxnet3 = "vmxnet3"
class QemuDiskInterfaceType(str, Enum):
"""
Supported Qemu VM disk interface types.
"""
ide = "ide"
sate = "sata"
nvme = "nvme"
scsi = "scsi"
sd = "sd"
mtd = "mtd"
floppy = "floppy"
pflash = "pflash"
virtio = "virtio"
none = "none"
class QemuBase(BaseModel):
"""
Common Qemu node properties.
@ -121,16 +169,16 @@ class QemuBase(BaseModel):
aux_type: Optional[QemuConsoleType] = Field(None, description="Auxiliary console type")
hda_disk_image: Optional[Path] = Field(None, description="QEMU hda disk image path")
hda_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hda disk image checksum")
hda_disk_image_interface: Optional[str] = Field(None, description="QEMU hda interface")
hda_disk_interface: Optional[QemuDiskInterfaceType] = Field(None, description="QEMU hda interface")
hdb_disk_image: Optional[Path] = Field(None, description="QEMU hdb disk image path")
hdb_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdb disk image checksum")
hdb_disk_image_interface: Optional[str] = Field(None, description="QEMU hdb interface")
hdb_disk_interface: Optional[QemuDiskInterfaceType] = Field(None, description="QEMU hdb interface")
hdc_disk_image: Optional[Path] = Field(None, description="QEMU hdc disk image path")
hdc_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdc disk image checksum")
hdc_disk_image_interface: Optional[str] = Field(None, description="QEMU hdc interface")
hdc_disk_interface: Optional[QemuDiskInterfaceType] = Field(None, description="QEMU hdc interface")
hdd_disk_image: Optional[Path] = Field(None, description="QEMU hdd disk image path")
hdd_disk_image_md5sum: Optional[str] = Field(None, description="QEMU hdd disk image checksum")
hdd_disk_image_interface: Optional[str] = Field(None, description="QEMU hdd interface")
hdd_disk_interface: Optional[QemuDiskInterfaceType] = Field(None, description="QEMU hdd interface")
cdrom_image: Optional[Path] = Field(None, description="QEMU cdrom image path")
cdrom_image_md5sum: Optional[str] = Field(None, description="QEMU cdrom image checksum")
bios_image: Optional[Path] = Field(None, description="QEMU bios image path")
@ -140,12 +188,12 @@ class QemuBase(BaseModel):
kernel_image: Optional[Path] = Field(None, description="QEMU kernel image path")
kernel_image_md5sum: Optional[str] = Field(None, description="QEMU kernel image checksum")
kernel_command_line: Optional[str] = Field(None, description="QEMU kernel command line")
boot_priotiry: Optional[QemuBootPriority] = Field(None, description="QEMU boot priority")
boot_priority: Optional[QemuBootPriority] = Field(None, description="QEMU boot priority")
ram: Optional[int] = Field(None, description="Amount of RAM in MB")
cpus: Optional[int] = Field(None, ge=1, le=255, description="Number of vCPUs")
maxcpus: Optional[int] = Field(None, ge=1, le=255, description="Maximum number of hotpluggable vCPUs")
adapters: Optional[int] = Field(None, ge=0, le=275, description="Number of adapters")
adapter_type: Optional[str] = Field(None, description="QEMU adapter type")
adapter_type: Optional[QemuAdapterType] = Field(None, description="QEMU adapter type")
mac_address: Optional[str] = Field(None, description="QEMU MAC address", regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$")
legacy_networking: Optional[bool] = Field(None, description="Use QEMU legagy networking commands (-net syntax)")
replicate_network_connection_state: Optional[bool] = Field(None, description="Replicate the network connection state for links in Qemu")

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .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")

View File

@ -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 <http://www.gnu.org/licenses/>.
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
},
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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"]
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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"]
}

View File

@ -45,8 +45,8 @@ class TemplateBase(BaseModel):
symbol: Optional[str] = None
builtin: Optional[bool] = None
template_type: Optional[NodeType] = None
usage: Optional[str] = None
compute_id: Optional[str] = None
usage: Optional[str] = ""
class Config:
extra = "allow"

View File

@ -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__':

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -15,19 +15,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
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")

View File

@ -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):

View File

@ -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 <http://www.gnu.org/licenses/>.
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
}

View File

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .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")

View File

@ -43,6 +43,21 @@ class VMwareOnCloseAction(str, Enum):
save_vm_state = "save_vm_state"
class VMwareAdapterType(str, Enum):
"""
Supported VMware VM adapter types.
"""
default = "default"
e1000 = "e1000"
e1000e = "e1000e"
flexible = "flexible"
vlance = "vlance"
vmxnet = "vmxnet"
vmxnet2 = "vmxnet2"
vmxnet3 = "vmxnet3"
class VMwareBase(BaseModel):
"""
Common VMware node properties.
@ -59,7 +74,7 @@ class VMwareBase(BaseModel):
on_close: Optional[VMwareOnCloseAction] = Field(None, description="Action to execute on the VM is closed")
# 10 adapters is the maximum supported by VMware VMs.
adapters: Optional[int] = Field(None, ge=0, le=10, description="Number of adapters")
adapter_type: Optional[str] = Field(None, description="VMware adapter type")
adapter_type: Optional[VMwareAdapterType] = Field(None, description="VMware adapter type")
use_any_adapter: Optional[bool] = Field(None, description="Allow GNS3 to use any VMware adapter")
custom_adapters: Optional[List[CustomAdapter]] = Field(None, description="Custom adpaters")

Some files were not shown because too many files have changed in this diff Show More