Add entry point: `parse_network.py`

This commit is contained in:
Théophile Bastian 2020-03-12 11:40:17 +01:00
parent cae5e2244c
commit 915875ecf2
3 changed files with 139 additions and 0 deletions

76
lxc_net/parse_network.py Normal file
View File

@ -0,0 +1,76 @@
import yaml
import sys
from . import network, container
class YamlTopology:
""" Parse a YAML description of a network topology. The networks' links and domains
are contained in the `links` and `domains` attributes, but their `create` methods
are not called. """
class InvalidConfiguration(Exception):
def __init__(self, reason):
self.reason = reason
def __str__(self):
return "Bad topology configuration: {}".format(self.reason)
def __init__(self, path, conn):
self.path = path
self.conn = conn
self.domains = None
self.links = None
self._parse()
def _parse(self):
with open(self.path, "r") as handle:
topology = yaml.safe_load(handle)
if "links" not in topology:
raise self.InvalidConfiguration("links definition is mandatory")
link_descr = topology["links"]
self.links = []
dom_descr = {}
for link_conf in link_descr:
if "domains" not in link_conf:
raise self.InvalidConfiguration(
"a 'domains' attribute is mandatory for each link"
)
cur_link = network.Network(self.conn)
self.links.append(cur_link)
for dom in link_conf["domains"]:
if dom not in dom_descr:
dom_descr[dom] = {"links": []}
dom_descr[dom]["links"].append(cur_link)
for dom_conf_name in topology.get("domains", None):
if dom_conf_name not in dom_descr:
# Domain does not participate in any link: warn and ignore
print(
(
"WARNING: domain {} does not participate in any link. "
"Ignored."
).format(dom_conf_name),
file=sys.stderr,
)
continue
dom_conf = topology["domains"][dom_conf_name]
dom_descr[dom_conf_name]["enable_v4"] = dom_conf.get("enable_v4", True)
sorted_dom_names = sorted(list(dom_descr.keys()))
self.domains = [
container.Container(
self.conn,
dom_descr[dom]["links"],
enable_v4=dom_descr[dom].get("enable_v4", True),
)
for dom in sorted_dom_names
]

View File

@ -1,2 +1,3 @@
libvirt-python
jinja2
pyyaml

62
spawn_network.py Executable file
View File

@ -0,0 +1,62 @@
#!/usr/bin/env python3
from lxc_net import parse_network
import sys
import signal
import libvirt
import argparse
def parse_args():
parser = argparse.ArgumentParser(description="Spawns a network of LXC containers.")
parser.add_argument("topology", help="A YAML file defining the network topology")
args = parser.parse_args()
return args
def main():
args = parse_args()
received_sigint = False
def handle_sigint(signum, frame):
""" Called upon SIGINT (^C) """
nonlocal received_sigint
print(" >> Received SIGINT, stopping network...")
received_sigint = True
signal.signal(signal.SIGINT, handle_sigint)
conn = libvirt.open("lxc:///")
topology = parse_network.YamlTopology(args.topology, conn)
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()
print("Done.")
print(">> Spawning containers: ", end="")
sys.stdout.flush()
for c_dom in topology.domains:
if received_sigint:
return
print(c_dom.name, end="... ")
sys.stdout.flush()
c_dom.create()
print("Done.")
print("Network running. Press ^C to terminate.")
while not received_sigint: # Wait for SIGINT
signal.pause()
if __name__ == "__main__":
main()