77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
|
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
|
||
|
]
|