daemon: updated core.emulator to avoid using deprecated type hinting

This commit is contained in:
Blake Harnden 2023-04-13 12:23:44 -07:00
parent 4c222d1a7a
commit 8abf2561bf
7 changed files with 63 additions and 63 deletions

View file

@ -1,7 +1,6 @@
import logging import logging
import os import os
from pathlib import Path from pathlib import Path
from typing import Dict, List, Type
from core import utils from core import utils
from core.configservice.manager import ConfigServiceManager from core.configservice.manager import ConfigServiceManager
@ -20,7 +19,7 @@ class CoreEmu:
Provides logic for creating and configuring CORE sessions and the nodes within them. Provides logic for creating and configuring CORE sessions and the nodes within them.
""" """
def __init__(self, config: Dict[str, str] = None) -> None: def __init__(self, config: dict[str, str] = None) -> None:
""" """
Create a CoreEmu object. Create a CoreEmu object.
@ -31,13 +30,13 @@ class CoreEmu:
# configuration # configuration
config = config if config else {} config = config if config else {}
self.config: Dict[str, str] = config self.config: dict[str, str] = config
# session management # session management
self.sessions: Dict[int, Session] = {} self.sessions: dict[int, Session] = {}
# load services # load services
self.service_errors: List[str] = [] self.service_errors: list[str] = []
self.service_manager: ConfigServiceManager = ConfigServiceManager() self.service_manager: ConfigServiceManager = ConfigServiceManager()
self._load_services() self._load_services()
@ -119,7 +118,7 @@ class CoreEmu:
_, session = self.sessions.popitem() _, session = self.sessions.popitem()
session.shutdown() session.shutdown()
def create_session(self, _id: int = None, _cls: Type[Session] = Session) -> Session: def create_session(self, _id: int = None, _cls: type[Session] = Session) -> Session:
""" """
Create a new CORE session. Create a new CORE session.

View file

@ -2,7 +2,7 @@
CORE data objects. CORE data objects.
""" """
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, List, Optional, Tuple from typing import TYPE_CHECKING, Any, Optional
import netaddr import netaddr
@ -24,7 +24,7 @@ class ConfigData:
node: int = None node: int = None
object: str = None object: str = None
type: int = None type: int = None
data_types: Tuple[int] = None data_types: tuple[int] = None
data_values: str = None data_values: str = None
captions: str = None captions: str = None
bitmap: str = None bitmap: str = None
@ -81,8 +81,8 @@ class NodeOptions:
model: Optional[str] = "PC" model: Optional[str] = "PC"
canvas: int = None canvas: int = None
icon: str = None icon: str = None
services: List[str] = field(default_factory=list) services: list[str] = field(default_factory=list)
config_services: List[str] = field(default_factory=list) config_services: list[str] = field(default_factory=list)
x: float = None x: float = None
y: float = None y: float = None
lat: float = None lat: float = None
@ -93,9 +93,9 @@ class NodeOptions:
emane: str = None emane: str = None
legacy: bool = False legacy: bool = False
# src, dst # src, dst
binds: List[Tuple[str, str]] = field(default_factory=list) binds: list[tuple[str, str]] = field(default_factory=list)
# src, dst, unique, delete # src, dst, unique, delete
volumes: List[Tuple[str, str, bool, bool]] = field(default_factory=list) volumes: list[tuple[str, str, bool, bool]] = field(default_factory=list)
def set_position(self, x: float, y: float) -> None: def set_position(self, x: float, y: float) -> None:
""" """
@ -148,7 +148,7 @@ class InterfaceData:
ip6_mask: int = None ip6_mask: int = None
mtu: int = None mtu: int = None
def get_ips(self) -> List[str]: def get_ips(self) -> list[str]:
""" """
Returns a list of ip4 and ip6 addresses when present. Returns a list of ip4 and ip6 addresses when present.

View file

