diff --git a/subiquity/client/controllers/network.py b/subiquity/client/controllers/network.py index b1ea396c..23542b0b 100644 --- a/subiquity/client/controllers/network.py +++ b/subiquity/client/controllers/network.py @@ -19,6 +19,8 @@ import shutil import tempfile from typing import List, Optional +from aiohttp import web + from subiquitycore.controllers.network import NetworkAnswersMixin from subiquitycore.models.network import ( BondConfig, @@ -30,6 +32,7 @@ from subiquitycore.ui.views.network import NetworkView from subiquity.client.controller import SubiquityTuiController from subiquity.common.api.server import make_server_at_path from subiquity.common.apidef import LinkAction, NetEventAPI +from subiquity.common.types import ErrorReportKind log = logging.getLogger('subiquity.client.controllers.network') @@ -42,6 +45,19 @@ class NetworkController(SubiquityTuiController, NetworkAnswersMixin): super().__init__(app) self.view = None + @web.middleware + async def middleware(self, request, handler): + resp = await handler(request) + if resp.get('exception'): + exc = resp['exception'] + log.debug( + 'request to {} crashed'.format(request.raw_path), exc_info=exc) + self.app.make_apport_report( + ErrorReportKind.NETWORK_CLIENT_FAIL, + "request to {}".format(request.raw_path), + exc=exc, interrupt=True) + return resp + async def update_link_POST(self, act: LinkAction, info: NetDevInfo) -> None: if self.view is None: @@ -73,7 +89,7 @@ class NetworkController(SubiquityTuiController, NetworkAnswersMixin): self.tdir = tempfile.mkdtemp() self.sock_path = os.path.join(self.tdir, 'socket') self.site = await make_server_at_path( - self.sock_path, NetEventAPI, self) + self.sock_path, NetEventAPI, self, middlewares=[self.middleware]) await self.endpoint.subscription.PUT(self.sock_path) async def unsubscribe(self): diff --git a/subiquity/common/api/server.py b/subiquity/common/api/server.py index 9abd7c7a..c8389141 100644 --- a/subiquity/common/api/server.py +++ b/subiquity/common/api/server.py @@ -168,8 +168,8 @@ def bind(router, endpoint, controller, serializer=None, _depth=None): handler=_make_handler(controller, v, impl, serializer)) -async def make_server_at_path(socket_path, endpoint, controller): - app = web.Application() +async def make_server_at_path(socket_path, endpoint, controller, **kw): + app = web.Application(**kw) bind(app.router, endpoint, controller) runner = web.AppRunner(app) await runner.setup() diff --git a/subiquity/common/types.py b/subiquity/common/types.py index 0b689424..e4511d91 100644 --- a/subiquity/common/types.py +++ b/subiquity/common/types.py @@ -39,6 +39,7 @@ class ErrorReportKind(enum.Enum): INSTALL_FAIL = _("Install failure") UI = _("Installer crash") NETWORK_FAIL = _("Network error") + NETWORK_CLIENT_FAIL = _("Network client error") SERVER_REQUEST_FAIL = _("Server request failure") UNKNOWN = _("Unknown error") diff --git a/subiquity/server/controllers/network.py b/subiquity/server/controllers/network.py index 5219dadb..e58c162c 100644 --- a/subiquity/server/controllers/network.py +++ b/subiquity/server/controllers/network.py @@ -184,8 +184,7 @@ class NetworkController(BaseNetworkController, SubiquityController): log.exception("_apply_config failed") self.model.has_network = False self.app.make_apport_report( - ErrorReportKind.NETWORK_FAIL, "applying network", - interrupt=True) + ErrorReportKind.NETWORK_FAIL, "applying network") if not self.interactive(): raise @@ -239,7 +238,10 @@ class NetworkController(BaseNetworkController, SubiquityController): if conn.closed: log.debug('closed') return - await getattr(client, meth_name).POST(*args) + try: + await getattr(client, meth_name).POST(*args) + except aiohttp.ClientError: + log.exception("call to %s on %s failed", meth_name, conn.path) def _call_clients(self, meth_name, *args): for client, conn, lock in self.clients.values():