grpc: added config service actions and update the gui to leverage them as the default for node context menus of running nodes

This commit is contained in:
Blake Harnden 2022-01-11 16:29:55 -08:00
parent 58b8d1cd24
commit 8f89488fd5
5 changed files with 88 additions and 4 deletions

View file

@ -810,6 +810,30 @@ class CoreGrpcClient:
response = self.stub.ServiceAction(request) response = self.stub.ServiceAction(request)
return response.result return response.result
def config_service_action(
self,
session_id: int,
node_id: int,
service: str,
action: wrappers.ServiceAction,
) -> bool:
"""
Send an action to a config service for a node.
:param session_id: session id
:param node_id: node id
:param service: config service name
:param action: action for service (start, stop, restart,
validate)
:return: True for success, False otherwise
:raises grpc.RpcError: when session or node doesn't exist
"""
request = ServiceActionRequest(
session_id=session_id, node_id=node_id, service=service, action=action.value
)
response = self.stub.ConfigServiceAction(request)
return response.result
def get_wlan_config( def get_wlan_config(
self, session_id: int, node_id: int self, session_id: int, node_id: int
) -> Dict[str, wrappers.ConfigOption]: ) -> Dict[str, wrappers.ConfigOption]:

View file

@ -72,6 +72,7 @@ from core.api.grpc.wlan_pb2 import (
WlanLinkRequest, WlanLinkRequest,
WlanLinkResponse, WlanLinkResponse,
) )
from core.configservice.base import ConfigServiceBootError
from core.emane.modelmanager import EmaneModelManager from core.emane.modelmanager import EmaneModelManager
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.data import InterfaceData, LinkData, LinkOptions from core.emulator.data import InterfaceData, LinkData, LinkOptions
@ -986,6 +987,48 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
return ServiceActionResponse(result=result) return ServiceActionResponse(result=result)
def ConfigServiceAction(
self, request: ServiceActionRequest, context: ServicerContext
) -> ServiceActionResponse:
"""
Take action whether to start, stop, restart, validate the config service or
none of the above.
:param request: service action request
:param context: context object
:return: service action response about status of action
"""
logger.debug("service action: %s", request)
session = self.get_session(request.session_id, context)
node = self.get_node(session, request.node_id, context, CoreNode)
service = node.config_services.get(request.service)
if not service:
context.abort(grpc.StatusCode.NOT_FOUND, "config service not found")
result = False
if request.action == ServiceAction.START:
try:
service.start()
result = True
except ConfigServiceBootError:
pass
elif request.action == ServiceAction.STOP:
service.stop()
result = True
elif request.action == ServiceAction.RESTART:
service.stop()
try:
service.start()
result = True
except ConfigServiceBootError:
pass
elif request.action == ServiceAction.VALIDATE:
try:
service.run_validation()
result = True
except ConfigServiceBootError:
pass
return ServiceActionResponse(result=result)
def GetWlanConfig( def GetWlanConfig(
self, request: GetWlanConfigRequest, context: ServicerContext self, request: GetWlanConfigRequest, context: ServicerContext
) -> GetWlanConfigResponse: ) -> GetWlanConfigResponse:

View file

@ -7,8 +7,7 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
import grpc import grpc
from PIL.ImageTk import PhotoImage from PIL.ImageTk import PhotoImage
from core.api.grpc.services_pb2 import ServiceAction from core.api.grpc.wrappers import Interface, Node, NodeType, ServiceAction
from core.api.grpc.wrappers import Interface, Node, NodeType
from core.gui import images from core.gui import images
from core.gui import nodeutils as nutils from core.gui import nodeutils as nutils
from core.gui import themes from core.gui import themes
@ -238,7 +237,7 @@ class CanvasNode:
) )
if nutils.is_container(self.core_node): if nutils.is_container(self.core_node):
services_menu = tk.Menu(self.context) services_menu = tk.Menu(self.context)
for service in sorted(self.core_node.services): for service in sorted(self.core_node.config_services):
service_menu = tk.Menu(services_menu) service_menu = tk.Menu(services_menu)
themes.style_menu(service_menu) themes.style_menu(service_menu)
start_func = functools.partial(self.start_service, service) start_func = functools.partial(self.start_service, service)
@ -463,7 +462,7 @@ class CanvasNode:
def _service_action(self, service: str, action: ServiceAction) -> None: def _service_action(self, service: str, action: ServiceAction) -> None:
session_id = self.app.core.session.id session_id = self.app.core.session.id
try: try:
result = self.app.core.client.service_action( result = self.app.core.client.config_service_action(
session_id, self.core_node.id, service, action session_id, self.core_node.id, service, action
) )
if not result: if not result:

View file

@ -87,6 +87,8 @@ service CoreApi {
} }
rpc GetNodeConfigService (configservices.GetNodeConfigServiceRequest) returns (configservices.GetNodeConfigServiceResponse) { rpc GetNodeConfigService (configservices.GetNodeConfigServiceRequest) returns (configservices.GetNodeConfigServiceResponse) {
} }
rpc ConfigServiceAction (services.ServiceActionRequest) returns (services.ServiceActionResponse) {
}
// wlan rpc // wlan rpc
rpc GetWlanConfig (wlan.GetWlanConfigRequest) returns (wlan.GetWlanConfigResponse) { rpc GetWlanConfig (wlan.GetWlanConfigRequest) returns (wlan.GetWlanConfigResponse) {

View file

@ -707,6 +707,22 @@ class TestGrpc:
# then # then
assert result is True assert result is True
def test_config_service_action(self, grpc_server: CoreGrpcServer):
# given
client = CoreGrpcClient()
session = grpc_server.coreemu.create_session()
node = session.add_node(CoreNode)
service_name = "DefaultRoute"
# then
with client.context_connect():
result = client.config_service_action(
session.id, node.id, service_name, ServiceAction.STOP
)
# then
assert result is True
def test_node_events(self, grpc_server: CoreGrpcServer): def test_node_events(self, grpc_server: CoreGrpcServer):
# given # given
client = CoreGrpcClient() client = CoreGrpcClient()