Merge pull request #686 from mwhudson/no-netplan-crash
if netplan apply fails show an error rather than crashing the ui
This commit is contained in:
commit
95c20226fd
|
@ -55,6 +55,7 @@ class ErrorReportKind(enum.Enum):
|
|||
DISK_PROBE_FAIL = _("Disk probe failure")
|
||||
INSTALL_FAIL = _("Install failure")
|
||||
UI = _("Installer crash")
|
||||
NETWORK_FAIL = _("Network error")
|
||||
UNKNOWN = _("Unknown error")
|
||||
|
||||
|
||||
|
|
|
@ -14,11 +14,16 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from subiquitycore.async_helpers import schedule_task
|
||||
from subiquitycore.controllers.network import NetworkController
|
||||
|
||||
from subiquity.controller import SubiquityController
|
||||
from subiquity.controllers.error import ErrorReportKind
|
||||
|
||||
|
||||
log = logging.getLogger("subiquity.controllers.network")
|
||||
|
||||
|
||||
class NetworkController(NetworkController, SubiquityController):
|
||||
|
@ -42,6 +47,10 @@ class NetworkController(NetworkController, SubiquityController):
|
|||
},
|
||||
}
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
app.note_file_for_apport("NetplanConfig", self.netplan_path)
|
||||
|
||||
def load_autoinstall_data(self, data):
|
||||
self.ai_data = data
|
||||
|
||||
|
@ -74,6 +83,20 @@ class NetworkController(NetworkController, SubiquityController):
|
|||
return r
|
||||
return super().render_config()
|
||||
|
||||
async def _apply_config(self, silent):
|
||||
try:
|
||||
await super()._apply_config(silent)
|
||||
except asyncio.CancelledError:
|
||||
# asyncio.CancelledError is a subclass of Exception in
|
||||
# Python 3.6 (sadface)
|
||||
raise
|
||||
except Exception:
|
||||
log.exception("_apply_config failed")
|
||||
self.model.has_network = False
|
||||
self.app.make_apport_report(
|
||||
ErrorReportKind.NETWORK_FAIL, "applying network",
|
||||
interrupt=True)
|
||||
|
||||
def done(self):
|
||||
self.configured()
|
||||
super().done()
|
||||
|
|
|
@ -350,14 +350,14 @@ class Subiquity(Application):
|
|||
else:
|
||||
super().unhandled_input(key)
|
||||
|
||||
def debug_shell(self):
|
||||
def debug_shell(self, after_hook=None):
|
||||
|
||||
def _before():
|
||||
os.system("clear")
|
||||
print(DEBUG_SHELL_INTRO)
|
||||
|
||||
self.run_command_in_foreground(
|
||||
["bash"], before_hook=_before, cwd='/')
|
||||
["bash"], before_hook=_before, after_hook=after_hook, cwd='/')
|
||||
|
||||
def note_file_for_apport(self, key, path):
|
||||
self._apport_files.append((key, path))
|
||||
|
|
|
@ -69,6 +69,9 @@ Sorry, there was a problem examining the storage devices on this system.
|
|||
"""),
|
||||
ErrorReportKind.INSTALL_FAIL: _("""
|
||||
Sorry, there was a problem completing the installation.
|
||||
"""),
|
||||
ErrorReportKind.NETWORK_FAIL: _("""
|
||||
Sorry, there was a problem applying the network configuration.
|
||||
"""),
|
||||
ErrorReportKind.UI: _("""
|
||||
Sorry, the installer has restarted because of an error.
|
||||
|
@ -106,6 +109,10 @@ devices manually.
|
|||
You may be able to fix the issue by switching to a shell and
|
||||
reconfiguring the system's block devices manually.
|
||||
"""), ['debug_shell', 'continue']),
|
||||
ErrorReportKind.NETWORK_FAIL: (_("""
|
||||
You can continue with the installation but it will be assumed the network
|
||||
is not functional.
|
||||
"""), ['continue']),
|
||||
ErrorReportKind.INSTALL_FAIL: (_("""
|
||||
Do you want to try starting the installation again?
|
||||
"""), ['restart', 'close']),
|
||||
|
@ -241,7 +248,6 @@ class ErrorReportStretchy(Stretchy):
|
|||
|
||||
def debug_shell(self, sender):
|
||||
self.parent.remove_overlay()
|
||||
self.app.debug_shell()
|
||||
|
||||
def restart(self, sender):
|
||||
self.app.restart()
|
||||
|
|
|
@ -149,13 +149,16 @@ class NetworkController(BaseController):
|
|||
os.makedirs(netplan_dir)
|
||||
with open(netplan_path, 'w') as fp:
|
||||
fp.write(default_netplan)
|
||||
self.model.parse_netplan_configs(self.root)
|
||||
self.parse_netplan_configs()
|
||||
|
||||
self._watching = False
|
||||
self.network_event_receiver = SubiquityNetworkEventReceiver(self.model)
|
||||
self.network_event_receiver.add_default_route_watcher(
|
||||
self.route_watcher)
|
||||
|
||||
def parse_netplan_configs(self):
|
||||
self.model.parse_netplan_configs(self.root)
|
||||
|
||||
def route_watcher(self, routes):
|
||||
if routes:
|
||||
self.signal.emit_signal('network-change')
|
||||
|
@ -349,7 +352,7 @@ class NetworkController(BaseController):
|
|||
self.model.stringify_config(config),
|
||||
omode="w")
|
||||
|
||||
self.model.parse_netplan_configs(self.root)
|
||||
self.parse_netplan_configs()
|
||||
|
||||
async def _apply_config(self, silent):
|
||||
with self.context.child(
|
||||
|
@ -383,58 +386,60 @@ class NetworkController(BaseController):
|
|||
if not silent and self.view:
|
||||
self.view.show_apply_spinner()
|
||||
|
||||
def error(stage):
|
||||
if not silent and self.view:
|
||||
self.view.show_network_error(stage)
|
||||
try:
|
||||
def error(stage):
|
||||
if not silent and self.view:
|
||||
self.view.show_network_error(stage)
|
||||
|
||||
if self.opts.dry_run:
|
||||
delay = 1/self.app.scale_factor
|
||||
await arun_command(['sleep', str(delay)])
|
||||
if os.path.exists('/lib/netplan/generate'):
|
||||
# If netplan appears to be installed, run generate to at
|
||||
# least test that what we wrote is acceptable to netplan.
|
||||
await arun_command(
|
||||
['netplan', 'generate', '--root', self.root],
|
||||
check=True)
|
||||
else:
|
||||
if devs_to_down or devs_to_delete:
|
||||
if self.opts.dry_run:
|
||||
delay = 1/self.app.scale_factor
|
||||
await arun_command(['sleep', str(delay)])
|
||||
if os.path.exists('/lib/netplan/generate'):
|
||||
# If netplan appears to be installed, run generate to
|
||||
# at least test that what we wrote is acceptable to
|
||||
# netplan.
|
||||
await arun_command(
|
||||
['netplan', 'generate', '--root', self.root],
|
||||
check=True)
|
||||
else:
|
||||
if devs_to_down or devs_to_delete:
|
||||
try:
|
||||
await arun_command(
|
||||
['systemctl', 'mask', '--runtime',
|
||||
'systemd-networkd.service',
|
||||
'systemd-networkd.socket'],
|
||||
check=True)
|
||||
await arun_command(
|
||||
['systemctl', 'stop',
|
||||
'systemd-networkd.service',
|
||||
'systemd-networkd.socket'],
|
||||
check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
error("stop-networkd")
|
||||
raise
|
||||
if devs_to_down:
|
||||
await self._down_devs(devs_to_down)
|
||||
if devs_to_delete:
|
||||
await self._delete_devs(devs_to_delete)
|
||||
if devs_to_down or devs_to_delete:
|
||||
await arun_command(
|
||||
['systemctl', 'unmask', '--runtime',
|
||||
'systemd-networkd.service',
|
||||
'systemd-networkd.socket'],
|
||||
check=True)
|
||||
try:
|
||||
await arun_command(
|
||||
['systemctl', 'mask', '--runtime',
|
||||
'systemd-networkd.service',
|
||||
'systemd-networkd.socket'],
|
||||
check=True)
|
||||
await arun_command(
|
||||
['systemctl', 'stop',
|
||||
'systemd-networkd.service',
|
||||
'systemd-networkd.socket'],
|
||||
check=True)
|
||||
await arun_command(['netplan', 'apply'], check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
error("stop-networkd")
|
||||
error("apply")
|
||||
raise
|
||||
if devs_to_down:
|
||||
await self._down_devs(devs_to_down)
|
||||
if devs_to_delete:
|
||||
await self._delete_devs(devs_to_delete)
|
||||
if devs_to_down or devs_to_delete:
|
||||
await arun_command(
|
||||
['systemctl', 'unmask', '--runtime',
|
||||
'systemd-networkd.service',
|
||||
'systemd-networkd.socket'],
|
||||
check=True)
|
||||
try:
|
||||
await arun_command(['netplan', 'apply'], check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
error("apply")
|
||||
raise
|
||||
if devs_to_down or devs_to_delete:
|
||||
# It's probably running already, but just in case.
|
||||
await arun_command(
|
||||
['systemctl', 'start', 'systemd-networkd.socket'],
|
||||
check=False)
|
||||
|
||||
if not silent and self.view:
|
||||
self.view.hide_apply_spinner()
|
||||
if devs_to_down or devs_to_delete:
|
||||
# It's probably running already, but just in case.
|
||||
await arun_command(
|
||||
['systemctl', 'start', 'systemd-networkd.socket'],
|
||||
check=False)
|
||||
finally:
|
||||
if not silent and self.view:
|
||||
self.view.hide_apply_spinner()
|
||||
|
||||
if self.answers.get('accept-default', False):
|
||||
self.done()
|
||||
|
|
Loading…
Reference in New Issue