From 0462c1b0841bebdc0516d885344b3c52a3a03096 Mon Sep 17 00:00:00 2001 From: Blake Harnden <32446120+bharnden@users.noreply.github.com> Date: Sun, 14 Jun 2020 13:35:06 -0700 Subject: [PATCH] daemon: added usage of ABC to NodeBase, CoreNodeBase, and CoreNetworkBase to help enforce accounting for abstract functions --- daemon/core/emane/nodes.py | 3 + daemon/core/nodes/base.py | 155 ++++++++++++++++++---------------- daemon/core/nodes/physical.py | 10 +-- 3 files changed, 92 insertions(+), 76 deletions(-) diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index 8383cdd1..c4c3428b 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -88,6 +88,9 @@ class EmaneNet(CoreNetworkBase): def unlink(self, netif1: CoreInterface, netif2: CoreInterface) -> None: pass + def linknet(self, net: "CoreNetworkBase") -> CoreInterface: + raise CoreError("emane networks cannot be linked to other networks") + def updatemodel(self, config: Dict[str, str]) -> None: if not self.model: raise CoreError(f"no model set to update for node({self.name})") diff --git a/daemon/core/nodes/base.py b/daemon/core/nodes/base.py index 3e9dfe7a..6c7ebcf0 100644 --- a/daemon/core/nodes/base.py +++ b/daemon/core/nodes/base.py @@ -1,7 +1,7 @@ """ Defines the base logic for nodes used within core. """ - +import abc import logging import os import shutil @@ -34,7 +34,7 @@ if TYPE_CHECKING: _DEFAULT_MTU = 1500 -class NodeBase: +class NodeBase(abc.ABC): """ Base class for CORE nodes (nodes and networks) """ @@ -78,6 +78,7 @@ class NodeBase: use_ovs = session.options.get_config("ovs") == "True" self.net_client: LinuxNetClient = get_net_client(use_ovs, self.host_cmd) + @abc.abstractmethod def startup(self) -> None: """ Each object implements its own startup method. @@ -86,6 +87,7 @@ class NodeBase: """ raise NotImplementedError + @abc.abstractmethod def shutdown(self) -> None: """ Each object implements its own shutdown method. @@ -267,12 +269,74 @@ class CoreNodeBase(NodeBase): self.nodedir: Optional[str] = None self.tmpnodedir: bool = False + @abc.abstractmethod def startup(self) -> None: raise NotImplementedError + @abc.abstractmethod def shutdown(self) -> None: raise NotImplementedError + @abc.abstractmethod + def nodefile(self, filename: str, contents: str, mode: int = 0o644) -> None: + """ + Create a node file with a given mode. + + :param filename: name of file to create + :param contents: contents of file + :param mode: mode for file + :return: nothing + """ + raise NotImplementedError + + @abc.abstractmethod + def addfile(self, srcname: str, filename: str) -> None: + """ + Add a file. + + :param srcname: source file name + :param filename: file name to add + :return: nothing + :raises CoreCommandError: when a non-zero exit status occurs + """ + raise NotImplementedError + + @abc.abstractmethod + def cmd(self, args: str, wait: bool = True, shell: bool = False) -> str: + """ + Runs a command within a node container. + + :param args: command to run + :param wait: True to wait for status, False otherwise + :param shell: True to use shell, False otherwise + :return: combined stdout and stderr + :raises CoreCommandError: when a non-zero exit status occurs + """ + raise NotImplementedError + + @abc.abstractmethod + def termcmdstring(self, sh: str) -> str: + """ + Create a terminal command string. + + :param sh: shell to execute command in + :return: str + """ + raise NotImplementedError + + @abc.abstractmethod + def newnetif( + self, net: "CoreNetworkBase", interface_data: InterfaceData + ) -> CoreInterface: + """ + Create a new network interface. + + :param net: network to associate with + :param interface_data: interface data for new interface + :return: interface index + """ + raise NotImplementedError + def add_config_service(self, service_class: "ConfigServiceType") -> None: """ Adds a configuration service to the node. @@ -432,61 +496,6 @@ class CoreNodeBase(NodeBase): common.append((netif1.net, netif1, netif2)) return common - def nodefile(self, filename: str, contents: str, mode: int = 0o644) -> None: - """ - Create a node file with a given mode. - - :param filename: name of file to create - :param contents: contents of file - :param mode: mode for file - :return: nothing - """ - raise NotImplementedError - - def addfile(self, srcname: str, filename: str) -> None: - """ - Add a file. - - :param srcname: source file name - :param filename: file name to add - :return: nothing - :raises CoreCommandError: when a non-zero exit status occurs - """ - raise NotImplementedError - - def cmd(self, args: str, wait: bool = True, shell: bool = False) -> str: - """ - Runs a command within a node container. - - :param args: command to run - :param wait: True to wait for status, False otherwise - :param shell: True to use shell, False otherwise - :return: combined stdout and stderr - :raises CoreCommandError: when a non-zero exit status occurs - """ - raise NotImplementedError - - def termcmdstring(self, sh: str) -> str: - """ - Create a terminal command string. - - :param sh: shell to execute command in - :return: str - """ - raise NotImplementedError - - def newnetif( - self, net: "CoreNetworkBase", interface_data: InterfaceData - ) -> CoreInterface: - """ - Create a new network interface. - - :param net: network to associate with - :param interface_data: interface data for new interface - :return: interface index - """ - raise NotImplementedError - class CoreNode(CoreNodeBase): """ @@ -1002,6 +1011,7 @@ class CoreNetworkBase(NodeBase): self._linked = {} self._linked_lock = threading.Lock() + @abc.abstractmethod def startup(self) -> None: """ Each object implements its own startup method. @@ -1010,6 +1020,7 @@ class CoreNetworkBase(NodeBase): """ raise NotImplementedError + @abc.abstractmethod def shutdown(self) -> None: """ Each object implements its own shutdown method. @@ -1018,6 +1029,7 @@ class CoreNetworkBase(NodeBase): """ raise NotImplementedError + @abc.abstractmethod def linknet(self, net: "CoreNetworkBase") -> CoreInterface: """ Link network to another. @@ -1025,7 +1037,21 @@ class CoreNetworkBase(NodeBase): :param net: network to link with :return: created interface """ - pass + raise NotImplementedError + + @abc.abstractmethod + def linkconfig( + self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None + ) -> None: + """ + Configure link parameters by applying tc queuing disciplines on the interface. + + :param netif: interface one + :param options: options for configuring link + :param netif2: interface two + :return: nothing + """ + raise NotImplementedError def getlinknetif(self, net: "CoreNetworkBase") -> Optional[CoreInterface]: """ @@ -1156,19 +1182,6 @@ class CoreNetworkBase(NodeBase): return all_links - def linkconfig( - self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None - ) -> None: - """ - Configure link parameters by applying tc queuing disciplines on the interface. - - :param netif: interface one - :param options: options for configuring link - :param netif2: interface two - :return: nothing - """ - raise NotImplementedError - class Position: """ diff --git a/daemon/core/nodes/physical.py b/daemon/core/nodes/physical.py index 13214093..741fe7d5 100644 --- a/daemon/core/nodes/physical.py +++ b/daemon/core/nodes/physical.py @@ -226,7 +226,7 @@ class PhysicalNode(CoreNodeBase): return self.host_cmd(args, wait=wait) def addfile(self, srcname: str, filename: str) -> None: - raise NotImplementedError + raise CoreError("physical node does not support addfile") class Rj45Node(CoreNodeBase): @@ -449,13 +449,13 @@ class Rj45Node(CoreNodeBase): self.interface.setposition() def termcmdstring(self, sh: str) -> str: - raise NotImplementedError + raise CoreError("rj45 does not support terminal commands") def addfile(self, srcname: str, filename: str) -> None: - raise NotImplementedError + raise CoreError("rj45 does not support addfile") def nodefile(self, filename: str, contents: str, mode: int = 0o644) -> None: - raise NotImplementedError + raise CoreError("rj45 does not support nodefile") def cmd(self, args: str, wait: bool = True, shell: bool = False) -> str: - raise NotImplementedError + raise CoreError("rj45 does not support cmds")