mirror of
https://github.com/GNS3/gns3-server.git
synced 2025-01-20 16:33:48 +02:00
Some cleaning.
This commit is contained in:
parent
bad3ef7003
commit
44074ff7c9
@ -71,7 +71,7 @@ async def get_links(project_id: UUID):
|
|||||||
409: {"model": schemas.ErrorMessage, "description": "Could not create link"},
|
409: {"model": schemas.ErrorMessage, "description": "Could not create link"},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
async def create_link(project_id: UUID, link_data: schemas.Link):
|
async def create_link(project_id: UUID, link_data: schemas.LinkCreate):
|
||||||
"""
|
"""
|
||||||
Create a new link.
|
Create a new link.
|
||||||
"""
|
"""
|
||||||
@ -116,7 +116,7 @@ async def get_link(link: Link = Depends(dep_link)):
|
|||||||
|
|
||||||
|
|
||||||
@router.put("/{link_id}", response_model=schemas.Link, response_model_exclude_unset=True)
|
@router.put("/{link_id}", response_model=schemas.Link, response_model_exclude_unset=True)
|
||||||
async def update_link(link_data: schemas.Link, link: Link = Depends(dep_link)):
|
async def update_link(link_data: schemas.LinkUpdate, link: Link = Depends(dep_link)):
|
||||||
"""
|
"""
|
||||||
Update a link.
|
Update a link.
|
||||||
"""
|
"""
|
||||||
|
@ -40,7 +40,12 @@ class EthernetHub(BaseNode):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"name": self.name, "usage": self.usage, "node_id": self.id, "project_id": self.project.id}
|
return {
|
||||||
|
"name": self.name,
|
||||||
|
"usage": self.usage,
|
||||||
|
"node_id": self.id,
|
||||||
|
"project_id": self.project.id
|
||||||
|
}
|
||||||
|
|
||||||
async def create(self):
|
async def create(self):
|
||||||
"""
|
"""
|
||||||
|
@ -40,7 +40,12 @@ class EthernetSwitch(BaseNode):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"name": self.name, "usage": self.usage, "node_id": self.id, "project_id": self.project.id}
|
return {
|
||||||
|
"name": self.name,
|
||||||
|
"usage": self.usage,
|
||||||
|
"node_id": self.id,
|
||||||
|
"project_id": self.project.id
|
||||||
|
}
|
||||||
|
|
||||||
async def create(self):
|
async def create(self):
|
||||||
"""
|
"""
|
||||||
|
@ -67,4 +67,7 @@ class NIOGenericEthernet(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_generic_ethernet", "ethernet_device": self._ethernet_device}
|
return {
|
||||||
|
"type": "nio_generic_ethernet",
|
||||||
|
"ethernet_device": self._ethernet_device
|
||||||
|
}
|
||||||
|
@ -66,4 +66,7 @@ class NIOLinuxEthernet(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_linux_ethernet", "ethernet_device": self._ethernet_device}
|
return {
|
||||||
|
"type": "nio_linux_ethernet",
|
||||||
|
"ethernet_device": self._ethernet_device
|
||||||
|
}
|
||||||
|
@ -60,4 +60,7 @@ class NIOTAP(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_tap", "tap_device": self._tap_device}
|
return {
|
||||||
|
"type": "nio_tap",
|
||||||
|
"tap_device": self._tap_device
|
||||||
|
}
|
||||||
|
@ -128,4 +128,9 @@ class NIOUDP(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_udp", "lport": self._lport, "rport": self._rport, "rhost": self._rhost}
|
return {
|
||||||
|
"type": "nio_udp",
|
||||||
|
"lport": self._lport,
|
||||||
|
"rport": self._rport,
|
||||||
|
"rhost": self._rhost
|
||||||
|
}
|
||||||
|
@ -81,4 +81,8 @@ class NIOUNIX(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_unix", "local_file": self._local_file, "remote_file": self._remote_file}
|
return {
|
||||||
|
"type": "nio_unix",
|
||||||
|
"local_file": self._local_file,
|
||||||
|
"remote_file": self._remote_file
|
||||||
|
}
|
||||||
|
@ -81,4 +81,8 @@ class NIOVDE(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_vde", "local_file": self._local_file, "control_file": self._control_file}
|
return {
|
||||||
|
"type": "nio_vde",
|
||||||
|
"local_file": self._local_file,
|
||||||
|
"control_file": self._control_file
|
||||||
|
}
|
||||||
|
@ -50,4 +50,7 @@ class NIOEthernet(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_ethernet", "ethernet_device": self._ethernet_device}
|
return {
|
||||||
|
"type": "nio_ethernet",
|
||||||
|
"ethernet_device": self._ethernet_device
|
||||||
|
}
|
||||||
|
@ -50,4 +50,7 @@ class NIOTAP(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_tap", "tap_device": self._tap_device}
|
return {
|
||||||
|
"type": "nio_tap",
|
||||||
|
"tap_device": self._tap_device
|
||||||
|
}
|
||||||
|
@ -74,4 +74,9 @@ class NIOUDP(NIO):
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"type": "nio_udp", "lport": self._lport, "rport": self._rport, "rhost": self._rhost}
|
return {
|
||||||
|
"type": "nio_udp",
|
||||||
|
"lport": self._lport,
|
||||||
|
"rport": self._rport,
|
||||||
|
"rhost": self._rhost
|
||||||
|
}
|
||||||
|
@ -79,7 +79,11 @@ class Project:
|
|||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
|
||||||
return {"name": self._name, "project_id": self._id, "variables": self._variables}
|
return {
|
||||||
|
"name": self._name,
|
||||||
|
"project_id": self._id,
|
||||||
|
"variables": self._variables
|
||||||
|
}
|
||||||
|
|
||||||
def is_local(self):
|
def is_local(self):
|
||||||
|
|
||||||
|
@ -17,14 +17,15 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Appliance:
|
class Appliance:
|
||||||
|
|
||||||
def __init__(self, appliance_id, data, builtin=True):
|
def __init__(self, appliance_id, data, builtin=True):
|
||||||
|
|
||||||
if appliance_id is None:
|
if appliance_id is None:
|
||||||
self._id = str(uuid.uuid4())
|
self._id = str(uuid.uuid4())
|
||||||
elif isinstance(appliance_id, uuid.UUID):
|
elif isinstance(appliance_id, uuid.UUID):
|
||||||
|
@ -390,7 +390,6 @@ class Node:
|
|||||||
data["node_id"] = self._id
|
data["node_id"] = self._id
|
||||||
if self._node_type == "docker":
|
if self._node_type == "docker":
|
||||||
timeout = None
|
timeout = None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
timeout = 1200
|
timeout = 1200
|
||||||
trial = 0
|
trial = 0
|
||||||
@ -543,7 +542,7 @@ class Node:
|
|||||||
if self.custom_adapters:
|
if self.custom_adapters:
|
||||||
data["custom_adapters"] = self.custom_adapters
|
data["custom_adapters"] = self.custom_adapters
|
||||||
|
|
||||||
# None properties are not be send. Because it can mean the emulator doesn't support it
|
# None properties are not be sent because it can mean the emulator doesn't support it
|
||||||
for key in list(data.keys()):
|
for key in list(data.keys()):
|
||||||
if data[key] is None or data[key] is {} or key in self.CONTROLLER_ONLY_PROPERTIES:
|
if data[key] is None or data[key] is {} or key in self.CONTROLLER_ONLY_PROPERTIES:
|
||||||
del data[key]
|
del data[key]
|
||||||
@ -628,7 +627,7 @@ class Node:
|
|||||||
|
|
||||||
async def put(self, path, data=None, **kwargs):
|
async def put(self, path, data=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
HTTP post on the node
|
HTTP put on the node
|
||||||
"""
|
"""
|
||||||
if path is None:
|
if path is None:
|
||||||
path = f"/projects/{self._project.id}/{self._node_type}/nodes/{self._id}"
|
path = f"/projects/{self._project.id}/{self._node_type}/nodes/{self._id}"
|
||||||
@ -780,11 +779,10 @@ class Node:
|
|||||||
|
|
||||||
def __json__(self, topology_dump=False):
|
def __json__(self, topology_dump=False):
|
||||||
"""
|
"""
|
||||||
:param topology_dump: Filter to keep only properties require for saving on disk
|
:param topology_dump: Filter to keep only properties required for saving on disk
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if topology_dump:
|
topology = {
|
||||||
return {
|
|
||||||
"compute_id": str(self._compute.id),
|
"compute_id": str(self._compute.id),
|
||||||
"node_id": self._id,
|
"node_id": self._id,
|
||||||
"node_type": self._node_type,
|
"node_type": self._node_type,
|
||||||
@ -808,35 +806,18 @@ class Node:
|
|||||||
"port_segment_size": self._port_segment_size,
|
"port_segment_size": self._port_segment_size,
|
||||||
"first_port_name": self._first_port_name,
|
"first_port_name": self._first_port_name,
|
||||||
"custom_adapters": self._custom_adapters,
|
"custom_adapters": self._custom_adapters,
|
||||||
}
|
|
||||||
return {
|
|
||||||
"compute_id": str(self._compute.id),
|
|
||||||
"project_id": self._project.id,
|
|
||||||
"node_id": self._id,
|
|
||||||
"template_id": self._template_id,
|
|
||||||
"node_type": self._node_type,
|
|
||||||
"node_directory": self._node_directory,
|
|
||||||
"name": self._name,
|
|
||||||
"console": self._console,
|
|
||||||
"console_host": str(self._compute.console_host),
|
|
||||||
"console_type": self._console_type,
|
|
||||||
"aux": self._aux,
|
|
||||||
"aux_type": self._aux_type,
|
|
||||||
"console_auto_start": self._console_auto_start,
|
|
||||||
"command_line": self._command_line,
|
|
||||||
"properties": self._properties,
|
|
||||||
"status": self._status,
|
|
||||||
"label": self._label,
|
|
||||||
"x": self._x,
|
|
||||||
"y": self._y,
|
|
||||||
"z": self._z,
|
|
||||||
"locked": self._locked,
|
|
||||||
"width": self._width,
|
|
||||||
"height": self._height,
|
|
||||||
"symbol": self._symbol,
|
|
||||||
"port_name_format": self._port_name_format,
|
|
||||||
"port_segment_size": self._port_segment_size,
|
|
||||||
"first_port_name": self._first_port_name,
|
|
||||||
"custom_adapters": self._custom_adapters,
|
|
||||||
"ports": [port.__json__() for port in self.ports],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if topology_dump:
|
||||||
|
return topology
|
||||||
|
|
||||||
|
additional_data = {
|
||||||
|
"project_id": self._project.id,
|
||||||
|
"command_line": self._command_line,
|
||||||
|
"status": self._status,
|
||||||
|
"console_host": str(self._compute.console_host),
|
||||||
|
"node_directory": self._node_directory,
|
||||||
|
"ports": [port.__json__() for port in self.ports]
|
||||||
|
}
|
||||||
|
topology.update(additional_data)
|
||||||
|
return topology
|
||||||
|
@ -28,6 +28,7 @@ class Notification:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, controller):
|
def __init__(self, controller):
|
||||||
|
|
||||||
self._controller = controller
|
self._controller = controller
|
||||||
self._project_listeners = {}
|
self._project_listeners = {}
|
||||||
self._controller_listeners = set()
|
self._controller_listeners = set()
|
||||||
@ -71,19 +72,6 @@ class Notification:
|
|||||||
:param event: Event to send
|
:param event: Event to send
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# If use in tests for documentation we save a sample
|
|
||||||
if os.environ.get("PYTEST_BUILD_DOCUMENTATION") == "1":
|
|
||||||
os.makedirs("docs/api/notifications", exist_ok=True)
|
|
||||||
try:
|
|
||||||
import json
|
|
||||||
|
|
||||||
data = json.dumps(event, indent=4, sort_keys=True)
|
|
||||||
if "MagicMock" not in data:
|
|
||||||
with open(os.path.join("docs/api/notifications", action + ".json"), "w+") as f:
|
|
||||||
f.write(data)
|
|
||||||
except TypeError: # If we receive a mock as an event it will raise TypeError when using json dump
|
|
||||||
pass
|
|
||||||
|
|
||||||
for controller_listener in self._controller_listeners:
|
for controller_listener in self._controller_listeners:
|
||||||
controller_listener.put_nowait((action, event, {}))
|
controller_listener.put_nowait((action, event, {}))
|
||||||
|
|
||||||
@ -127,19 +115,6 @@ class Notification:
|
|||||||
:param event: Event to send
|
:param event: Event to send
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# If use in tests for documentation we save a sample
|
|
||||||
if os.environ.get("PYTEST_BUILD_DOCUMENTATION") == "1":
|
|
||||||
os.makedirs("docs/api/notifications", exist_ok=True)
|
|
||||||
try:
|
|
||||||
import json
|
|
||||||
|
|
||||||
data = json.dumps(event, indent=4, sort_keys=True)
|
|
||||||
if "MagicMock" not in data:
|
|
||||||
with open(os.path.join("docs/api/notifications", action + ".json"), "w+") as f:
|
|
||||||
f.write(data)
|
|
||||||
except TypeError: # If we receive a mock as an event it will raise TypeError when using json dump
|
|
||||||
pass
|
|
||||||
|
|
||||||
if "project_id" in event or project_id:
|
if "project_id" in event or project_id:
|
||||||
self._send_event_to_project(event.get("project_id", project_id), action, event)
|
self._send_event_to_project(event.get("project_id", project_id), action, event)
|
||||||
else:
|
else:
|
||||||
|
@ -633,7 +633,7 @@ class Project:
|
|||||||
def _get_closed_data(self, section, id_key):
|
def _get_closed_data(self, section, id_key):
|
||||||
"""
|
"""
|
||||||
Get the data for a project from the .gns3 when
|
Get the data for a project from the .gns3 when
|
||||||
the project is close
|
the project is closed
|
||||||
|
|
||||||
:param section: The section name in the .gns3
|
:param section: The section name in the .gns3
|
||||||
:param id_key: The key for the element unique id
|
:param id_key: The key for the element unique id
|
||||||
@ -1117,7 +1117,7 @@ class Project:
|
|||||||
try:
|
try:
|
||||||
topo = project_to_topology(self)
|
topo = project_to_topology(self)
|
||||||
path = self._topology_file()
|
path = self._topology_file()
|
||||||
log.debug("Write %s", path)
|
log.debug(f"Write topology file '{path}'")
|
||||||
with open(path + ".tmp", "w+", encoding="utf-8") as f:
|
with open(path + ".tmp", "w+", encoding="utf-8") as f:
|
||||||
json.dump(topo, f, indent=4, sort_keys=True)
|
json.dump(topo, f, indent=4, sort_keys=True)
|
||||||
shutil.move(path + ".tmp", path)
|
shutil.move(path + ".tmp", path)
|
||||||
@ -1176,6 +1176,7 @@ class Project:
|
|||||||
:param z: Z position
|
:param z: Z position
|
||||||
:returns: New node
|
:returns: New node
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if node.status != "stopped" and not node.is_always_running():
|
if node.status != "stopped" and not node.is_always_running():
|
||||||
raise ControllerError("Cannot duplicate node data while the node is running")
|
raise ControllerError("Cannot duplicate node data while the node is running")
|
||||||
|
|
||||||
|
@ -36,10 +36,6 @@ import logging
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# The string use to extract the date from the filename
|
|
||||||
FILENAME_TIME_FORMAT = "%d%m%y_%H%M%S"
|
|
||||||
|
|
||||||
|
|
||||||
class Snapshot:
|
class Snapshot:
|
||||||
"""
|
"""
|
||||||
A snapshot object
|
A snapshot object
|
||||||
@ -59,7 +55,7 @@ class Snapshot:
|
|||||||
filename = (
|
filename = (
|
||||||
self._name
|
self._name
|
||||||
+ "_"
|
+ "_"
|
||||||
+ datetime.utcfromtimestamp(self._created_at).replace(tzinfo=None).strftime(FILENAME_TIME_FORMAT)
|
+ datetime.utcfromtimestamp(self._created_at).replace(tzinfo=None).strftime("%d%m%y_%H%M%S")
|
||||||
+ ".gns3project"
|
+ ".gns3project"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -67,7 +63,7 @@ class Snapshot:
|
|||||||
datestring = filename.replace(self._name + "_", "").split(".")[0]
|
datestring = filename.replace(self._name + "_", "").split(".")[0]
|
||||||
try:
|
try:
|
||||||
self._created_at = (
|
self._created_at = (
|
||||||
datetime.strptime(datestring, FILENAME_TIME_FORMAT).replace(tzinfo=timezone.utc).timestamp()
|
datetime.strptime(datestring, "%d%m%y_%H%M%S").replace(tzinfo=timezone.utc).timestamp()
|
||||||
)
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self._created_at = datetime.utcnow().timestamp()
|
self._created_at = datetime.utcnow().timestamp()
|
||||||
|
@ -121,7 +121,8 @@ def load_topology(path):
|
|||||||
"""
|
"""
|
||||||
Open a topology file, patch it for last GNS3 release and return it
|
Open a topology file, patch it for last GNS3 release and return it
|
||||||
"""
|
"""
|
||||||
log.debug("Read topology %s", path)
|
|
||||||
|
log.debug(f"Read topology {path}")
|
||||||
try:
|
try:
|
||||||
with open(path, encoding="utf-8") as f:
|
with open(path, encoding="utf-8") as f:
|
||||||
topo = json.load(f)
|
topo = json.load(f)
|
||||||
|
@ -20,7 +20,7 @@ from .common import ErrorMessage
|
|||||||
from .version import Version
|
from .version import Version
|
||||||
|
|
||||||
# Controller schemas
|
# Controller schemas
|
||||||
from .controller.links import Link
|
from .controller.links import LinkCreate, LinkUpdate, Link
|
||||||
from .controller.computes import ComputeCreate, ComputeUpdate, AutoIdlePC, Compute
|
from .controller.computes import ComputeCreate, ComputeUpdate, AutoIdlePC, Compute
|
||||||
from .controller.templates import TemplateCreate, TemplateUpdate, TemplateUsage, Template
|
from .controller.templates import TemplateCreate, TemplateUpdate, TemplateUsage, Template
|
||||||
from .controller.drawings import Drawing
|
from .controller.drawings import Drawing
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from uuid import UUID
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
from .labels import Label
|
from .labels import Label
|
||||||
|
|
||||||
@ -42,24 +42,45 @@ class LinkType(str, Enum):
|
|||||||
serial = "serial"
|
serial = "serial"
|
||||||
|
|
||||||
|
|
||||||
class Link(BaseModel):
|
class LinkBase(BaseModel):
|
||||||
"""
|
"""
|
||||||
Link data.
|
Link data.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
link_id: Optional[UUID] = None
|
nodes: Optional[List[LinkNode]] = Field(None, min_items=0, max_items=2)
|
||||||
project_id: Optional[UUID] = None
|
|
||||||
nodes: Optional[List[LinkNode]] = None
|
|
||||||
suspend: Optional[bool] = None
|
suspend: Optional[bool] = None
|
||||||
filters: Optional[dict] = None
|
filters: Optional[dict] = None
|
||||||
capturing: Optional[bool] = Field(None, description="Read only property. True if a capture running on the link")
|
|
||||||
|
|
||||||
|
class LinkCreate(LinkBase):
|
||||||
|
|
||||||
|
link_id: UUID = Field(default_factory=uuid4)
|
||||||
|
nodes: List[LinkNode] = Field(..., min_items=2, max_items=2)
|
||||||
|
|
||||||
|
|
||||||
|
class LinkUpdate(LinkBase):
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Link(LinkBase):
|
||||||
|
|
||||||
|
link_id: UUID
|
||||||
|
project_id: Optional[UUID] = None
|
||||||
|
link_type: Optional[LinkType] = None
|
||||||
|
capturing: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Read only property. True if a capture running on the link"
|
||||||
|
)
|
||||||
capture_file_name: Optional[str] = Field(
|
capture_file_name: Optional[str] = Field(
|
||||||
None, description="Read only property. The name of the capture file if a capture is running"
|
None,
|
||||||
|
description="Read only property. The name of the capture file if a capture is running"
|
||||||
)
|
)
|
||||||
capture_file_path: Optional[str] = Field(
|
capture_file_path: Optional[str] = Field(
|
||||||
None, description="Read only property. The full path of the capture file if a capture is running"
|
None,
|
||||||
|
description="Read only property. The full path of the capture file if a capture is running"
|
||||||
)
|
)
|
||||||
capture_compute_id: Optional[str] = Field(
|
capture_compute_id: Optional[str] = Field(
|
||||||
None, description="Read only property. The compute identifier where a capture is running"
|
None,
|
||||||
|
description="Read only property. The compute identifier where a capture is running"
|
||||||
)
|
)
|
||||||
link_type: Optional[LinkType] = None
|
|
||||||
|
@ -20,7 +20,7 @@ import time
|
|||||||
|
|
||||||
class CpuPercent:
|
class CpuPercent:
|
||||||
"""
|
"""
|
||||||
Ensures a minumum interval between two cpu_percent() calls
|
Ensures a minimum interval between two cpu_percent() calls
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_last_measurement = None # time of last measurement
|
_last_measurement = None # time of last measurement
|
||||||
|
Loading…
Reference in New Issue
Block a user