Skip to content

Commit

Permalink
chore: refined load config interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
penglei0 committed Jul 31, 2024
1 parent 22b72f6 commit e3f9ab7
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 84 deletions.
69 changes: 50 additions & 19 deletions src/containernet/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,48 +77,79 @@ class TopologyConfig:
json_description: Optional[str] = field(default=None)


supported_config_keys = ["node", "topology"]


class INodeConfig(ABC):
@staticmethod
def load_node_config(yaml_config_file: str,
config_name: str) -> NodeConfig:
def is_supported_config_key(config_key: str):
return config_key in supported_config_keys

@staticmethod
def load_config_reference(yaml_config_file: str,
config_name: str, config_key: str):
if not INodeConfig.is_supported_config_key(config_key):
logging.error(
f"load_config_reference: key %s is not supported.",
config_key)
return None
if not os.path.exists(yaml_config_file):
logging.error(
f"load_node_config: file %s does not exist.",
f"load_config_reference: file %s does not exist.",
yaml_config_file)
return None
node_config = []
loaded_yaml_config = []
with open(yaml_config_file, 'r', encoding='utf-8') as stream:
try:
node_config = yaml.safe_load(stream)
loaded_yaml_config = yaml.safe_load(stream)
except yaml.YAMLError as exc:
logging.error(exc)
return None
if node_config is None or "node" not in node_config:
# check key 'config_key' in the yaml content
if loaded_yaml_config is None or config_key not in loaded_yaml_config:
logging.error(
f"load_node_config: node config is not defined in %s",
yaml_config_file)
f"load_config_reference: %s is not defined in %s",
config_key, yaml_config_file)
return None
loaded_config = None
# Find it by 'name' in `node_config`, for example "linear_network"
for topology in node_config['node']:
if topology['name'] == config_name:
loaded_node_config = topology
for conf in loaded_yaml_config[config_key]:
if conf['name'] == config_name:
loaded_config = conf
logging.info('load_config_reference: loaded %s', loaded_config)
break
logging.info('load_node_config: loaded %s', loaded_node_config)
return NodeConfig(**loaded_node_config)
if loaded_config is None:
logging.error(
f"load_config_reference: %s is not defined in %s",
config_name, yaml_config_file)
return None
if config_key == "node":
return NodeConfig(**loaded_config)
if config_key == "topology":
return TopologyConfig(**loaded_config)
return None

@staticmethod
def load_yaml_config(yaml_description: str):
def load_yaml_config(yaml_description: str, config_key: str):
# load it directly from the yaml_description or
# load it from another yaml file.
node_config = None
if not INodeConfig.is_supported_config_key(config_key):
logging.error(
f"load_yaml_config: key %s is not supported.",
config_key)
return None
config_data = None
is_load_from_file = ["config_file", "config_name"]
if all(key in yaml_description for key in is_load_from_file):
# load from the yaml file `config_file`
node_config = INodeConfig.load_node_config(
config_data = INodeConfig.load_config_reference(
yaml_description['config_file'],
yaml_description['config_name'])
yaml_description['config_name'], config_key)
else:
# load directly from the yaml_description
logging.info('load_yaml_config: %s', yaml_description)
node_config = NodeConfig(**yaml_description)
return node_config
if config_key == "node":
config_data = NodeConfig(**yaml_description)
if config_key == "topology":
config_data = TopologyConfig(**yaml_description)
return config_data
64 changes: 2 additions & 62 deletions src/containernet/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import logging
import os
import json
import yaml

from .config import (TopologyConfig, MatrixType)


Expand All @@ -28,10 +26,9 @@ class LinkAttr(IntEnum):
class ITopology(ABC):
def __init__(self, top: TopologyConfig) -> None:
self.all_mats = {}
self.top_config = None
self.adj_matrix = None
self.top_config = top
self.init_all_matrices()
self.init_all_mats()

@abstractmethod
def generate_adj_matrix(self, num_of_nodes: int):
Expand All @@ -49,7 +46,7 @@ def get_matrix(self, mat_type: MatrixType):
return None
return self.all_mats[mat_type]

def init_all_matrices(self):
def init_all_mats(self):
# init from json_description or array_description
if self.top_config.json_description is not None:
logging.info(
Expand All @@ -63,63 +60,6 @@ def init_all_matrices(self):
self.all_mats[MatrixType.ADJACENCY_MATRIX] = self.adj_matrix
self.generate_other_matrices(self.adj_matrix)

@staticmethod
def load_topology_config(yaml_config_file: str,
config_name: str) -> TopologyConfig:
'''
Load the topology configuration from a yaml file. The configuration
contains the following fields:
- name of the topology
- number of nodes
- topology type
- one of the following:
- array_description: the array description of the topology
- json_description: the json description of the topology;
if json_description is provided, need load the topology
from the json file.
'''
if not os.path.exists(yaml_config_file):
logging.error(
f"load_topology_config: file %s does not exist.",
yaml_config_file)
return None
topology_config = []
with open(yaml_config_file, 'r', encoding='utf-8') as stream:
try:
topology_config = yaml.safe_load(stream)
except yaml.YAMLError as exc:
logging.error(exc)
return None
if topology_config is None or "topology" not in topology_config:
logging.error(
f"load_topology_config: topology is not defined in %s",
yaml_config_file)
return None
# Find it by 'name' in `topology_config`, for example "linear_network"
for topology in topology_config['topology']:
if topology['name'] == config_name:
loaded_topology = topology
break
logging.info('load_topology_config: loaded %s', loaded_topology)
return TopologyConfig(**loaded_topology)

@staticmethod
def load_yaml_config(yaml_description: str):
# load it directly from the yaml_description or
# load it from another yaml file.
topology = None
is_load_from_file = ["config_file", "config_name"]
if all(key in yaml_description for key in is_load_from_file):
# load from the yaml file `config_file`
topology = ITopology.load_topology_config(
yaml_description['config_file'],
yaml_description['config_name'])
else:
# load directly from the yaml_description
logging.info('load_yaml_config: %s', yaml_description)
topology = TopologyConfig(**yaml_description)
return topology

def load_all_mats(self, json_file_path):
"""Load all matrices from the Json file.
Args:
Expand Down
5 changes: 2 additions & 3 deletions src/run_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
# from mininet.cli import CLI
from mininet.log import setLogLevel
from containernet.linear_topology import LinearTopology
from containernet.topology import ITopology
from containernet.network import Network
from containernet.config import (
INodeConfig, NodeConfig, TopologyConfig)
Expand Down Expand Up @@ -61,8 +60,8 @@ def load_config(test_case_yaml) -> Tuple[NodeConfig, TopologyConfig]:
if local_net_top_yaml is None or local_node_conf_yaml is None:
logging.error("Error: top_yaml or node_conf_yaml is None.")
return None, None
node_config = INodeConfig.load_yaml_config(local_node_conf_yaml)
top_config = ITopology.load_yaml_config(local_net_top_yaml)
node_config = INodeConfig.load_yaml_config(local_node_conf_yaml, 'node')
top_config = INodeConfig.load_yaml_config(local_net_top_yaml, 'topology')
if top_config is None or node_config is None:
logging.error("Error: topology/node configuration is None.")
return None, None
Expand Down

0 comments on commit e3f9ab7

Please sign in to comment.