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)
# 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
config = session.emane.get_configs()
@ -156,14 +159,28 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
)
# 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
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
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)

View file

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

View file

@ -6,6 +6,7 @@ import logging
import os
import time
from pathlib import Path
from tkinter import messagebox
import grpc
@ -476,21 +477,31 @@ class CoreClient:
file_configs,
asymmetric_links,
)
self.set_metadata()
process_time = time.perf_counter() - start
logging.debug(
"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
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
# stop progress bar and update status
self.app.statusbar.progress_bar.stop()
message = f"Start ran for {process_time:.3f} seconds"
self.app.statusbar.set_status(message)
if response.result:
self.set_metadata()
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:
show_grpc_error(e)

View file

@ -68,10 +68,9 @@ class StatusBar(ttk.Frame):
dialog = AlertsDialog(self.app, self.app)
dialog.show()
def start_session_callback(self, process_time):
self.progress_bar.stop()
self.statusvar.set(f"Session started in {process_time:.3f} seconds")
def set_status(self, message):
self.statusvar.set(message)
def stop_session_callback(self, cleanup_time):
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
"""
self.app.canvas.hide_context()
self.app.statusbar.core_alarms.clear()
self.app.statusbar.progress_bar.start(5)
self.app.canvas.mode = GraphMode.SELECT
thread = threading.Thread(target=self.app.core.start_session)
thread.start()
def set_runtime(self):
self.runtime_frame.tkraise()
self.click_runtime_selection()

View file

@ -458,7 +458,7 @@ class CoreServices:
"""
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
"""
boot_paths = ServiceDependencies(node.services).boot_paths()
@ -468,7 +468,7 @@ class CoreServices:
funcs.append((self._start_boot_paths, args, {}))
result, exceptions = utils.threadpool(funcs)
if exceptions:
raise ServiceBootError(exceptions)
raise ServiceBootError(*exceptions)
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.nodes import ipaddress
from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix
from core.services.coreservices import CoreService
from core.services.coreservices import CoreService, ServiceMode
class UtilService(CoreService):
@ -173,6 +173,7 @@ class SshService(UtilService):
startup = ("sh startsshd.sh",)
shutdown = ("killall sshd",)
validate = ()
validation_mode = ServiceMode.BLOCKING
@classmethod
def generate_config(cls, node, filename):

View file

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