updated start proto to return exception strings, updated grpc start session to exist early when a failure is found, updated coretk ui to not switch ui to running when start fails and display error dialog

This commit is contained in:
Blake Harnden 2019-12-20 15:11:34 -08:00
parent 5639aeab75
commit 6d68034177
8 changed files with 70 additions and 36 deletions

View file

@ -124,7 +124,10 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
session.add_hook(hook.state, hook.file, None, hook.data) session.add_hook(hook.state, hook.file, None, hook.data)
# create nodes # create nodes
grpcutils.create_nodes(session, request.nodes) _, exceptions = grpcutils.create_nodes(session, request.nodes)
if exceptions:
exceptions = [str(x) for x in exceptions]
return core_pb2.StartSessionResponse(result=False, exceptions=exceptions)
# emane configs # emane configs
config = session.emane.get_configs() config = session.emane.get_configs()
@ -156,14 +159,28 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
) )
# create links # create links
grpcutils.create_links(session, request.links) _, exceptions = grpcutils.create_links(session, request.links)
if exceptions:
exceptions = [str(x) for x in exceptions]
return core_pb2.StartSessionResponse(result=False, exceptions=exceptions)
# asymmetric links # asymmetric links
grpcutils.edit_links(session, request.asymmetric_links) _, exceptions = grpcutils.edit_links(session, request.asymmetric_links)
if exceptions:
exceptions = [str(x) for x in exceptions]
return core_pb2.StartSessionResponse(result=False, exceptions=exceptions)
# set to instantiation and start # set to instantiation and start
session.set_state(EventTypes.INSTANTIATION_STATE) session.set_state(EventTypes.INSTANTIATION_STATE)
session.instantiate()
# boot services
boot_exceptions = session.instantiate()
if boot_exceptions:
exceptions = []
for boot_exception in boot_exceptions:
for service_exception in boot_exception.args:
exceptions.append(str(service_exception))
return core_pb2.StartSessionResponse(result=False, exceptions=exceptions)
return core_pb2.StartSessionResponse(result=True) return core_pb2.StartSessionResponse(result=True)

View file

@ -635,7 +635,6 @@ class Session:
:return: created node :return: created node
:raises core.CoreError: when an invalid node type is given :raises core.CoreError: when an invalid node type is given
""" """
# validate node type, get class, or throw error # validate node type, get class, or throw error
if _cls is None: if _cls is None:
node_class = self.get_node_class(_type) node_class = self.get_node_class(_type)
@ -1450,17 +1449,19 @@ class Session:
return return
# boot node services and then start mobility # boot node services and then start mobility
self.boot_nodes() exceptions = self.boot_nodes()
self.mobility.startup() if not exceptions:
self.mobility.startup()
# notify listeners that instantiation is complete # notify listeners that instantiation is complete
event = EventData(event_type=EventTypes.INSTANTIATION_COMPLETE.value) event = EventData(event_type=EventTypes.INSTANTIATION_COMPLETE.value)
self.broadcast_event(event) self.broadcast_event(event)
# assume either all nodes have booted already, or there are some # assume either all nodes have booted already, or there are some
# nodes on slave servers that will be booted and those servers will # nodes on slave servers that will be booted and those servers will
# send a node status response message # send a node status response message
self.check_runtime() self.check_runtime()
return exceptions
def get_node_count(self): def get_node_count(self):
""" """
@ -1577,6 +1578,9 @@ class Session:
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
request flag. request flag.
:return: service boot exceptions
:rtype: list[core.services.coreservices.ServiceBootError]
""" """
with self._nodes_lock: with self._nodes_lock:
funcs = [] funcs = []
@ -1589,9 +1593,9 @@ class Session:
results, exceptions = utils.threadpool(funcs) results, exceptions = utils.threadpool(funcs)
total = time.monotonic() - start total = time.monotonic() - start
logging.debug("boot run time: %s", total) logging.debug("boot run time: %s", total)
if exceptions: if not exceptions:
raise CoreError(exceptions) self.update_control_interface_hosts()
self.update_control_interface_hosts() return exceptions
def get_control_net_prefixes(self): def get_control_net_prefixes(self):
""" """

View file