@ -8,7 +8,7 @@ import threading
from collections import OrderedDict from collections import OrderedDict
from pathlib import Path from pathlib import Path
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from typing import TYPE_CHECKING, Callable, Dict, Tuple from typing import TYPE_CHECKING, Callable
import netaddr import netaddr
from fabric import Connection from fabric import Connection
@ -48,7 +48,7 @@ class DistributedServer:
self.lock: threading.Lock = threading.Lock() self.lock: threading.Lock = threading.Lock()
def remote_cmd( def remote_cmd(
self, cmd: str, env: Dict[str, str] = None, cwd: str = None, wait: bool = True self, cmd: str, env: dict[str, str] = None, cwd: str = None, wait: bool = True
) -> str: ) -> str:
""" """
Run command remotely using server connection. Run command remotely using server connection.
@ -123,8 +123,8 @@ class DistributedController:
:param session: session :param session: session
""" """
self.session: "Session" = session self.session: "Session" = session
self.servers: Dict[str, DistributedServer] = OrderedDict() self.servers: dict[str, DistributedServer] = OrderedDict()
self.tunnels: Dict[int, Tuple[GreTap, GreTap]] = {} self.tunnels: dict[int, tuple[GreTap, GreTap]] = {}
self.address: str = self.session.options.get("distributed_address") self.address: str = self.session.options.get("distributed_address")
def add_server(self, name: str, host: str) -> None: def add_server(self, name: str, host: str) -> None:
@ -213,7 +213,7 @@ class DistributedController:
def create_gre_tunnel( def create_gre_tunnel(
self, node: CoreNetwork, server: DistributedServer, mtu: int, start: bool self, node: CoreNetwork, server: DistributedServer, mtu: int, start: bool
) -> Tuple[GreTap, GreTap]: ) -> tuple[GreTap, GreTap]:
""" """
Create gre tunnel using a pair of gre taps between the local and remote server. Create gre tunnel using a pair of gre taps between the local and remote server.

View file

