Merge pull request #451 from coreemu/enhancement/grpc-wlan-links
Enhancement/grpc wlan links
This commit is contained in:
commit
19ee367dc5
5 changed files with 101 additions and 26 deletions
|
@ -89,6 +89,8 @@ from core.api.grpc.wlan_pb2 import (
|
||||||
SetWlanConfigRequest,
|
SetWlanConfigRequest,
|
||||||
SetWlanConfigResponse,
|
SetWlanConfigResponse,
|
||||||
WlanConfig,
|
WlanConfig,
|
||||||
|
WlanLinkRequest,
|
||||||
|
WlanLinkResponse,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1204,6 +1206,18 @@ class CoreGrpcClient:
|
||||||
request = ExecuteScriptRequest(script=script)
|
request = ExecuteScriptRequest(script=script)
|
||||||
return self.stub.ExecuteScript(request)
|
return self.stub.ExecuteScript(request)
|
||||||
|
|
||||||
|
def wlan_link(
|
||||||
|
self, session_id: int, wlan: int, node_one: int, node_two: int, linked: bool
|
||||||
|
) -> WlanLinkResponse:
|
||||||
|
request = WlanLinkRequest(
|
||||||
|
session_id=session_id,
|
||||||
|
wlan=wlan,
|
||||||
|
node_one=node_one,
|
||||||
|
node_two=node_two,
|
||||||
|
linked=linked,
|
||||||
|
)
|
||||||
|
return self.stub.WlanLink(request)
|
||||||
|
|
||||||
def connect(self) -> None:
|
def connect(self) -> None:
|
||||||
"""
|
"""
|
||||||
Open connection to server, must be closed manually.
|
Open connection to server, must be closed manually.
|
||||||
|
|
|
@ -6,7 +6,7 @@ import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from typing import Type
|
from typing import Type, TypeVar
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
from grpc import ServicerContext
|
from grpc import ServicerContext
|
||||||
|
@ -102,6 +102,8 @@ from core.api.grpc.wlan_pb2 import (
|
||||||
GetWlanConfigsResponse,
|
GetWlanConfigsResponse,
|
||||||
SetWlanConfigRequest,
|
SetWlanConfigRequest,
|
||||||
SetWlanConfigResponse,
|
SetWlanConfigResponse,
|
||||||
|
WlanLinkRequest,
|
||||||
|
WlanLinkResponse,
|
||||||
)
|
)
|
||||||
from core.emulator.coreemu import CoreEmu
|
from core.emulator.coreemu import CoreEmu
|
||||||
from core.emulator.data import LinkData
|
from core.emulator.data import LinkData
|
||||||
|
@ -110,11 +112,13 @@ from core.emulator.enumerations import EventTypes, LinkTypes, MessageFlags
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import Session
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||||
from core.nodes.base import CoreNodeBase, NodeBase
|
from core.nodes.base import CoreNode, CoreNodeBase, NodeBase
|
||||||
|
from core.nodes.network import WlanNode
|
||||||
from core.services.coreservices import ServiceManager
|
from core.services.coreservices import ServiceManager
|
||||||
|
|
||||||
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
|
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
|
||||||
_INTERFACE_REGEX = re.compile(r"veth(?P<node>[0-9a-fA-F]+)")
|
_INTERFACE_REGEX = re.compile(r"veth(?P<node>[0-9a-fA-F]+)")
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
|
@ -170,19 +174,34 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
def get_node(
|
def get_node(
|
||||||
self, session: Session, node_id: int, context: ServicerContext
|
self,
|
||||||
) -> NodeBase:
|
session: Session,
|
||||||
|
node_id: int,
|
||||||
|
context: ServicerContext,
|
||||||
|
node_class: Type[T],
|
||||||
|
) -> T:
|
||||||
"""
|
"""
|
||||||
Retrieve node given session and node id
|
Retrieve node given session and node id
|
||||||
|
|
||||||
:param session: session that has the node
|
:param session: session that has the node
|
||||||
:param node_id: node id
|
:param node_id: node id
|
||||||
:param context:
|
:param context: request
|
||||||
|
:param node_class: type of node we are expecting
|
||||||
:return: node object that satisfies. If node not found then raise an exception.
|
:return: node object that satisfies. If node not found then raise an exception.
|
||||||
:raises Exception: raises grpc exception when node does not exist
|
:raises Exception: raises grpc exception when node does not exist
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return session.get_node(node_id)
|
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:
|
except CoreError:
|
||||||
context.abort(grpc.StatusCode.NOT_FOUND, f"node {node_id} not found")
|
context.abort(grpc.StatusCode.NOT_FOUND, f"node {node_id} not found")
|
||||||
|
|
||||||
|
@ -261,7 +280,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
|
|
||||||
# config service configs
|
# config service configs
|
||||||
for config in request.config_service_configs:
|
for config in request.config_service_configs:
|
||||||
node = self.get_node(session, config.node_id, context)
|
node = self.get_node(session, config.node_id, context, CoreNode)
|
||||||
service = node.config_services[config.name]
|
service = node.config_services[config.name]
|
||||||
if config.config:
|
if config.config:
|
||||||
service.set_config(config.config)
|
service.set_config(config.config)
|
||||||
|
@ -678,7 +697,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
"""
|
"""
|
||||||
logging.debug("get node: %s", request)
|
logging.debug("get node: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, NodeBase)
|
||||||
interfaces = []
|
interfaces = []
|
||||||
for interface_id in node._netif:
|
for interface_id in node._netif:
|
||||||
interface = node._netif[interface_id]
|
interface = node._netif[interface_id]
|
||||||
|
@ -699,7 +718,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
"""
|
"""
|
||||||
logging.debug("edit node: %s", request)
|
logging.debug("edit node: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, NodeBase)
|
||||||
options = NodeOptions()
|
options = NodeOptions()
|
||||||
options.icon = request.icon
|
options.icon = request.icon
|
||||||
if request.HasField("position"):
|
if request.HasField("position"):
|
||||||
|
@ -751,7 +770,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
"""
|
"""
|
||||||
logging.debug("sending node command: %s", request)
|
logging.debug("sending node command: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, CoreNode)
|
||||||
try:
|
try:
|
||||||
output = node.cmd(request.command)
|
output = node.cmd(request.command)
|
||||||
except CoreCommandError as e:
|
except CoreCommandError as e:
|
||||||
|
@ -770,7 +789,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
"""
|
"""
|
||||||
logging.debug("getting node terminal: %s", request)
|
logging.debug("getting node terminal: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, CoreNode)
|
||||||
terminal = node.termcmdstring("/bin/bash")
|
terminal = node.termcmdstring("/bin/bash")
|
||||||
return core_pb2.GetNodeTerminalResponse(terminal=terminal)
|
return core_pb2.GetNodeTerminalResponse(terminal=terminal)
|
||||||
|
|
||||||
|
@ -786,7 +805,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
"""
|
"""
|
||||||
logging.debug("get node links: %s", request)
|
logging.debug("get node links: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, NodeBase)
|
||||||
links = get_links(node)
|
links = get_links(node)
|
||||||
return core_pb2.GetNodeLinksResponse(links=links)
|
return core_pb2.GetNodeLinksResponse(links=links)
|
||||||
|
|
||||||
|
@ -803,8 +822,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
logging.debug("add link: %s", request)
|
logging.debug("add link: %s", request)
|
||||||
# validate session and nodes
|
# validate session and nodes
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
self.get_node(session, request.link.node_one_id, context)
|
self.get_node(session, request.link.node_one_id, context, NodeBase)
|
||||||
self.get_node(session, request.link.node_two_id, context)
|
self.get_node(session, request.link.node_two_id, context, NodeBase)
|
||||||
|
|
||||||
node_one_id = request.link.node_one_id
|
node_one_id = request.link.node_one_id
|
||||||
node_two_id = request.link.node_two_id
|
node_two_id = request.link.node_two_id
|
||||||
|
@ -994,7 +1013,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
"""
|
"""
|
||||||
logging.debug("mobility action: %s", request)
|
logging.debug("mobility action: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, WlanNode)
|
||||||
result = True
|
result = True
|
||||||
if request.action == MobilityAction.START:
|
if request.action == MobilityAction.START:
|
||||||
node.mobility.start()
|
node.mobility.start()
|
||||||
|
@ -1121,7 +1140,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
"""
|
"""
|
||||||
logging.debug("get node service file: %s", request)
|
logging.debug("get node service file: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, CoreNode)
|
||||||
file_data = session.services.get_service_file(
|
file_data = session.services.get_service_file(
|
||||||
node, request.service, request.file
|
node, request.service, request.file
|
||||||
)
|
)
|
||||||
|
@ -1176,7 +1195,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
"""
|
"""
|
||||||
logging.debug("service action: %s", request)
|
logging.debug("service action: %s", request)
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, CoreNode)
|
||||||
service = None
|
service = None
|
||||||
for current_service in node.services:
|
for current_service in node.services:
|
||||||
if current_service.name == request.service:
|
if current_service.name == request.service:
|
||||||
|
@ -1265,7 +1284,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
wlan_config.node_id, BasicRangeModel.name, wlan_config.config
|
wlan_config.node_id, BasicRangeModel.name, wlan_config.config
|
||||||
)
|
)
|
||||||
if session.state == EventTypes.RUNTIME_STATE:
|
if session.state == EventTypes.RUNTIME_STATE:
|
||||||
node = self.get_node(session, wlan_config.node_id, context)
|
node = self.get_node(session, wlan_config.node_id, context, WlanNode)
|
||||||
node.updatemodel(wlan_config.config)
|
node.updatemodel(wlan_config.config)
|
||||||
return SetWlanConfigResponse(result=True)
|
return SetWlanConfigResponse(result=True)
|
||||||
|
|
||||||
|
@ -1546,7 +1565,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
:return: get node config service response
|
:return: get node config service response
|
||||||
"""
|
"""
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, CoreNode)
|
||||||
self.validate_service(request.name, context)
|
self.validate_service(request.name, context)
|
||||||
service = node.config_services.get(request.name)
|
service = node.config_services.get(request.name)
|
||||||
if service:
|
if service:
|
||||||
|
@ -1628,7 +1647,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
:return: get node config services response
|
:return: get node config services response
|
||||||
"""
|
"""
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, CoreNode)
|
||||||
services = node.config_services.keys()
|
services = node.config_services.keys()
|
||||||
return GetNodeConfigServicesResponse(services=services)
|
return GetNodeConfigServicesResponse(services=services)
|
||||||
|
|
||||||
|
@ -1643,7 +1662,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
:return: set node config service response
|
:return: set node config service response
|
||||||
"""
|
"""
|
||||||
session = self.get_session(request.session_id, context)
|
session = self.get_session(request.session_id, context)
|
||||||
node = self.get_node(session, request.node_id, context)
|
node = self.get_node(session, request.node_id, context, CoreNode)
|
||||||
self.validate_service(request.name, context)
|
self.validate_service(request.name, context)
|
||||||
service = node.config_services.get(request.name)
|
service = node.config_services.get(request.name)
|
||||||
if service:
|
if service:
|
||||||
|
@ -1684,3 +1703,35 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
||||||
if new_sessions:
|
if new_sessions:
|
||||||
new_session = new_sessions[0]
|
new_session = new_sessions[0]
|
||||||
return ExecuteScriptResponse(session_id=new_session)
|
return ExecuteScriptResponse(session_id=new_session)
|
||||||
|
|
||||||
|
def WlanLink(
|
||||||
|
self, request: WlanLinkRequest, context: ServicerContext
|
||||||
|
) -> WlanLinkResponse:
|
||||||
|
session = self.get_session(request.session_id, context)
|
||||||
|
wlan = self.get_node(session, request.wlan, context, WlanNode)
|
||||||
|
if not isinstance(wlan, WlanNode):
|
||||||
|
context.abort(
|
||||||
|
grpc.StatusCode.NOT_FOUND, f"wlan id {request.wlan} is not a wlan node"
|
||||||
|
)
|
||||||
|
if not isinstance(wlan.model, BasicRangeModel):
|
||||||
|
context.abort(
|
||||||
|
grpc.StatusCode.NOT_FOUND,
|
||||||
|
f"wlan node {request.wlan} does not using BasicRangeModel",
|
||||||
|
)
|
||||||
|
n1 = self.get_node(session, request.node_one, context, CoreNode)
|
||||||
|
n2 = self.get_node(session, request.node_two, context, CoreNode)
|
||||||
|
n1_netif, n2_netif = None, None
|
||||||
|
for net, netif1, netif2 in n1.commonnets(n2):
|
||||||
|
if net == wlan:
|
||||||
|
n1_netif = netif1
|
||||||
|
n2_netif = netif2
|
||||||
|
break
|
||||||
|
result = False
|
||||||
|
if n1_netif and n2_netif:
|
||||||
|
if request.linked:
|
||||||
|
wlan.link(n1_netif, n2_netif)
|
||||||
|
else:
|
||||||
|
wlan.unlink(n1_netif, n2_netif)
|
||||||
|
wlan.model.sendlinkmsg(n1_netif, n2_netif, unlink=not request.linked)
|
||||||
|
result = True
|
||||||
|
return WlanLinkResponse(result=result)
|
||||||
|
|
|
@ -509,11 +509,7 @@ class BasicRangeModel(WirelessModel):
|
||||||
:param unlink: unlink or not
|
:param unlink: unlink or not
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
if unlink:
|
message_type = MessageFlags.DELETE if unlink else MessageFlags.ADD
|
||||||
message_type = MessageFlags.DELETE
|
|
||||||
else:
|
|
||||||
message_type = MessageFlags.ADD
|
|
||||||
|
|
||||||
link_data = self.create_link_data(netif, netif2, message_type)
|
link_data = self.create_link_data(netif, netif2, message_type)
|
||||||
self.session.broadcast_link(link_data)
|
self.session.broadcast_link(link_data)
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,8 @@ service CoreApi {
|
||||||
}
|
}
|
||||||
rpc SetWlanConfig (wlan.SetWlanConfigRequest) returns (wlan.SetWlanConfigResponse) {
|
rpc SetWlanConfig (wlan.SetWlanConfigRequest) returns (wlan.SetWlanConfigResponse) {
|
||||||
}
|
}
|
||||||
|
rpc WlanLink (wlan.WlanLinkRequest) returns (wlan.WlanLinkResponse) {
|
||||||
|
}
|
||||||
|
|
||||||
// emane rpc
|
// emane rpc
|
||||||
rpc GetEmaneConfig (emane.GetEmaneConfigRequest) returns (emane.GetEmaneConfigResponse) {
|
rpc GetEmaneConfig (emane.GetEmaneConfigRequest) returns (emane.GetEmaneConfigResponse) {
|
||||||
|
|
|
@ -34,3 +34,15 @@ message SetWlanConfigRequest {
|
||||||
message SetWlanConfigResponse {
|
message SetWlanConfigResponse {
|
||||||
bool result = 1;
|
bool result = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message WlanLinkRequest {
|
||||||
|
int32 session_id = 1;
|
||||||
|
int32 wlan = 2;
|
||||||
|
int32 node_one = 3;
|
||||||
|
int32 node_two = 4;
|
||||||
|
bool linked = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WlanLinkResponse {
|
||||||
|
bool result = 1;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue