Some cleaning.

This commit is contained in:
grossmj 2021-04-17 18:36:32 +09:30
parent bad3ef7003
commit 44074ff7c9
22 changed files with 122 additions and 99 deletions

@ -71,7 +71,7 @@ async def get_links(project_id: UUID):
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.
"""
@ -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)
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.
"""

@ -40,7 +40,12 @@ class EthernetHub(BaseNode):
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):
"""

@ -40,7 +40,12 @@ class EthernetSwitch(BaseNode):
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):
"""

@ -67,4 +67,7 @@ class NIOGenericEthernet(NIO):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):

@ -17,14 +17,15 @@
import copy
import uuid
import logging
log = logging.getLogger(__name__)
class Appliance:
def __init__(self, appliance_id, data, builtin=True):
if appliance_id is None:
self._id = str(uuid.uuid4())
elif isinstance(appliance_id, uuid.UUID):

@ -390,7 +390,6 @@ class Node:
data["node_id"] = self._id
if self._node_type == "docker":
timeout = None
else:
timeout = 1200
trial = 0
@ -543,7 +542,7 @@ class Node:
if 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()):
if data[key] is None or data[key] is {} or key in self.CONTROLLER_ONLY_PROPERTIES:
del data[key]
@ -628,7 +627,7 @@ class Node:
async def put(self, path, data=None, **kwargs):
"""
HTTP post on the node
HTTP put on the node
"""
if path is None:
path = f"/projects/{self._project.id}/{self._node_type}/nodes/{self._id}"
@ -780,11 +779,10 @@ class Node:
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:
return {
topology = {
"compute_id": str(self._compute.id),
"node_id": self._id,
"node_type": self._node_type,
@ -808,35 +806,18 @@ class Node:
"port_segment_size": self._port_segment_size,
"first_port_name": self._first_port_name,
"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):
self._controller = controller
self._project_listeners = {}
self._controller_listeners = set()
@ -71,19 +72,6 @@ class Notification:
: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:
controller_listener.put_nowait((action, event, {}))
@ -127,19 +115,6 @@ class Notification:
: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:
self._send_event_to_project(event.get("project_id", project_id), action, event)
else:

@ -633,7 +633,7 @@ class Project:
def _get_closed_data(self, section, id_key):
"""
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 id_key: The key for the element unique id
@ -1117,7 +1117,7 @@ class Project:
try:
topo = project_to_topology(self)
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:
json.dump(topo, f, indent=4, sort_keys=True)
shutil.move(path + ".tmp", path)
@ -1176,6 +1176,7 @@ class Project:
:param z: Z position
:returns: New node
"""
if node.status != "stopped" and not node.is_always_running():
raise ControllerError("Cannot duplicate node data while the node is running")

@ -36,10 +36,6 @@ import logging
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:
"""
A snapshot object
@ -59,7 +55,7 @@ class Snapshot:
filename = (
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"
)
else:
@ -67,7 +63,7 @@ class Snapshot:
datestring = filename.replace(self._name + "_", "").split(".")[0]
try:
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:
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
"""
log.debug("Read topology %s", path)
log.debug(f"Read topology {path}")
try:
with open(path, encoding="utf-8") as f:
topo = json.load(f)

@ -20,7 +20,7 @@ from .common import ErrorMessage
from .version import Version
# Controller schemas
from .controller.links import Link
from .controller.links import LinkCreate, LinkUpdate, Link
from .controller.computes import ComputeCreate, ComputeUpdate, AutoIdlePC, Compute
from .controller.templates import TemplateCreate, TemplateUpdate, TemplateUsage, Template
from .controller.drawings import Drawing

@ -17,7 +17,7 @@
from pydantic import BaseModel, Field
from typing import List, Optional
from enum import Enum
from uuid import UUID
from uuid import UUID, uuid4
from .labels import Label
@ -42,24 +42,45 @@ class LinkType(str, Enum):
serial = "serial"
class Link(BaseModel):
class LinkBase(BaseModel):
"""
Link data.
"""
link_id: Optional[UUID] = None
project_id: Optional[UUID] = None
nodes: Optional[List[LinkNode]] = None
nodes: Optional[List[LinkNode]] = Field(None, min_items=0, max_items=2)
suspend: Optional[bool] = 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(
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(
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(
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:
"""
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