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", {}): 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 ]