changes to support better type checking for retrieving an arbitrary node from a session, get_node now requires an expected class that the node would be an instance of, if the returned node is not an instance a CoreError is thrown, this also helps editors pick up expected types to account for variable/function usage better as well

This commit is contained in:
Blake Harnden 2020-05-20 14:44:34 -07:00
parent 19ee367dc5
commit d5254e6a91
21 changed files with 149 additions and 126 deletions

View file

@ -6,7 +6,7 @@ import tempfile
import threading
import time
from concurrent import futures
from typing import Type, TypeVar
from typing import Type
import grpc
from grpc import ServicerContext
@ -109,7 +109,7 @@ from core.emulator.coreemu import CoreEmu
from core.emulator.data import LinkData
from core.emulator.emudata import LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, LinkTypes, MessageFlags
from core.emulator.session import Session
from core.emulator.session import NT, Session
from core.errors import CoreCommandError, CoreError
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
from core.nodes.base import CoreNode, CoreNodeBase, NodeBase
@ -118,7 +118,6 @@ from core.services.coreservices import ServiceManager
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_INTERFACE_REGEX = re.compile(r"veth(?P<node>[0-9a-fA-F]+)")
T = TypeVar("T")
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
@ -174,36 +173,22 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
return session
def get_node(
self,
session: Session,
node_id: int,
context: ServicerContext,
node_class: Type[T],
) -> T:
self, session: Session, node_id: int, context: ServicerContext, _class: Type[NT]
) -> NT:
"""
Retrieve node given session and node id
:param session: session that has the node
:param node_id: node id
:param context: request
:param node_class: type of node we are expecting
:param _class: type of node we are expecting
:return: node object that satisfies. If node not found then raise an exception.
:raises Exception: raises grpc exception when node does not exist
"""
try:
node = session.get_node(node_id)
if isinstance(node, node_class):
return node
else:
actual = node.__class__.__name__
expected = node_class.__name__
context.abort(
grpc.StatusCode.NOT_FOUND,
f"node({node_id}) class({actual}) "
f"was not expected class({expected})",
)
except CoreError:
context.abort(grpc.StatusCode.NOT_FOUND, f"node {node_id} not found")
return session.get_node(node_id, _class)
except CoreError as e:
context.abort(grpc.StatusCode.NOT_FOUND, str(e))
def validate_service(
self, name: str, context: ServicerContext

View file

@ -41,6 +41,7 @@ from core.emulator.enumerations import (
)
from core.errors import CoreCommandError, CoreError
from core.location.mobility import BasicRangeModel
from core.nodes.base import CoreNodeBase, NodeBase
from core.nodes.network import WlanNode
from core.services.coreservices import ServiceManager, ServiceShim
@ -836,7 +837,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
return ()
try:
node = self.session.get_node(node_num)
node = self.session.get_node(node_num, CoreNodeBase)
# build common TLV items for reply
tlv_data = b""
@ -1228,7 +1229,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
if not node_id:
return replies
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, CoreNodeBase)
if node is None:
logging.warning(
"request to configure service for unknown node %s", node_id
@ -1373,7 +1374,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
self.session.mobility.set_model_config(node_id, object_name, parsed_config)
if self.session.state == EventTypes.RUNTIME_STATE and parsed_config:
try:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, WlanNode)
if object_name == BasicRangeModel.name:
node.updatemodel(parsed_config)
except CoreError:
@ -1553,7 +1554,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
logging.debug("handling event %s at %s", event_type.name, time.ctime())
if event_type.value <= EventTypes.SHUTDOWN_STATE.value:
if node_id is not None:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, NodeBase)
# configure mobility models for WLAN added during runtime
if event_type == EventTypes.INSTANTIATION_STATE and isinstance(
@ -1647,7 +1648,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
name = event_data.name
try:
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, CoreNodeBase)
except CoreError:
logging.warning(
"ignoring event for service '%s', unknown node '%s'", name, node_id
@ -1883,7 +1884,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
data_types = tuple(
repeat(ConfigDataTypes.STRING.value, len(ServiceShim.keys))
)
node = self.session.get_node(node_id)
node = self.session.get_node(node_id, CoreNodeBase)
values = ServiceShim.tovaluelist(node, service)
config_data = ConfigData(
message_type=0,