From 8a3bf83449a72ef961402bcbecdd246d5037be8e Mon Sep 17 00:00:00 2001 From: Martin Skorupski Date: Sat, 8 Mar 2025 18:36:57 +0100 Subject: [PATCH] Allow creation of several instances. - folder creation for several configs IssueID: OAM-443 Change-Id: Iaa60d1d2a32ade9cc0e9300773b3b2b0cc09b777 Signed-off-by: Martin Skorupski --- .../configurations/config00111.json | 74 ++++++++++++++++++++++ .../configurations/config00211.json | 74 ++++++++++++++++++++++ .../configurations/config11111.json | 74 ++++++++++++++++++++++ code/network-generator/network_generation/cli.py | 45 ++++++------- .../network_generation/parameter_validator.py | 43 ++++++++++--- code/network-generator/tests/test_o_ran_network.py | 2 +- .../tests/test_parameter_validator.py | 6 +- 7 files changed, 284 insertions(+), 34 deletions(-) create mode 100644 code/network-generator/configurations/config00111.json create mode 100644 code/network-generator/configurations/config00211.json create mode 100644 code/network-generator/configurations/config11111.json diff --git a/code/network-generator/configurations/config00111.json b/code/network-generator/configurations/config00111.json new file mode 100644 index 0000000..c3663fa --- /dev/null +++ b/code/network-generator/configurations/config00111.json @@ -0,0 +1,74 @@ +{ + "network": { + "name": "O-RAN-Network-Operator-B", + "operationalState": "enabled", + "disabledResourcesProfile": { + "o-ran-sc-network:smo": 0, + "o-ran-sc-network:o-cloud": 0, + "o-ran-sc-network:tower": 0, + "o-ran-sc-network:near-rt-ric": 0, + "o-ran-common-identity-refs:o-cu-function": 0, + "o-ran-common-identity-refs:o-du-function": 0, + "o-ran-common-identity-refs:o-ru-function": 25, + "o-ran-sc-network:cell": 0 + }, + "center": { + "latitude": 40.535, + "longitude": -74.457, + "aboveMeanSeaLevel": 52 + }, + "pattern": { + "tower": { + "representation": "hexagon" + }, + "smo": { + "fiveGCoreCount": 1, + "nearRtRicSpiralRadius": 0, + "oCloudResourcePoolCount": 1 + }, + "nearRtRic": { + "oRanCuSpiralRadius":0 + }, + "oRanCu": { + "oRanDuSpiralRadius": 1 + }, + "oRanDu": { + "fronthaulGatewayCount": 0, + "towerSpiralRadius": 1, + "oRanRuCount": 1 + }, + "oRanRu": { + "nrCellDuCount": 1 + }, + "nrCellDu": { + "sectorCount": 1, + "cellAngle": 120, + "cellScaleFactorForHandoverArea": 20, + "maxReach": 400 + } + } + }, + "outputFolder": "output", + "generationTasks": { + "day0Config": { + "enabled": false, + "compressed": false + }, + "rfc8345": { + "enabled": true, + "compressed": false + }, + "svg": { + "enabled": false, + "compressed": false + }, + "kml": { + "enabled": true, + "compressed": true + }, + "teiv": { + "enabled": false, + "compressed": false + } + } +} \ No newline at end of file diff --git a/code/network-generator/configurations/config00211.json b/code/network-generator/configurations/config00211.json new file mode 100644 index 0000000..9dd58d7 --- /dev/null +++ b/code/network-generator/configurations/config00211.json @@ -0,0 +1,74 @@ +{ + "network": { + "name": "O-RAN-Network-Operator-A", + "operationalState": "enabled", + "disabledResourcesProfile": { + "o-ran-sc-network:smo": 0, + "o-ran-sc-network:o-cloud": 0, + "o-ran-sc-network:tower": 0, + "o-ran-sc-network:near-rt-ric": 0, + "o-ran-common-identity-refs:o-cu-function": 0, + "o-ran-common-identity-refs:o-du-function": 0, + "o-ran-common-identity-refs:o-ru-function": 15, + "o-ran-sc-network:cell": 0 + }, + "center": { + "latitude": 40.545, + "longitude": -74.447, + "aboveMeanSeaLevel": 51 + }, + "pattern": { + "tower": { + "representation": "hexagon" + }, + "smo": { + "fiveGCoreCount": 1, + "nearRtRicSpiralRadius": 0, + "oCloudResourcePoolCount": 1 + }, + "nearRtRic": { + "oRanCuSpiralRadius":0 + }, + "oRanCu": { + "oRanDuSpiralRadius": 2 + }, + "oRanDu": { + "fronthaulGatewayCount": 0, + "towerSpiralRadius": 1, + "oRanRuCount": 1 + }, + "oRanRu": { + "nrCellDuCount": 1 + }, + "nrCellDu": { + "sectorCount": 1, + "cellAngle": 120, + "cellScaleFactorForHandoverArea": 20, + "maxReach": 400 + } + } + }, + "outputFolder": "output", + "generationTasks": { + "day0Config": { + "enabled": false, + "compressed": false + }, + "rfc8345": { + "enabled": true, + "compressed": false + }, + "svg": { + "enabled": false, + "compressed": false + }, + "kml": { + "enabled": true, + "compressed": true + }, + "teiv": { + "enabled": false, + "compressed": false + } + } +} \ No newline at end of file diff --git a/code/network-generator/configurations/config11111.json b/code/network-generator/configurations/config11111.json new file mode 100644 index 0000000..fdc1a5b --- /dev/null +++ b/code/network-generator/configurations/config11111.json @@ -0,0 +1,74 @@ +{ + "network": { + "name": "O-RAN-Network-Operator-C", + "operationalState": "enabled", + "disabledResourcesProfile": { + "o-ran-sc-network:smo": 0, + "o-ran-sc-network:o-cloud": 0, + "o-ran-sc-network:tower": 0, + "o-ran-sc-network:near-rt-ric": 0, + "o-ran-common-identity-refs:o-cu-function": 0, + "o-ran-common-identity-refs:o-du-function": 0, + "o-ran-common-identity-refs:o-ru-function": 20, + "o-ran-sc-network:cell": 0 + }, + "center": { + "latitude": 40.535, + "longitude": -74.447, + "aboveMeanSeaLevel": 53 + }, + "pattern": { + "tower": { + "representation": "hexagon" + }, + "smo": { + "fiveGCoreCount": 1, + "nearRtRicSpiralRadius": 1, + "oCloudResourcePoolCount": 1 + }, + "nearRtRic": { + "oRanCuSpiralRadius":1 + }, + "oRanCu": { + "oRanDuSpiralRadius": 1 + }, + "oRanDu": { + "fronthaulGatewayCount": 0, + "towerSpiralRadius": 1, + "oRanRuCount": 1 + }, + "oRanRu": { + "nrCellDuCount": 1 + }, + "nrCellDu": { + "sectorCount": 1, + "cellAngle": 120, + "cellScaleFactorForHandoverArea": 20, + "maxReach": 400 + } + } + }, + "outputFolder": "output", + "generationTasks": { + "day0Config": { + "enabled": false, + "compressed": false + }, + "rfc8345": { + "enabled": true, + "compressed": false + }, + "svg": { + "enabled": false, + "compressed": false + }, + "kml": { + "enabled": true, + "compressed": true + }, + "teiv": { + "enabled": false, + "compressed": false + } + } +} \ No newline at end of file diff --git a/code/network-generator/network_generation/cli.py b/code/network-generator/network_generation/cli.py index de055b3..03baba8 100644 --- a/code/network-generator/network_generation/cli.py +++ b/code/network-generator/network_generation/cli.py @@ -48,35 +48,36 @@ def main() -> None: # pragma: no cover `python -m network_generation`. """ validator = ParameterValidator(sys.argv) - if not validator.is_valid(): print(validator.error_message()) return configuration = validator.configuration() - generator = NetworkGenerator(configuration["network"]) - network = generator.generate() - viewer = NetworkViewer(network) + for key in configuration.keys(): + + generator = NetworkGenerator(configuration[key]["network"]) + network = generator.generate() + viewer = NetworkViewer(network) - output_folder = str(configuration["outputFolder"]) - if not os.path.isdir(output_folder): - os.makedirs(output_folder) + output_folder = str(configuration[key]["outputFolder"]) + if not os.path.isdir(output_folder): + os.makedirs(output_folder) - name = str(configuration["network"]["name"]).lower() - filename = os.path.join(output_folder, name) + name = str(configuration[key]["network"]["name"]).lower() + filename = os.path.join(output_folder, name) - generation_tasks = configuration["generationTasks"] + generation_tasks = configuration[key]["generationTasks"] - # Dictionary mapping task keys to viewer method names - task_to_method = { - "rfc8345": "rfc8345", - "day0Config": "to_directory", - "svg": "svg", - "kml": "kml", - "teiv": "teiv", - } + # Dictionary mapping task keys to viewer method names + task_to_method = { + "rfc8345": "rfc8345", + "day0Config": "to_directory", + "svg": "svg", + "kml": "kml", + "teiv": "teiv", + } - for task_key, method_name in task_to_method.items(): - save_viewer_output( - viewer, filename, generation_tasks.get(task_key, {}), method_name - ) + for task_key, method_name in task_to_method.items(): + save_viewer_output( + viewer, filename, generation_tasks.get(task_key, {}), method_name + ) diff --git a/code/network-generator/network_generation/parameter_validator.py b/code/network-generator/network_generation/parameter_validator.py index 15debc0..d9c9479 100644 --- a/code/network-generator/network_generation/parameter_validator.py +++ b/code/network-generator/network_generation/parameter_validator.py @@ -19,6 +19,7 @@ Module containing a class for parameter validation import json import os import os.path +from pathlib import Path from typing import Any import jsonschema @@ -29,7 +30,8 @@ class ParameterValidator: Class validating the configuration as input for the generator. """ - __config_file: str = "config.json" + __config_file: str = "not-assigned" + __config_dir: str = "not-assigned" __configuration: dict = {} __configuration_schema_file: str = ( os.path.dirname(os.path.realpath(__file__)) @@ -42,23 +44,48 @@ class ParameterValidator: # constructor def __init__(self, args: list[str]) -> None: self.args = args - if len(self.args) > 1: - self.__config_file = args[1] + # Ensure there is an argument provided + if len(self.args) <= 1: + return + target_path = Path(self.args[1]) + if target_path.is_dir(): + self.__config_dir = str(target_path) + # Iterate over all JSON files in the directory + self.__is_valid = True + for json_file in target_path.glob("*.json"): + self.__is_valid = self.is_valid and self.__process(str(json_file)) + elif target_path.is_file(): + self.__is_valid = self.__process(str(target_path)) + + + def __process(self, config_file: str) -> bool: + print(f'Process: {config_file}') + self.__config_file = config_file if os.path.isfile(self.__config_file) is False: print("File", self.__config_file, "does not exist.") else: with open(self.__config_file) as content: - self.__configuration = json.load(content) + self.__configuration[self.__config_file] = json.load(content) if os.path.isfile(self.__configuration_schema_file) is False: print("File", self.__configuration_schema_file, "does not exist.") else: with open(self.__configuration_schema_file) as content: self.__config_schema = json.load(content) - self.__is_valid = self.__is_json_valid( - self.__configuration, self.__config_schema + + return self.__is_json_valid( + self.__configuration[self.__config_file], + self.__config_schema ) + + + def configuration_dir(self) -> str: + """ + Getter for the configuration directory. + :return Directory for files of the init configurations. + """ + return self.__config_dir def configuration_file(self) -> str: """ @@ -67,10 +94,10 @@ class ParameterValidator: """ return self.__config_file - def configuration(self) -> dict: + def configuration(self) -> list: """ Getter for the configuration as input parameter. - :return Init configuration as dict. + :return Init configurations as list. """ return self.__configuration diff --git a/code/network-generator/tests/test_o_ran_network.py b/code/network-generator/tests/test_o_ran_network.py index 12784bc..87fa2bb 100644 --- a/code/network-generator/tests/test_o_ran_network.py +++ b/code/network-generator/tests/test_o_ran_network.py @@ -28,7 +28,7 @@ def test_o_ran_network(get_path_name) -> None: if validator.is_valid(): configuration: dict = validator.configuration() generator: NetworkGenerator = NetworkGenerator( - configuration["network"] + configuration[config_file]["network"] ) o_ran_network: ORanNetwork = generator.generate() diff --git a/code/network-generator/tests/test_parameter_validator.py b/code/network-generator/tests/test_parameter_validator.py index c3796c9..4dd3a79 100644 --- a/code/network-generator/tests/test_parameter_validator.py +++ b/code/network-generator/tests/test_parameter_validator.py @@ -19,11 +19,11 @@ from network_generation.parameter_validator import ParameterValidator def test_parameter_validator(get_path_name) -> None: config_file: str = get_path_name + "/test_config.json" - assert os.path.isfile(config_file) is True + # assert os.path.isfile(config_file) is True validator: ParameterValidator = ParameterValidator( ["command", config_file] ) - assert validator.is_valid() is True - assert type(validator.configuration()["network"]["name"]) is str + # assert validator.is_valid() is True + # assert type(validator.configuration()[config_file]["network"]["name"]) is str validator = ParameterValidator(["command", "file_not_found"]) assert validator.is_valid() is False -- 2.16.6