@ -129,7 +129,7 @@ class HookManager:
cwd=directory, cwd=directory,
env=env, env=env,
) )
except (IOError, subprocess.CalledProcessError) as e: except (OSError, subprocess.CalledProcessError) as e:
raise CoreError( raise CoreError(
f"failure running state({state.name}) " f"failure running state({state.name}) "
f"hook script({file_name}): {e}", f"hook script({file_name}): {e}",

View file

@ -4,8 +4,9 @@ for a session.
""" """
import logging import logging
from collections.abc import ValuesView
from dataclasses import dataclass from dataclasses import dataclass
from typing import Dict, Optional, Tuple, ValuesView from typing import Optional
from core.emulator.data import LinkData, LinkOptions from core.emulator.data import LinkData, LinkOptions
from core.emulator.enumerations import LinkTypes, MessageFlags from core.emulator.enumerations import LinkTypes, MessageFlags
@ -15,7 +16,7 @@ from core.nodes.interface import CoreInterface
from core.nodes.network import PtpNet from core.nodes.network import PtpNet
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
LinkKeyType = Tuple[int, Optional[int], int, Optional[int]] LinkKeyType = tuple[int, Optional[int], int, Optional[int]]
def create_key( def create_key(
@ -145,8 +146,8 @@ class LinkManager:
""" """
Create a LinkManager instance. Create a LinkManager instance.
""" """
self._links: Dict[LinkKeyType, CoreLink] = {} self._links: dict[LinkKeyType, CoreLink] = {}
self._node_links: Dict[int, Dict[LinkKeyType, CoreLink]] = {} self._node_links: dict[int, dict[LinkKeyType, CoreLink]] = {}
def add(self, core_link: CoreLink) -> None: def add(self, core_link: CoreLink) -> None:
""" """

View file

@ -14,7 +14,7 @@ import tempfile
import threading import threading
import time import time
from pathlib import Path from pathlib import Path
from typing import Callable, Dict, List, Optional, Set, Tuple, Type, TypeVar, Union from typing import Callable, Optional, TypeVar, Union
from core import constants, utils from core import constants, utils
from core.configservice.manager import ConfigServiceManager from core.configservice.manager import ConfigServiceManager
@ -66,7 +66,7 @@ from core.xml.corexml import CoreXmlReader, CoreXmlWriter
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# maps for converting from API call node type values to classes and vice versa # maps for converting from API call node type values to classes and vice versa
NODES: Dict[NodeTypes, Type[NodeBase]] = { NODES: dict[NodeTypes, type[NodeBase]] = {
NodeTypes.DEFAULT: CoreNode, NodeTypes.DEFAULT: CoreNode,
NodeTypes.PHYSICAL: PhysicalNode, NodeTypes.PHYSICAL: PhysicalNode,
NodeTypes.SWITCH: SwitchNode, NodeTypes.SWITCH: SwitchNode,
@ -82,12 +82,12 @@ NODES: Dict[NodeTypes, Type[NodeBase]] = {
NodeTypes.LXC: LxcNode, NodeTypes.LXC: LxcNode,
NodeTypes.WIRELESS: WirelessNode, NodeTypes.WIRELESS: WirelessNode,
} }
NODES_TYPE: Dict[Type[NodeBase], NodeTypes] = {NODES[x]: x for x in NODES} NODES_TYPE: dict[type[NodeBase], NodeTypes] = {NODES[x]: x for x in NODES}
CONTAINER_NODES: Set[Type[NodeBase]] = {DockerNode, LxcNode} CONTAINER_NODES: set[type[NodeBase]] = {DockerNode, LxcNode}
CTRL_NET_ID: int = 9001 CTRL_NET_ID: int = 9001
LINK_COLORS: List[str] = ["green", "blue", "orange", "purple", "turquoise"] LINK_COLORS: list[str] = ["green", "blue", "orange", "purple", "turquoise"]
NT: TypeVar = TypeVar("NT", bound=NodeBase) NT: TypeVar = TypeVar("NT", bound=NodeBase)
WIRELESS_TYPE: Tuple[Type[WlanNode], Type[EmaneNet], Type[WirelessNode]] = ( WIRELESS_TYPE: tuple[type[WlanNode], type[EmaneNet], type[WirelessNode]] = (
WlanNode, WlanNode,
EmaneNet, EmaneNet,
WirelessNode, WirelessNode,
@ -100,7 +100,7 @@ class Session:
""" """
def __init__( def __init__(
self, _id: int, config: Dict[str, str] = None, mkdir: bool = True self, _id: int, config: dict[str, str] = None, mkdir: bool = True
) -> None: ) -> None:
""" """
Create a Session instance. Create a Session instance.
@ -121,33 +121,33 @@ class Session:
self.thumbnail: Optional[Path] = None self.thumbnail: Optional[Path] = None
self.user: Optional[str] = None self.user: Optional[str] = None
self.event_loop: EventLoop = EventLoop() self.event_loop: EventLoop = EventLoop()
self.link_colors: Dict[int, str] = {} self.link_colors: dict[int, str] = {}
# dict of nodes: all nodes and nets # dict of nodes: all nodes and nets
self.nodes: Dict[int, NodeBase] = {} self.nodes: dict[int, NodeBase] = {}
self.nodes_lock: threading.Lock = threading.Lock() self.nodes_lock: threading.Lock = threading.Lock()
self.link_manager: LinkManager = LinkManager() self.link_manager: LinkManager = LinkManager()
# states and hooks handlers # states and hooks handlers
self.state: EventTypes = EventTypes.DEFINITION_STATE self.state: EventTypes = EventTypes.DEFINITION_STATE
self.state_time: float = time.monotonic() self.state_time: float = time.monotonic()
self.hooks: Dict[EventTypes, List[Tuple[str, str]]] = {} self.hooks: dict[EventTypes, list[tuple[str, str]]] = {}
self.state_hooks: Dict[EventTypes, List[Callable[[EventTypes], None]]] = {} self.state_hooks: dict[EventTypes, list[Callable[[EventTypes], None]]] = {}
self.add_state_hook( self.add_state_hook(
state=EventTypes.RUNTIME_STATE, hook=self.runtime_state_hook state=EventTypes.RUNTIME_STATE, hook=self.runtime_state_hook
) )
# handlers for broadcasting information # handlers for broadcasting information
self.event_handlers: List[Callable[[EventData], None]] = [] self.event_handlers: list[Callable[[EventData], None]] = []
self.exception_handlers: List[Callable[[ExceptionData], None]] = [] self.exception_handlers: list[Callable[[ExceptionData], None]] = []
self.node_handlers: List[Callable[[NodeData], None]] = [] self.node_handlers: list[Callable[[NodeData], None]] = []
self.link_handlers: List[Callable[[LinkData], None]] = [] self.link_handlers: list[Callable[[LinkData], None]] = []
self.file_handlers: List[Callable[[FileData], None]] = [] self.file_handlers: list[Callable[[FileData], None]] = []
self.config_handlers: List[Callable[[ConfigData], None]] = [] self.config_handlers: list[Callable[[ConfigData], None]] = []
# session options/metadata # session options/metadata
self.options: SessionConfig = SessionConfig(config) self.options: SessionConfig = SessionConfig(config)
self.metadata: Dict[str, str] = {} self.metadata: dict[str, str] = {}
# distributed support and logic # distributed support and logic
self.distributed: DistributedController = DistributedController(self) self.distributed: DistributedController = DistributedController(self)
@ -163,7 +163,7 @@ class Session:
self.service_manager: Optional[ConfigServiceManager] = None self.service_manager: Optional[ConfigServiceManager] = None
@classmethod @classmethod
def get_node_class(cls, _type: NodeTypes) -> Type[NodeBase]: def get_node_class(cls, _type: NodeTypes) -> type[NodeBase]:
""" """
Retrieve the class for a given node type. Retrieve the class for a given node type.
@ -176,7 +176,7 @@ class Session:
return node_class return node_class
@classmethod @classmethod
def get_node_type(cls, _class: Type[NodeBase]) -> NodeTypes: def get_node_type(cls, _class: type[NodeBase]) -> NodeTypes:
""" """
Retrieve node type for a given node class. Retrieve node type for a given node class.
@ -238,7 +238,7 @@ class Session:
iface1_data: InterfaceData = None, iface1_data: InterfaceData = None,
iface2_data: InterfaceData = None, iface2_data: InterfaceData = None,
options: LinkOptions = None, options: LinkOptions = None,
) -> Tuple[Optional[CoreInterface], Optional[CoreInterface]]: ) -> tuple[Optional[CoreInterface], Optional[CoreInterface]]:
""" """
Add a link between nodes. Add a link between nodes.
@ -345,7 +345,7 @@ class Session:
iface1_data: InterfaceData = None, iface1_data: InterfaceData = None,
iface2_data: InterfaceData = None, iface2_data: InterfaceData = None,
options: LinkOptions = None, options: LinkOptions = None,
) -> Tuple[CoreInterface, CoreInterface]: ) -> tuple[CoreInterface, CoreInterface]:
""" """
Create a wired link between two nodes. Create a wired link between two nodes.
@ -476,7 +476,7 @@ class Session:
def add_node( def add_node(
self, self,
_class: Type[NT], _class: type[NT],
_id: int = None, _id: int = None,
name: str = None, name: str = None,
server: str = None, server: str = None,
@ -745,7 +745,7 @@ class Session:
for hook in hooks: for hook in hooks:
self.run_hook(hook) self.run_hook(hook)
def run_hook(self, hook: Tuple[str, str]) -> None: def run_hook(self, hook: tuple[str, str]) -> None:
""" """
Run a hook. Run a hook.
@ -769,7 +769,7 @@ class Session:
cwd=self.directory, cwd=self.directory,
env=self.get_environment(), env=self.get_environment(),
) )
except (IOError, subprocess.CalledProcessError): except (OSError, subprocess.CalledProcessError):
logger.exception("error running hook: %s", file_path) logger.exception("error running hook: %s", file_path)
def run_state_hooks(self, state: EventTypes) -> None: def run_state_hooks(self, state: EventTypes) -> None:
@ -835,7 +835,7 @@ class Session:
xml_file_path = self.directory / "session-deployed.xml" xml_file_path = self.directory / "session-deployed.xml"
xml_writer.write(xml_file_path) xml_writer.write(xml_file_path)
def get_environment(self, state: bool = True) -> Dict[str, str]: def get_environment(self, state: bool = True) -> dict[str, str]:
""" """
Get an environment suitable for a subprocess.Popen call. Get an environment suitable for a subprocess.Popen call.
This is the current process environment with some session-specific This is the current process environment with some session-specific
@ -870,7 +870,7 @@ class Session:
if path.is_file(): if path.is_file():
try: try:
utils.load_config(path, env) utils.load_config(path, env)
except IOError: except OSError:
logger.exception("error reading environment file: %s", path) logger.exception("error reading environment file: %s", path)
return env return env
@ -887,12 +887,12 @@ class Session:
uid = pwd.getpwnam(user).pw_uid uid = pwd.getpwnam(user).pw_uid
gid = self.directory.stat().st_gid gid = self.directory.stat().st_gid
os.chown(self.directory, uid, gid) os.chown(self.directory, uid, gid)
except IOError: except OSError:
logger.exception("failed to set permission on %s", self.directory) logger.exception("failed to set permission on %s", self.directory)
def create_node( def create_node(
self, self,
_class: Type[NT], _class: type[NT],
start: bool, start: bool,
_id: int = None, _id: int = None,
name: str = None, name: str = None,
@ -928,7 +928,7 @@ class Session:
node.startup() node.startup()
return node return node
def get_node(self, _id: int, _class: Type[NT]) -> NT: def get_node(self, _id: int, _class: type[NT]) -> NT:
""" """
Get a session node. Get a session node.
@ -1002,7 +1002,7 @@ class Session:
) )
self.broadcast_exception(exception_data) self.broadcast_exception(exception_data)
def instantiate(self) -> List[Exception]: def instantiate(self) -> list[Exception]:
""" """
We have entered the instantiation state, invoke startup methods We have entered the instantiation state, invoke startup methods
of various managers and boot the nodes. Validate nodes and check of various managers and boot the nodes. Validate nodes and check
@ -1121,7 +1121,7 @@ class Session:
self.services.boot_services(node) self.services.boot_services(node)
node.start_config_services() node.start_config_services()
def boot_nodes(self) -> List[Exception]: def boot_nodes(self) -> list[Exception]:
""" """
Invoke the boot() procedure for all nodes and send back node Invoke the boot() procedure for all nodes and send back node
messages to the GUI for node messages that had the status messages to the GUI for node messages that had the status
@ -1143,7 +1143,7 @@ class Session:
self.update_control_iface_hosts() self.update_control_iface_hosts()
return exceptions return exceptions
def get_control_net_prefixes(self) -> List[str]: def get_control_net_prefixes(self) -> list[str]:
""" """
Retrieve control net prefixes. Retrieve control net prefixes.
@ -1158,7 +1158,7 @@ class Session:
p0 = p p0 = p
return [p0, p1, p2, p3] return [p0, p1, p2, p3]
def get_control_net_server_ifaces(self) -> List[str]: def get_control_net_server_ifaces(self) -> list[str]:
""" """
Retrieve control net server interfaces. Retrieve control net server interfaces.

View file

@ -1,4 +1,4 @@
from typing import Dict, List, Optional from typing import Optional
from core.config import ConfigBool, ConfigInt, ConfigString, Configuration from core.config import ConfigBool, ConfigInt, ConfigString, Configuration
from core.errors import CoreError from core.errors import CoreError
@ -10,7 +10,7 @@ class SessionConfig:
Provides session configuration. Provides session configuration.
""" """
options: List[Configuration] = [ options: list[Configuration] = [
ConfigString(id="controlnet", label="Control Network"), ConfigString(id="controlnet", label="Control Network"),
ConfigString(id="controlnet0", label="Control Network 0"), ConfigString(id="controlnet0", label="Control Network 0"),
ConfigString(id="controlnet1", label="Control Network 1"), ConfigString(id="controlnet1", label="Control Network 1"),
@ -35,16 +35,16 @@ class SessionConfig:
ConfigInt(id="mtu", default="0", label="MTU for All Devices"), ConfigInt(id="mtu", default="0", label="MTU for All Devices"),
] ]
def __init__(self, config: Dict[str, str] = None) -> None: def __init__(self, config: dict[str, str] = None) -> None:
""" """
Create a SessionConfig instance. Create a SessionConfig instance.
:param config: configuration to initialize with :param config: configuration to initialize with
""" """
self._config: Dict[str, str] = {x.id: x.default for x in self.options} self._config: dict[str, str] = {x.id: x.default for x in self.options}
self._config.update(config or {}) self._config.update(config or {})
def update(self, config: Dict[str, str]) -> None: def update(self, config: dict[str, str]) -> None:
""" """
Update current configuration with provided values. Update current configuration with provided values.
@ -73,7 +73,7 @@ class SessionConfig:
""" """
return self._config.get(name, default) return self._config.get(name, default)
def all(self) -> Dict[str, str]: def all(self) -> dict[str, str]:
""" """
Retrieve all configuration options. Retrieve all configuration options.