introduce a helper for a restartable task

(there are going to be a few of these)
This commit is contained in:
Michael Hudson-Doyle 2019-12-11 15:24:48 +13:00
parent 2d1bd0011d
commit eb228ab7f3
5 changed files with 43 additions and 20 deletions

View File

@ -16,11 +16,43 @@
import asyncio
def _done(fut):
try:
fut.result()
except asyncio.CancelledError:
pass
def schedule_task(coro):
loop = asyncio.get_event_loop()
loop.call_soon(asyncio.ensure_future, coro)
if asyncio.iscoroutine(coro):
task = asyncio.Task(coro)
else:
task = coro
task.add_done_callback(_done)
loop.call_soon(asyncio.ensure_future, task)
return task
async def run_in_thread(func, *args):
loop = asyncio.get_event_loop()
return await loop.run_in_executor(None, func, *args)
class SingleInstanceTask:
def __init__(self, func):
self.func = func
self.task = None
async def start(self, *args, **kw):
if self.task is not None:
self.task.cancel()
try:
await self.task
except asyncio.CancelledError:
pass
self.task = schedule_task(self.func(*args, **kw))
def start_sync(self, *args, **kw):
return schedule_task(self.start(*args, **kw))

View File

@ -34,7 +34,7 @@ from subiquitycore.utils import (
from subiquitycore.file_util import write_file
from subiquitycore import netplan
from subiquity.async_helpers import schedule_task
from subiquity.async_helpers import SingleInstanceTask
log = logging.getLogger("subiquitycore.controller.network")
@ -129,7 +129,7 @@ class NetworkController(BaseController):
self.model = app.base_model.network
self.view = None
self.view_shown = False
self.apply_config_task = None
self.apply_config_task = SingleInstanceTask(self._apply_config)
if self.opts.dry_run:
self.root = os.path.abspath(".subiquity")
netplan_path = self.netplan_path
@ -282,7 +282,7 @@ class NetworkController(BaseController):
self.update_initial_configs()
self.view = NetworkView(self.model, self)
if not self.view_shown:
self.apply_config_start()
self.apply_config(silent=True)
self.view_shown = True
self.network_event_receiver.view = self.view
self.ui.set_body(self.view)
@ -298,18 +298,8 @@ class NetworkController(BaseController):
netplan_config_file_name = '00-snapd-config.yaml'
return os.path.join(self.root, 'etc/netplan', netplan_config_file_name)
def apply_config_start(self, silent=False):
schedule_task(self.apply_config(silent))
async def apply_config(self, silent):
if self.apply_config_task is not None:
self.apply_config_task.cancel()
try:
await self.apply_config_task
except asyncio.CancelledError:
pass
self.apply_config_task = asyncio.ensure_future(
self._apply_config(silent))
def apply_config(self, silent=False):
self.apply_config_task.start_sync(silent)
async def _down_devs(self, devs):
for dev in devs:

View File

@ -274,6 +274,7 @@ class AsyncioEventLoop(urwid.AsyncioEventLoop):
def _exception_handler(self, loop, context):
exc = context.get('exception')
if exc:
log.debug("_exception_handler %r", exc)
loop.stop()
if not isinstance(exc, urwid.ExitMainLoop):
# Store the exc_info so we can re-raise after the loop stops

View File

@ -136,7 +136,7 @@ class NetworkView(BaseView):
self.del_link(device)
for dev in touched_devs:
self.update_link(dev)
self.controller.apply_config_start()
self.controller.apply_config()
def _action(self, sender, action, device):
action, meth = action

View File

@ -250,7 +250,7 @@ class EditNetworkStretchy(Stretchy):
self.device.config['dhcp{v}'.format(v=self.ip_version)] = True
else:
log.debug("EditNetworkStretchy %s, disabled", self.ip_version)
self.parent.controller.apply_config_start()
self.parent.controller.apply_config()
self.parent.update_link(self.device)
self.parent.remove_overlay()
@ -307,7 +307,7 @@ class AddVlanStretchy(Stretchy):
dev = self.parent.controller.add_vlan(
self.device, self.form.vlan.value)
self.parent.new_link(dev)
self.parent.controller.apply_config_start()
self.parent.controller.apply_config()
def cancel(self, sender=None):
self.parent.remove_overlay()
@ -487,7 +487,7 @@ class BondStretchy(Stretchy):
for dev in touched_devices:
self.parent.update_link(dev)
self.parent.remove_overlay()
self.parent.controller.apply_config_start()
self.parent.controller.apply_config()
def cancel(self, sender=None):
self.parent.remove_overlay()