mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-10-29 09:12:37 +00:00
This commit introduces new functions for converting between YANG formatted files and legacy formats. The conversion processes adhere to RFC7951 for encoding YANG data. Key changes include: - Conversion of float and empty type representations. - Transformation of Span and SI lists xx_power_range into dictionaries. - Addition of necessary namespaces. - use of oopt-gnpy-libyang to enforce compliancy to yang models These utilities enable full compatibility with GNPy. Co-authored-by: Renato Ambrosone <renato.ambrosone@polito.it> Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com> Change-Id: Ia004113bca2b0631d1648564e5ccb60504fe80f8
244 lines
10 KiB
Python
244 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
# JSON files format conversion legacy <-> YANG
|
|
# Copyright (C) 2025 Telecom Infra Project and GNPy contributors
|
|
# see AUTHORS.rst for a list of contributors
|
|
|
|
"""
|
|
YANG formatted to legacy format conversion
|
|
==========================================
|
|
|
|
"""
|
|
|
|
from argparse import ArgumentParser
|
|
from pathlib import Path
|
|
from copy import deepcopy
|
|
import json
|
|
from typing import Dict
|
|
|
|
from gnpy.tools.yang_convert_utils import convert_degree, convert_back_degree, \
|
|
convert_delta_power_range, convert_back_delta_power_range, \
|
|
convert_dict, convert_back, \
|
|
remove_null_region_city, remove_union_that_fail, \
|
|
convert_design_band, convert_back_design_band, \
|
|
convert_none_to_empty, convert_empty_to_none, \
|
|
convert_loss_coeff_list, convert_back_loss_coeff_list, \
|
|
ELEMENTS_KEY, PATH_REQUEST_KEY, RESPONSE_KEY, SPECTRUM_KEY, EQPT_TYPES, EDFA_CONFIG_KEYS, SIM_PARAMS_KEYS, \
|
|
TOPO_NMSP, SERV_NMSP, EQPT_NMSP, SPECTRUM_NMSP, SIM_PARAMS_NMSP, EDFA_CONFIG_NMSP, RESP_NMSP, \
|
|
dump_data, add_missing_default_type_variety, \
|
|
remove_namespace_context, load_data, reorder_route_objects, reorder_lumped_losses_objects, \
|
|
reorder_raman_pumps, convert_raman_coef, convert_back_raman_coef, convert_raman_efficiency, \
|
|
convert_back_raman_efficiency, convert_nf_coef, convert_back_nf_coef, \
|
|
convert_nf_fit_coef, convert_back_nf_fit_coef
|
|
|
|
|
|
def legacy_to_yang(json_data: Dict) -> Dict:
|
|
"""Convert legacy format to GNPy YANG format.
|
|
|
|
This function adds the required namespace if not present and processes the input JSON data
|
|
based on its structure to convert it to the appropriate YANG format. There is no validation
|
|
of yang formatted data.
|
|
|
|
:param json_data: The input JSON data to convert.
|
|
:type json_data: Dict
|
|
:return: The converted JSON data in GNPy YANG format.
|
|
:rtype: Dict
|
|
"""
|
|
json_data = convert_none_to_empty(deepcopy(json_data))
|
|
|
|
# case of topology json
|
|
if ELEMENTS_KEY in json_data:
|
|
json_data = reorder_raman_pumps(json_data)
|
|
json_data = reorder_lumped_losses_objects(json_data)
|
|
json_data = remove_null_region_city(json_data)
|
|
json_data = convert_degree(json_data)
|
|
json_data = convert_design_band(json_data)
|
|
json_data = convert_loss_coeff_list(json_data)
|
|
json_data = convert_raman_coef(json_data)
|
|
json_data = {TOPO_NMSP: json_data}
|
|
elif TOPO_NMSP in json_data:
|
|
# then this is a new format topology json, ensure that there are no issues
|
|
json_data[TOPO_NMSP] = convert_degree(json_data[TOPO_NMSP])
|
|
json_data[TOPO_NMSP] = convert_design_band(json_data[TOPO_NMSP])
|
|
json_data[TOPO_NMSP] = convert_loss_coeff_list(json_data[TOPO_NMSP])
|
|
json_data[TOPO_NMSP] = remove_null_region_city(json_data[TOPO_NMSP])
|
|
|
|
# case of equipment json
|
|
elif any(k in json_data for k in EQPT_TYPES):
|
|
json_data = convert_raman_efficiency(json_data)
|
|
json_data = convert_delta_power_range(json_data)
|
|
json_data = convert_nf_coef(json_data)
|
|
json_data = add_missing_default_type_variety(json_data)
|
|
json_data = {EQPT_NMSP: json_data}
|
|
elif EQPT_NMSP in json_data:
|
|
# then this is already a new format topology json, ensure that there are no issues
|
|
json_data[EQPT_NMSP] = convert_raman_efficiency(json_data[EQPT_NMSP])
|
|
json_data[EQPT_NMSP] = convert_delta_power_range(json_data[EQPT_NMSP])
|
|
json_data[EQPT_NMSP] = convert_nf_coef(json_data[EQPT_NMSP])
|
|
json_data[EQPT_NMSP] = add_missing_default_type_variety(json_data[EQPT_NMSP])
|
|
|
|
# case of service json
|
|
elif PATH_REQUEST_KEY in json_data:
|
|
json_data = reorder_route_objects(json_data)
|
|
json_data = remove_union_that_fail(json_data)
|
|
json_data = {SERV_NMSP: json_data}
|
|
|
|
elif SERV_NMSP in json_data:
|
|
json_data[SERV_NMSP] = reorder_route_objects(json_data[SERV_NMSP])
|
|
json_data[SERV_NMSP] = remove_union_that_fail(json_data[SERV_NMSP])
|
|
|
|
# case of edfa_config json
|
|
elif any(k in json_data for k in EDFA_CONFIG_KEYS):
|
|
json_data = convert_nf_fit_coef(json_data)
|
|
json_data = {EDFA_CONFIG_NMSP: json_data}
|
|
|
|
elif EDFA_CONFIG_NMSP in json_data:
|
|
json_data[EDFA_CONFIG_NMSP] = convert_nf_fit_coef(json_data[EDFA_CONFIG_NMSP])
|
|
|
|
# case of spectrum json
|
|
elif SPECTRUM_KEY in json_data:
|
|
json_data = {SPECTRUM_NMSP: json_data[SPECTRUM_KEY]}
|
|
|
|
# case of sim_params json
|
|
elif any(k in json_data for k in SIM_PARAMS_KEYS):
|
|
json_data = {SIM_PARAMS_NMSP: json_data}
|
|
|
|
# case of response json
|
|
elif RESPONSE_KEY in json_data:
|
|
json_data = {RESP_NMSP: json_data}
|
|
|
|
elif any(k in json_data for k in [SPECTRUM_NMSP, SIM_PARAMS_NMSP, RESP_NMSP]):
|
|
# then this is a new format json, nothing to convert
|
|
pass
|
|
|
|
else:
|
|
raise ValueError('Unrecognized type of content (not topology, service or equipment)')
|
|
|
|
json_data = convert_dict(json_data)
|
|
return json_data
|
|
|
|
|
|
def yang_to_legacy(json_data: Dict) -> Dict:
|
|
"""Convert GNPy YANG format to legacy format.
|
|
|
|
This function processes the input JSON data to convert it from the new GNPy YANG format
|
|
back to the legacy format. It handles various types of content, including topology,
|
|
equipment, and service jsons, ensuring that the necessary conversions are applied.
|
|
The input data is validated with oopt-gnpy-libyang.
|
|
|
|
:param json_data: The input JSON data in GNPy YANG format to convert.
|
|
:type json_data: Dict
|
|
:return: The converted JSON data in legacy format.
|
|
:rtype: Dict
|
|
|
|
:raises ValueError: If the input JSON data does not match any recognized content type
|
|
(not topology, service, or equipment).
|
|
"""
|
|
# validate data compliance: make sure that this is yang formated data before validation.
|
|
load_data(json.dumps(legacy_to_yang(json_data)))
|
|
json_data = convert_empty_to_none(json_data)
|
|
json_data = convert_back(json_data)
|
|
|
|
# case of topology json
|
|
if ELEMENTS_KEY in json_data:
|
|
json_data = convert_back_degree(json_data)
|
|
json_data = convert_back_design_band(json_data)
|
|
json_data = convert_back_loss_coeff_list(json_data)
|
|
json_data = convert_back_raman_coef(json_data)
|
|
elif TOPO_NMSP in json_data:
|
|
json_data = convert_back_degree(json_data[TOPO_NMSP])
|
|
json_data = convert_back_design_band(json_data)
|
|
json_data = convert_back_loss_coeff_list(json_data)
|
|
json_data = convert_back_raman_coef(json_data)
|
|
|
|
# case of equipment json
|
|
elif any(k in json_data for k in EQPT_TYPES):
|
|
json_data = convert_back_delta_power_range(json_data)
|
|
json_data = convert_back_raman_efficiency(json_data)
|
|
json_data = convert_back_nf_coef(json_data)
|
|
json_data = remove_namespace_context(json_data, "gnpy-eqpt-config:")
|
|
elif EQPT_NMSP in json_data:
|
|
json_data[EQPT_NMSP] = convert_back_delta_power_range(json_data[EQPT_NMSP])
|
|
json_data[EQPT_NMSP] = convert_back_raman_efficiency(json_data[EQPT_NMSP])
|
|
json_data[EQPT_NMSP] = convert_back_nf_coef(json_data[EQPT_NMSP])
|
|
json_data = remove_namespace_context(json_data[EQPT_NMSP], "gnpy-eqpt-config:")
|
|
|
|
# case of EDFA config json
|
|
elif any(k in json_data for k in EDFA_CONFIG_KEYS):
|
|
json_data = convert_back_nf_fit_coef(json_data)
|
|
elif EDFA_CONFIG_NMSP in json_data:
|
|
json_data[EDFA_CONFIG_NMSP] = convert_back_nf_fit_coef(json_data[EDFA_CONFIG_NMSP])
|
|
|
|
# case of service json
|
|
elif SERV_NMSP in json_data:
|
|
json_data = json_data[SERV_NMSP]
|
|
|
|
# case of sim_params json
|
|
elif SIM_PARAMS_NMSP in json_data:
|
|
json_data = json_data[SIM_PARAMS_NMSP]
|
|
|
|
# case of spectrum json
|
|
elif SPECTRUM_NMSP in json_data:
|
|
json_data = {SPECTRUM_KEY: json_data[SPECTRUM_NMSP]}
|
|
|
|
# case of planning response json
|
|
elif RESP_NMSP in json_data:
|
|
json_data = json_data[RESP_NMSP]
|
|
elif any(k in json_data for k in SIM_PARAMS_KEYS + [SPECTRUM_KEY, RESPONSE_KEY, PATH_REQUEST_KEY]):
|
|
# then this is a legacy format json, nothing to convert
|
|
pass
|
|
else:
|
|
raise ValueError('Unrecognized type of content (not topology, service or equipment)')
|
|
return json_data
|
|
|
|
|
|
def main():
|
|
"""Conversion function
|
|
"""
|
|
parser = ArgumentParser()
|
|
parser.add_argument('--legacy-to-yang', nargs='?', type=Path,
|
|
help='convert file with this name into yangconformedname.json')
|
|
parser.add_argument('--yang-to-legacy', nargs='?', type=Path,
|
|
help='convert file with this name into gnpy'
|
|
+ ' using decimal instead of strings and null instead of [null]')
|
|
parser.add_argument('--validate', nargs='?', type=Path,
|
|
help='validate yang conformity')
|
|
parser.add_argument('-o', '--output', type=Path,
|
|
help='Stores into file with this name; default = GNPy_legacy_formatted-<file_name>.json or'
|
|
+ 'GNPy_yang_formatted-<file_name>.json')
|
|
args = parser.parse_args()
|
|
|
|
if not (args.legacy_to_yang or args.yang_to_legacy or args.validate):
|
|
parser.error("You must specify at least one of --legacy-to-yang, --yang-to-legacy, or --validate ")
|
|
|
|
output = None
|
|
converted = None
|
|
if args.validate:
|
|
with open(args.validate, 'r', encoding='utf-8') as f:
|
|
json_data = json.load(f)
|
|
load_data(json.dumps(json_data))
|
|
return 0
|
|
elif args.legacy_to_yang:
|
|
prefix = 'GNPy_yang_formatted-'
|
|
with open(args.legacy_to_yang, 'r', encoding='utf-8') as f:
|
|
json_data = json.load(f)
|
|
# note that dump_data automatically validate date against yang models
|
|
converted = dump_data(legacy_to_yang(json_data))
|
|
output = prefix + str(args.legacy_to_yang.name)
|
|
elif args.yang_to_legacy:
|
|
prefix = 'GNPy_legacy_formatted-'
|
|
with open(args.yang_to_legacy, 'r', encoding='utf-8') as f:
|
|
json_data = json.load(f)
|
|
converted = json.dumps(yang_to_legacy(json_data), indent=2, ensure_ascii=False)
|
|
output = prefix + str(args.yang_to_legacy.name)
|
|
if args.output:
|
|
output = args.output
|
|
with open(output, 'w', encoding='utf-8') as f:
|
|
f.write(converted)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|