@ -6,6 +6,7 @@ import logging
import os import os
import time import time
from pathlib import Path from pathlib import Path
from tkinter import messagebox
import grpc import grpc
@ -476,21 +477,31 @@ class CoreClient:
file_configs, file_configs,
asymmetric_links, asymmetric_links,
) )
self.set_metadata()
process_time = time.perf_counter() - start
logging.debug( logging.debug(
"start session(%s), result: %s", self.session_id, response.result "start session(%s), result: %s", self.session_id, response.result
) )
self.app.statusbar.start_session_callback(process_time) process_time = time.perf_counter() - start
# display mobility players # stop progress bar and update status
for node_id, config in self.mobility_configs.items(): self.app.statusbar.progress_bar.stop()
canvas_node = self.canvas_nodes[node_id] message = f"Start ran for {process_time:.3f} seconds"
mobility_player = MobilityPlayer( self.app.statusbar.set_status(message)
self.app, self.app, canvas_node, config
) if response.result:
mobility_player.show() self.set_metadata()
self.mobility_players[node_id] = mobility_player self.app.toolbar.set_runtime()
# display mobility players
for node_id, config in self.mobility_configs.items():
canvas_node = self.canvas_nodes[node_id]
mobility_player = MobilityPlayer(
self.app, self.app, canvas_node, config
)
mobility_player.show()
self.mobility_players[node_id] = mobility_player
else:
message = "\n".join(response.exceptions)
messagebox.showerror("Start Error", message)
except grpc.RpcError as e: except grpc.RpcError as e:
show_grpc_error(e) show_grpc_error(e)

View file

@ -68,10 +68,9 @@ class StatusBar(ttk.Frame):
dialog = AlertsDialog(self.app, self.app) dialog = AlertsDialog(self.app, self.app)
dialog.show() dialog.show()
def start_session_callback(self, process_time): def set_status(self, message):
self.progress_bar.stop() self.statusvar.set(message)
self.statusvar.set(f"Session started in {process_time:.3f} seconds")
def stop_session_callback(self, cleanup_time): def stop_session_callback(self, cleanup_time):
self.progress_bar.stop() self.progress_bar.stop()
self.statusvar.set(f"Stopped session in {cleanup_time:.3f} seconds") self.statusvar.set(f"Stopped in {cleanup_time:.3f} seconds")

View file

@ -236,11 +236,12 @@ class Toolbar(ttk.Frame):
:return: nothing :return: nothing
""" """
self.app.canvas.hide_context() self.app.canvas.hide_context()
self.app.statusbar.core_alarms.clear()
self.app.statusbar.progress_bar.start(5) self.app.statusbar.progress_bar.start(5)
self.app.canvas.mode = GraphMode.SELECT self.app.canvas.mode = GraphMode.SELECT
thread = threading.Thread(target=self.app.core.start_session) thread = threading.Thread(target=self.app.core.start_session)
thread.start() thread.start()
def set_runtime(self):
self.runtime_frame.tkraise() self.runtime_frame.tkraise()
self.click_runtime_selection() self.click_runtime_selection()

View file

@ -458,7 +458,7 @@ class CoreServices:
""" """
Start all services on a node. Start all services on a node.
:param core.netns.vnode.LxcNode node: node to start services on :param core.nodes.base.CoreNode node: node to start services on
:return: nothing :return: nothing
""" """
boot_paths = ServiceDependencies(node.services).boot_paths() boot_paths = ServiceDependencies(node.services).boot_paths()
@ -468,7 +468,7 @@ class CoreServices:
funcs.append((self._start_boot_paths, args, {})) funcs.append((self._start_boot_paths, args, {}))
result, exceptions = utils.threadpool(funcs) result, exceptions = utils.threadpool(funcs)
if exceptions: if exceptions:
raise ServiceBootError(exceptions) raise ServiceBootError(*exceptions)
def _start_boot_paths(self, node, boot_path): def _start_boot_paths(self, node, boot_path):
""" """

View file

@ -8,7 +8,7 @@ from core import constants, utils
from core.errors import CoreCommandError from core.errors import CoreCommandError
from core.nodes import ipaddress from core.nodes import ipaddress
from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix
from core.services.coreservices import CoreService from core.services.coreservices import CoreService, ServiceMode
class UtilService(CoreService): class UtilService(CoreService):
@ -173,6 +173,7 @@ class SshService(UtilService):
startup = ("sh startsshd.sh",) startup = ("sh startsshd.sh",)
shutdown = ("killall sshd",) shutdown = ("killall sshd",)
validate = () validate = ()
validation_mode = ServiceMode.BLOCKING
@classmethod @classmethod
def generate_config(cls, node, filename): def generate_config(cls, node, filename):

View file

@ -155,6 +155,7 @@ message StartSessionRequest {
message StartSessionResponse { message StartSessionResponse {
bool result = 1; bool result = 1;
repeated string exceptions = 2;
} }
message StopSessionRequest { message StopSessionRequest {