diff --git a/lxc_net/network.py b/lxc_net/network.py index 786c501..2ea1612 100644 --- a/lxc_net/network.py +++ b/lxc_net/network.py @@ -4,6 +4,8 @@ from . import settings from . import util from .jinja_template import JinjaTemplate +import asyncio + class Network(util.LibvirtObject): class AlreadyExists(Exception): @@ -40,6 +42,11 @@ class Network(util.LibvirtObject): self.lxc_network = self.conn.networkCreateXML(xml) + async def async_create(self): + """ Same as `create`, asyncio-enabled """ + executor_create = util.run_in_executor(self.create) + await executor_create() + def cleanup(self): if self.lxc_network: self.lxc_network.destroy() diff --git a/lxc_net/util.py b/lxc_net/util.py index 6d32f11..91056d6 100644 --- a/lxc_net/util.py +++ b/lxc_net/util.py @@ -5,6 +5,8 @@ import uuid import subprocess import sys +import asyncio +import functools class NumberedClass: @@ -136,3 +138,14 @@ def run_cmd_retry(command, *args, **kwargs): print("Command failed. Try again:", file=sys.stderr) rc = subprocess.run(command, *args, **kwargs) return rc + + +def run_in_executor(f): + """ Decorator: transforms a blocking function into an awaitable one """ + + @functools.wraps(f) + def inner(*args, **kwargs): + loop = asyncio.get_running_loop() + return loop.run_in_executor(None, functools.partial(f, *args, **kwargs)) + + return inner diff --git a/spawn_network.py b/spawn_network.py index aad7ec2..0ca93b2 100755 --- a/spawn_network.py +++ b/spawn_network.py @@ -5,6 +5,7 @@ import sys import signal import libvirt import argparse +import asyncio def parse_args(): @@ -15,6 +16,18 @@ def parse_args(): return args +async def spawn_network(link): + await link.async_create() + print(link.name, end="... ") + sys.stdout.flush() + + +async def spawn_networks(links): + link_tasks = [asyncio.create_task(spawn_network(link)) for link in links] + for link_task in link_tasks: + await link_task + + def main(): args = parse_args() @@ -35,12 +48,7 @@ def main(): print(">> Spawning networks: ", end="") sys.stdout.flush() - for link in topology.links: - if received_sigint: - return - print(link.name, end="... ") - sys.stdout.flush() - link.create() + asyncio.run(spawn_networks(topology.links)) print("Done.") print(">> Spawning containers: ", end="")