mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-11-03 19:47:46 +00:00
@@ -25,7 +25,7 @@ from gnpy.core.service_sheet import convert_service_sheet, Request_element, Elem
|
|||||||
from gnpy.core.utils import load_json
|
from gnpy.core.utils import load_json
|
||||||
from gnpy.core.network import load_network, build_network, set_roadm_loss, save_network
|
from gnpy.core.network import load_network, build_network, set_roadm_loss, save_network
|
||||||
from gnpy.core.equipment import load_equipment, trx_mode_params, automatic_nch, automatic_spacing
|
from gnpy.core.equipment import load_equipment, trx_mode_params, automatic_nch, automatic_spacing
|
||||||
from gnpy.core.elements import Transceiver, Roadm, Edfa, Fused
|
from gnpy.core.elements import Transceiver, Roadm, Edfa, Fused, Fiber
|
||||||
from gnpy.core.utils import db2lin, lin2db
|
from gnpy.core.utils import db2lin, lin2db
|
||||||
from gnpy.core.request import (Path_request, Result_element, compute_constrained_path,
|
from gnpy.core.request import (Path_request, Result_element, compute_constrained_path,
|
||||||
propagate, jsontocsv, Disjunction, compute_path_dsjctn, requests_aggregation,
|
propagate, jsontocsv, Disjunction, compute_path_dsjctn, requests_aggregation,
|
||||||
@@ -44,7 +44,7 @@ parser.add_argument('network_filename', nargs='?', type = Path, default= Path(__
|
|||||||
parser.add_argument('service_filename', nargs='?', type = Path, default= Path(__file__).parent / 'meshTopologyExampleV2.xls')
|
parser.add_argument('service_filename', nargs='?', type = Path, default= Path(__file__).parent / 'meshTopologyExampleV2.xls')
|
||||||
parser.add_argument('eqpt_filename', nargs='?', type = Path, default=Path(__file__).parent / 'eqpt_config.json')
|
parser.add_argument('eqpt_filename', nargs='?', type = Path, default=Path(__file__).parent / 'eqpt_config.json')
|
||||||
parser.add_argument('-v', '--verbose', action='count', default=0, help='increases verbosity for each occurence')
|
parser.add_argument('-v', '--verbose', action='count', default=0, help='increases verbosity for each occurence')
|
||||||
parser.add_argument('-o', '--output')
|
parser.add_argument('-o', '--output', type = Path)
|
||||||
|
|
||||||
|
|
||||||
def requests_from_json(json_data,equipment):
|
def requests_from_json(json_data,equipment):
|
||||||
@@ -226,7 +226,9 @@ def correct_route_list(network, pathreqlist):
|
|||||||
# prepares the format of route list of nodes to be consistant
|
# prepares the format of route list of nodes to be consistant
|
||||||
# remove wrong names, remove endpoints
|
# remove wrong names, remove endpoints
|
||||||
# also correct source and destination
|
# also correct source and destination
|
||||||
anytype = [n.uid for n in network.nodes() if not isinstance(n, Transceiver)]
|
anytype = [n.uid for n in network.nodes() if not isinstance(n, Transceiver) and not isinstance(n, Fiber)]
|
||||||
|
# TODO there is a problem of identification of fibers in case of parallel fibers bitween two adjacent roadms
|
||||||
|
# so fiber constraint is not supported
|
||||||
transponders = [n.uid for n in network.nodes() if isinstance(n, Transceiver)]
|
transponders = [n.uid for n in network.nodes() if isinstance(n, Transceiver)]
|
||||||
for pathreq in pathreqlist:
|
for pathreq in pathreqlist:
|
||||||
for i,n_id in enumerate(pathreq.nodes_list):
|
for i,n_id in enumerate(pathreq.nodes_list):
|
||||||
@@ -249,7 +251,6 @@ def correct_route_list(network, pathreqlist):
|
|||||||
msg = f'could not find node : {n_id} in network topology. Strict constraint can not be applied.'
|
msg = f'could not find node : {n_id} in network topology. Strict constraint can not be applied.'
|
||||||
logger.critical(msg)
|
logger.critical(msg)
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
if pathreq.source not in transponders:
|
if pathreq.source not in transponders:
|
||||||
msg = f'Request: {pathreq.request_id}: could not find transponder source : {pathreq.source}.'
|
msg = f'Request: {pathreq.request_id}: could not find transponder source : {pathreq.source}.'
|
||||||
logger.critical(msg)
|
logger.critical(msg)
|
||||||
@@ -363,9 +364,10 @@ if __name__ == '__main__':
|
|||||||
for i,p in enumerate(propagatedpths):
|
for i,p in enumerate(propagatedpths):
|
||||||
result.append(Result_element(rqs[i],p))
|
result.append(Result_element(rqs[i],p))
|
||||||
temp = path_result_json(result)
|
temp = path_result_json(result)
|
||||||
with open(args.output, 'w', encoding='utf-8') as f:
|
fnamecsv = f'{str(args.output)[0:len(str(args.output))-len(str(args.output.suffix))]}.csv'
|
||||||
|
fnamejson = f'{str(args.output)[0:len(str(args.output))-len(str(args.output.suffix))]}.json'
|
||||||
|
with open(fnamejson, 'w', encoding='utf-8') as f:
|
||||||
f.write(dumps(path_result_json(result), indent=2, ensure_ascii=False))
|
f.write(dumps(path_result_json(result), indent=2, ensure_ascii=False))
|
||||||
fnamecsv = next(s for s in args.output.split('.')) + '.csv'
|
|
||||||
with open(fnamecsv,"w", encoding='utf-8') as fcsv :
|
with open(fnamecsv,"w", encoding='utf-8') as fcsv :
|
||||||
jsontocsv(temp,equipment,fcsv)
|
jsontocsv(temp,equipment,fcsv)
|
||||||
|
|
||||||
|
|||||||
@@ -285,10 +285,15 @@ def eqpt_connection_by_city(city_name):
|
|||||||
# Then len(other_cities) == 2
|
# Then len(other_cities) == 2
|
||||||
direction = ['ingress', 'egress']
|
direction = ['ingress', 'egress']
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
|
try:
|
||||||
from_ = fiber_link(other_cities[i], city_name)
|
from_ = fiber_link(other_cities[i], city_name)
|
||||||
in_ = eqpt_in_city_to_city(city_name, other_cities[0],direction[i])
|
in_ = eqpt_in_city_to_city(city_name, other_cities[0],direction[i])
|
||||||
to_ = fiber_link(city_name, other_cities[1-i])
|
to_ = fiber_link(city_name, other_cities[1-i])
|
||||||
subdata += connect_eqpt(from_, in_, to_)
|
subdata += connect_eqpt(from_, in_, to_)
|
||||||
|
except IndexError:
|
||||||
|
msg = f'In {__name__} eqpt_connection_by_city:\n\t{city_name} is not properly connected'
|
||||||
|
print(msg)
|
||||||
|
exit(1)
|
||||||
elif nodes_by_city[city_name].node_type.lower() == 'roadm':
|
elif nodes_by_city[city_name].node_type.lower() == 'roadm':
|
||||||
for other_city in other_cities:
|
for other_city in other_cities:
|
||||||
from_ = f'roadm {city_name}'
|
from_ = f'roadm {city_name}'
|
||||||
|
|||||||
@@ -64,7 +64,12 @@ def network_from_json(json_data, equipment):
|
|||||||
|
|
||||||
for cx in json_data['connections']:
|
for cx in json_data['connections']:
|
||||||
from_node, to_node = cx['from_node'], cx['to_node']
|
from_node, to_node = cx['from_node'], cx['to_node']
|
||||||
|
try:
|
||||||
g.add_edge(nodes[from_node], nodes[to_node])
|
g.add_edge(nodes[from_node], nodes[to_node])
|
||||||
|
except KeyError:
|
||||||
|
msg = f'In {__name__} network_from_json function:\n\tcan not find {from_node} or {to_node} defined in {cx}'
|
||||||
|
print(msg)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
return g
|
return g
|
||||||
|
|
||||||
@@ -171,7 +176,13 @@ def target_power(dp_from_gain, network, node, equipment): #get_fiber_dp
|
|||||||
def prev_node_generator(network, node):
|
def prev_node_generator(network, node):
|
||||||
"""fused spans interest:
|
"""fused spans interest:
|
||||||
iterate over all predecessors while they are Fused or Fiber type"""
|
iterate over all predecessors while they are Fused or Fiber type"""
|
||||||
|
try:
|
||||||
prev_node = next(n for n in network.predecessors(node))
|
prev_node = next(n for n in network.predecessors(node))
|
||||||
|
except StopIteration:
|
||||||
|
msg = f'In {__name__} prev_node_generator function:\n\t{node.uid} is not properly connected, please check network topology'
|
||||||
|
print(msg)
|
||||||
|
logger.critical(msg)
|
||||||
|
exit(1)
|
||||||
# yield and re-iterate
|
# yield and re-iterate
|
||||||
if isinstance(prev_node, Fused) or isinstance(node, Fused):
|
if isinstance(prev_node, Fused) or isinstance(node, Fused):
|
||||||
yield prev_node
|
yield prev_node
|
||||||
@@ -182,7 +193,11 @@ def prev_node_generator(network, node):
|
|||||||
def next_node_generator(network, node):
|
def next_node_generator(network, node):
|
||||||
"""fused spans interest:
|
"""fused spans interest:
|
||||||
iterate over all successors while they are Fused or Fiber type"""
|
iterate over all successors while they are Fused or Fiber type"""
|
||||||
|
try:
|
||||||
next_node = next(n for n in network.successors(node))
|
next_node = next(n for n in network.successors(node))
|
||||||
|
except StopIteration:
|
||||||
|
print(f'In {__name__} next_node_generator function:\n\t{node.uid} is not properly connected, please check network topology')
|
||||||
|
exit(1)
|
||||||
# yield and re-iterate
|
# yield and re-iterate
|
||||||
if isinstance(next_node, Fused) or isinstance(node, Fused):
|
if isinstance(next_node, Fused) or isinstance(node, Fused):
|
||||||
yield next_node
|
yield next_node
|
||||||
@@ -334,7 +349,8 @@ def split_fiber(network, fiber, bounds, target_length, equipment):
|
|||||||
next_node = next(network.successors(fiber))
|
next_node = next(network.successors(fiber))
|
||||||
prev_node = next(network.predecessors(fiber))
|
prev_node = next(network.predecessors(fiber))
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
print(f'{repr(fiber)} is not properly connected, please check network topology')
|
|
||||||
|
print(f'In {__name__} split_fiber function:\n\t{fiber.uid} is not properly connected, please check network topology')
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
network.remove_node(fiber)
|
network.remove_node(fiber)
|
||||||
@@ -367,7 +383,13 @@ def add_fiber_padding(network, fibers, padding):
|
|||||||
if isinstance(fiber, Fiber))"""
|
if isinstance(fiber, Fiber))"""
|
||||||
for fiber in fibers:
|
for fiber in fibers:
|
||||||
this_span_loss = span_loss(network, fiber)
|
this_span_loss = span_loss(network, fiber)
|
||||||
|
try:
|
||||||
next_node = next(network.successors(fiber))
|
next_node = next(network.successors(fiber))
|
||||||
|
except StopIteration:
|
||||||
|
msg = f'In {__name__} add_fiber_padding function:\n\t{fiber.uid} is not properly connected, please check network topology'
|
||||||
|
print(msg)
|
||||||
|
logger.critical(msg)
|
||||||
|
exit(1)
|
||||||
if this_span_loss < padding and not (isinstance(next_node, Fused)):
|
if this_span_loss < padding and not (isinstance(next_node, Fused)):
|
||||||
#add a padding att_in at the input of the 1st fiber:
|
#add a padding att_in at the input of the 1st fiber:
|
||||||
#address the case when several fibers are spliced together
|
#address the case when several fibers are spliced together
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ def compute_constrained_path(network, req):
|
|||||||
destination = next(el for el in trx if el.uid == req.destination)
|
destination = next(el for el in trx if el.uid == req.destination)
|
||||||
nodes_list = []
|
nodes_list = []
|
||||||
for n in req.nodes_list :
|
for n in req.nodes_list :
|
||||||
|
# for debug excel print(n)
|
||||||
nodes_list.append(next(el for el in anytypenode if el.uid == n))
|
nodes_list.append(next(el for el in anytypenode if el.uid == n))
|
||||||
# nodes_list contains at least the destination
|
# nodes_list contains at least the destination
|
||||||
if nodes_list is None :
|
if nodes_list is None :
|
||||||
@@ -297,7 +298,7 @@ def compute_constrained_path(network, req):
|
|||||||
total_path = []
|
total_path = []
|
||||||
else :
|
else :
|
||||||
all_simp_pths = list(all_simple_paths(network,source=source,\
|
all_simp_pths = list(all_simple_paths(network,source=source,\
|
||||||
target=destination))
|
target=destination, cutoff=120))
|
||||||
candidate = []
|
candidate = []
|
||||||
for p in all_simp_pths :
|
for p in all_simp_pths :
|
||||||
if ispart(nodes_list, p) :
|
if ispart(nodes_list, p) :
|
||||||
@@ -308,7 +309,7 @@ def compute_constrained_path(network, req):
|
|||||||
candidate.sort(key=lambda x: len(x))
|
candidate.sort(key=lambda x: len(x))
|
||||||
total_path = candidate[0]
|
total_path = candidate[0]
|
||||||
else:
|
else:
|
||||||
if req.loose_list[req.nodes_list.index(n)] == 'loose':
|
if req.loose_list[1] == 'loose':
|
||||||
print(f'Request {req.request_id} could not find a path crossing {nodes_list} in network topology')
|
print(f'Request {req.request_id} could not find a path crossing {nodes_list} in network topology')
|
||||||
print(f'constraint ignored')
|
print(f'constraint ignored')
|
||||||
total_path = dijkstra_path(network, source, destination)
|
total_path = dijkstra_path(network, source, destination)
|
||||||
@@ -422,9 +423,12 @@ def propagate_and_optimize_mode(path, req, equipment, show=False):
|
|||||||
if show :
|
if show :
|
||||||
print(el)
|
print(el)
|
||||||
for m in modes_to_explore :
|
for m in modes_to_explore :
|
||||||
|
if path[-1].snr is not None:
|
||||||
if round(mean(path[-1].snr+lin2db(b/(12.5e9))),2) > m['OSNR'] :
|
if round(mean(path[-1].snr+lin2db(b/(12.5e9))),2) > m['OSNR'] :
|
||||||
found_a_feasible_mode = True
|
found_a_feasible_mode = True
|
||||||
return path, m
|
return path, m
|
||||||
|
else:
|
||||||
|
return [], None
|
||||||
# only get to this point if no budrate/mode staisfies OSNR requirement
|
# only get to this point if no budrate/mode staisfies OSNR requirement
|
||||||
# returns the last propagated path and mode
|
# returns the last propagated path and mode
|
||||||
msg = f'Warning! Request {req.request_id}: no mode satisfies path SNR requirement.\n'
|
msg = f'Warning! Request {req.request_id}: no mode satisfies path SNR requirement.\n'
|
||||||
@@ -461,7 +465,7 @@ def jsontocsv(json_data,equipment,fileout):
|
|||||||
# selects only roadm nodes
|
# selects only roadm nodes
|
||||||
pth = ' | '.join([ e['path-route-object']['unnumbered-hop']['node-id']
|
pth = ' | '.join([ e['path-route-object']['unnumbered-hop']['node-id']
|
||||||
for e in p['path-properties']['path-route-objects']
|
for e in p['path-properties']['path-route-objects']
|
||||||
if e['path-route-object']['unnumbered-hop']['node-id'].startswith('roadm')])
|
if e['path-route-object']['unnumbered-hop']['node-id'].startswith('roadm') or e['path-route-object']['unnumbered-hop']['node-id'].startswith('Edfa')])
|
||||||
|
|
||||||
[tsp,mode] = p['path-properties']['path-route-objects'][0]\
|
[tsp,mode] = p['path-properties']['path-route-objects'][0]\
|
||||||
['path-route-object']['unnumbered-hop']['hop-type'].split(' - ')
|
['path-route-object']['unnumbered-hop']['hop-type'].split(' - ')
|
||||||
@@ -585,7 +589,8 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
|
|||||||
for pathreq in pathreqlist_disjt :
|
for pathreq in pathreqlist_disjt :
|
||||||
all_simp_pths = list(all_simple_paths(network,\
|
all_simp_pths = list(all_simple_paths(network,\
|
||||||
source=next(el for el in network.nodes() if el.uid == pathreq.source),\
|
source=next(el for el in network.nodes() if el.uid == pathreq.source),\
|
||||||
target=next(el for el in network.nodes() if el.uid == pathreq.destination)))
|
target=next(el for el in network.nodes() if el.uid == pathreq.destination),\
|
||||||
|
cutoff=80))
|
||||||
# sort them
|
# sort them
|
||||||
all_simp_pths = sorted(all_simp_pths, key=lambda path: len(path))
|
all_simp_pths = sorted(all_simp_pths, key=lambda path: len(path))
|
||||||
# reversed direction paths required to check disjunction on both direction
|
# reversed direction paths required to check disjunction on both direction
|
||||||
|
|||||||
Reference in New Issue
Block a user