mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-10-29 17:22:42 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40bbb9b553 | ||
|
|
c5a29d7b81 | ||
|
|
2fa0dac2f1 | ||
|
|
02916691c7 | ||
|
|
5d3526a74c | ||
|
|
459a82150b | ||
|
|
f67e9c4914 | ||
|
|
0c2bf58080 | ||
|
|
396020eeb5 | ||
|
|
84fd574df9 | ||
|
|
e97d20c3fe | ||
|
|
f52ff92918 | ||
|
|
4707abd2bd | ||
|
|
5b824a7a2c | ||
|
|
3784627bc9 | ||
|
|
1b265a3d27 | ||
|
|
927d73c720 | ||
|
|
1cf90a019b | ||
|
|
e2fac13219 |
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
cp -nr /oopt-gnpy/gnpy/example-data /shared
|
||||
cp -nr /opt/application/oopt-gnpy/gnpy/example-data /shared
|
||||
exec "$@"
|
||||
|
||||
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
venv/
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -65,3 +65,5 @@ target/
|
||||
|
||||
# MacOS DS_store
|
||||
.DS_Store
|
||||
|
||||
venv/
|
||||
|
||||
22
Dockerfile
22
Dockerfile
@@ -1,8 +1,18 @@
|
||||
FROM python:3.7-slim
|
||||
COPY . /oopt-gnpy
|
||||
WORKDIR /oopt-gnpy
|
||||
RUN apt update; apt install -y git
|
||||
RUN pip install .
|
||||
WORKDIR /shared/example-data
|
||||
ENTRYPOINT ["/oopt-gnpy/.docker-entry.sh"]
|
||||
WORKDIR /opt/application/oopt-gnpy
|
||||
RUN mkdir -p /shared/example-data \
|
||||
&& groupadd gnpy \
|
||||
&& useradd -u 1000 -g gnpy -m gnpy \
|
||||
&& apt-get update \
|
||||
&& apt-get install git -y \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY . /opt/application/oopt-gnpy
|
||||
WORKDIR /opt/application/oopt-gnpy
|
||||
RUN mkdir topology \
|
||||
&& mkdir equipment \
|
||||
&& mkdir autodesign \
|
||||
&& pip install . \
|
||||
&& chown -Rc gnpy:gnpy /opt/application/oopt-gnpy /shared/example-data
|
||||
USER gnpy
|
||||
ENTRYPOINT ["/opt/application/oopt-gnpy/.docker-entry.sh"]
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
30
README.rst
30
README.rst
@@ -128,6 +128,36 @@ As a result transponder type is not part of the network info. it is related to t
|
||||
|
||||
The current version includes a spectrum assigment features that enables to compute a candidate spectrum assignment for each service based on a first fit policy. Spectrum is assigned based on service specified spacing value, path_bandwidth value and selected mode for the transceiver. This spectrum assignment includes a basic capacity planning capability so that the spectrum resource is limited by the frequency min and max values defined for the links. If the requested services reach the link spectrum capacity, additional services feasibility are computed but marked as blocked due to spectrum reason.
|
||||
|
||||
REST API (experimental)
|
||||
-----------------------
|
||||
``gnpy`` provides an experimental api for requesting several paths at once. It is based on Flask server.
|
||||
You can run it through command line or Docker.
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
$ gnpy-rest
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
$ docker run -p 8080:8080 -it emmanuelledelfour/gnpy-experimental:candi-1.1 gnpy-rest
|
||||
|
||||
When starting the api server will aks for an encryption/decryption key. This key i used to encrypt equipment file when using /api/v1/equipments endpoint.
|
||||
This key is a Fernet key and can be generated this way:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from cryptography.fernet import Fernet
|
||||
Fernet.generate_key()
|
||||
|
||||
|
||||
After typing the key, you can detach the container by typing ^P^Q.
|
||||
After starting the api server, you can launch a request
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
$ curl -v -X POST -H "Content-Type: application/json" -d @<PATH_TO_JSON_REQUEST_FILE> https://localhost:8080/api/v1/path-computation -k
|
||||
|
||||
TODO: api documentation, unit tests, real WSGI server with trusted certificates
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
9
gnpy/api/__init__.py
Normal file
9
gnpy/api/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# coding: utf-8
|
||||
from flask import Flask
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
import gnpy.api.route.path_request_route
|
||||
import gnpy.api.route.status_route
|
||||
import gnpy.api.route.topology_route
|
||||
import gnpy.api.route.equipments_route
|
||||
1
gnpy/api/exception/__init__.py
Normal file
1
gnpy/api/exception/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# coding: utf-8
|
||||
14
gnpy/api/exception/config_error.py
Normal file
14
gnpy/api/exception/config_error.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
class ConfigError(Exception):
|
||||
""" Exception raise for configuration file error
|
||||
Attributes:
|
||||
message -- explanation of the error
|
||||
"""
|
||||
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
14
gnpy/api/exception/equipment_error.py
Normal file
14
gnpy/api/exception/equipment_error.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
class EquipmentError(Exception):
|
||||
""" Exception raise for equipment error
|
||||
Attributes:
|
||||
message -- explanation of the error
|
||||
"""
|
||||
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
33
gnpy/api/exception/exception_handler.py
Normal file
33
gnpy/api/exception/exception_handler.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# coding: utf-8
|
||||
import json
|
||||
import re
|
||||
|
||||
import werkzeug
|
||||
|
||||
from gnpy.api.model.error import Error
|
||||
|
||||
_reaesc = re.compile(r'\x1b[^m]*m')
|
||||
|
||||
|
||||
def common_error_handler(exception):
|
||||
"""
|
||||
|
||||
:type exception: Exception
|
||||
|
||||
"""
|
||||
status_code = 500
|
||||
if not isinstance(exception, werkzeug.exceptions.HTTPException):
|
||||
exception = werkzeug.exceptions.InternalServerError()
|
||||
exception.description = "Something went wrong on our side."
|
||||
else:
|
||||
status_code = exception.code
|
||||
response = Error(message=exception.name, description=exception.description,
|
||||
code=status_code)
|
||||
|
||||
return werkzeug.Response(response=json.dumps(response.__dict__), status=status_code, mimetype='application/json')
|
||||
|
||||
|
||||
def bad_request_handler(exception):
|
||||
response = Error(message='bad request', description=_reaesc.sub('', str(exception)),
|
||||
code=400)
|
||||
return werkzeug.Response(response=json.dumps(response.__dict__), status=400, mimetype='application/json')
|
||||
14
gnpy/api/exception/path_computation_error.py
Normal file
14
gnpy/api/exception/path_computation_error.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
class PathComputationError(Exception):
|
||||
""" Exception raise for path computation error error
|
||||
Attributes:
|
||||
message -- explanation of the error
|
||||
"""
|
||||
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
14
gnpy/api/exception/topology_error.py
Normal file
14
gnpy/api/exception/topology_error.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
class TopologyError(Exception):
|
||||
""" Exception raise for topology error
|
||||
Attributes:
|
||||
message -- explanation of the error
|
||||
"""
|
||||
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
1
gnpy/api/model/__init__.py
Normal file
1
gnpy/api/model/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# coding: utf-8
|
||||
17
gnpy/api/model/error.py
Normal file
17
gnpy/api/model/error.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
class Error:
|
||||
|
||||
def __init__(self, code: int = None, message: str = None, description: str = None):
|
||||
"""Error
|
||||
:param code: The code of this Error.
|
||||
:type code: int
|
||||
:param message: The message of this Error.
|
||||
:type message: str
|
||||
:param description: The description of this Error.
|
||||
:type description: str
|
||||
"""
|
||||
self.code = code
|
||||
self.message = message
|
||||
self.description = description
|
||||
8
gnpy/api/model/result.py
Normal file
8
gnpy/api/model/result.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
class Result:
|
||||
|
||||
def __init__(self, message: str = None, description: str = None):
|
||||
self.message = message
|
||||
self.description = description
|
||||
83
gnpy/api/rest_example.py
Normal file
83
gnpy/api/rest_example.py
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
gnpy.tools.rest_example
|
||||
=======================
|
||||
|
||||
GNPy as a rest API example
|
||||
'''
|
||||
|
||||
import logging
|
||||
from logging.handlers import RotatingFileHandler
|
||||
|
||||
import werkzeug
|
||||
from flask_injector import FlaskInjector
|
||||
from injector import singleton
|
||||
from werkzeug.exceptions import InternalServerError
|
||||
|
||||
import gnpy.core.exceptions as exceptions
|
||||
from gnpy.api import app
|
||||
from gnpy.api.exception.exception_handler import bad_request_handler, common_error_handler
|
||||
from gnpy.api.exception.path_computation_error import PathComputationError
|
||||
from gnpy.api.exception.topology_error import TopologyError
|
||||
from gnpy.api.service import config_service
|
||||
from gnpy.api.service.encryption_service import EncryptionService
|
||||
from gnpy.api.service.equipment_service import EquipmentService
|
||||
from gnpy.api.service.path_request_service import PathRequestService
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _init_logger():
|
||||
handler = RotatingFileHandler('api.log', maxBytes=1024 * 1024, backupCount=5, encoding='utf-8')
|
||||
ch = logging.StreamHandler()
|
||||
logging.basicConfig(level=logging.INFO, handlers=[handler, ch],
|
||||
format="%(asctime)s %(levelname)s %(name)s(%(lineno)s) [%(threadName)s - %(thread)d] - %("
|
||||
"message)s")
|
||||
|
||||
|
||||
def _init_app(key):
|
||||
app.register_error_handler(KeyError, bad_request_handler)
|
||||
app.register_error_handler(TypeError, bad_request_handler)
|
||||
app.register_error_handler(ValueError, bad_request_handler)
|
||||
app.register_error_handler(exceptions.ConfigurationError, bad_request_handler)
|
||||
app.register_error_handler(exceptions.DisjunctionError, bad_request_handler)
|
||||
app.register_error_handler(exceptions.EquipmentConfigError, bad_request_handler)
|
||||
app.register_error_handler(exceptions.NetworkTopologyError, bad_request_handler)
|
||||
app.register_error_handler(exceptions.ServiceError, bad_request_handler)
|
||||
app.register_error_handler(exceptions.SpectrumError, bad_request_handler)
|
||||
app.register_error_handler(exceptions.ParametersError, bad_request_handler)
|
||||
app.register_error_handler(AssertionError, bad_request_handler)
|
||||
app.register_error_handler(InternalServerError, common_error_handler)
|
||||
app.register_error_handler(TopologyError, bad_request_handler)
|
||||
app.register_error_handler(PathComputationError, bad_request_handler)
|
||||
for error_code in werkzeug.exceptions.default_exceptions:
|
||||
app.register_error_handler(error_code, common_error_handler)
|
||||
config = config_service.init_config()
|
||||
config.add_section('SECRET')
|
||||
config.set('SECRET', 'equipment', key)
|
||||
app.config['properties'] = config
|
||||
|
||||
|
||||
def _configure(binder):
|
||||
binder.bind(EquipmentService,
|
||||
to=EquipmentService(EncryptionService(app.config['properties'].get('SECRET', 'equipment'))),
|
||||
scope=singleton)
|
||||
binder.bind(PathRequestService,
|
||||
to=PathRequestService(EncryptionService(app.config['properties'].get('SECRET', 'equipment'))),
|
||||
scope=singleton)
|
||||
app.config['properties'].pop('SECRET', None)
|
||||
|
||||
|
||||
def main():
|
||||
key = input('Enter encryption/decryption key: ')
|
||||
_init_logger()
|
||||
_init_app(key)
|
||||
FlaskInjector(app=app, modules=[_configure])
|
||||
|
||||
app.run(host='0.0.0.0', port=8080, ssl_context='adhoc')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
2
gnpy/api/route/__init__.py
Normal file
2
gnpy/api/route/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# coding: utf-8
|
||||
|
||||
38
gnpy/api/route/equipments_route.py
Normal file
38
gnpy/api/route/equipments_route.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# coding: utf-8
|
||||
import http
|
||||
import json
|
||||
|
||||
from flask import request
|
||||
|
||||
from gnpy.api import app
|
||||
from gnpy.api.exception.equipment_error import EquipmentError
|
||||
from gnpy.api.model.result import Result
|
||||
from gnpy.api.service.equipment_service import EquipmentService
|
||||
|
||||
EQUIPMENT_BASE_PATH = '/api/v1/equipments'
|
||||
EQUIPMENT_ID_PATH = EQUIPMENT_BASE_PATH + '/<equipment_id>'
|
||||
|
||||
|
||||
@app.route(EQUIPMENT_BASE_PATH, methods=['POST'])
|
||||
def create_equipment(equipment_service: EquipmentService):
|
||||
if not request.is_json:
|
||||
raise EquipmentError('Request body is not json')
|
||||
equipment_identifier = equipment_service.save_equipment(request.json)
|
||||
response = Result(message='Equipment creation ok', description=equipment_identifier)
|
||||
return json.dumps(response.__dict__), 201, {'location': EQUIPMENT_BASE_PATH + '/' + equipment_identifier}
|
||||
|
||||
|
||||
@app.route(EQUIPMENT_ID_PATH, methods=['PUT'])
|
||||
def update_equipment(equipment_id, equipment_service: EquipmentService):
|
||||
if not request.is_json:
|
||||
raise EquipmentError('Request body is not json')
|
||||
equipment_identifier = equipment_service.update_equipment(request.json, equipment_id)
|
||||
response = Result(message='Equipment update ok', description=equipment_identifier)
|
||||
return json.dumps(response.__dict__), http.HTTPStatus.OK, {
|
||||
'location': EQUIPMENT_BASE_PATH + '/' + equipment_identifier}
|
||||
|
||||
|
||||
@app.route(EQUIPMENT_ID_PATH, methods=['DELETE'])
|
||||
def delete_equipment(equipment_id, equipment_service: EquipmentService):
|
||||
equipment_service.delete_equipment(equipment_id)
|
||||
return '', http.HTTPStatus.NO_CONTENT
|
||||
63
gnpy/api/route/path_request_route.py
Normal file
63
gnpy/api/route/path_request_route.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# coding: utf-8
|
||||
import http
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from flask import request
|
||||
|
||||
from gnpy.api import app
|
||||
from gnpy.api.exception.equipment_error import EquipmentError
|
||||
from gnpy.api.exception.topology_error import TopologyError
|
||||
from gnpy.api.service import topology_service
|
||||
from gnpy.api.service.equipment_service import EquipmentService
|
||||
from gnpy.api.service.path_request_service import PathRequestService
|
||||
from gnpy.tools.json_io import _equipment_from_json, network_from_json
|
||||
from gnpy.topology.request import ResultElement
|
||||
|
||||
PATH_COMPUTATION_BASE_PATH = '/api/v1/path-computation'
|
||||
AUTODESIGN_PATH = PATH_COMPUTATION_BASE_PATH + '/<path_computation_id>/autodesign'
|
||||
|
||||
_examples_dir = Path(__file__).parent.parent.parent / 'example-data'
|
||||
|
||||
|
||||
@app.route(PATH_COMPUTATION_BASE_PATH, methods=['POST'])
|
||||
def compute_path(equipment_service: EquipmentService, path_request_service: PathRequestService):
|
||||
data = request.json
|
||||
service = data['gnpy-api:service']
|
||||
if 'gnpy-api:topology' in data:
|
||||
topology = data['gnpy-api:topology']
|
||||
elif 'gnpy-api:topology_id' in data:
|
||||
topology = topology_service.get_topology(data['gnpy-api:topology_id'])
|
||||
else:
|
||||
raise TopologyError('No topology found in request')
|
||||
if 'gnpy-api:equipment' in data:
|
||||
equipment = data['gnpy-api:equipment']
|
||||
elif 'gnpy-api:equipment_id' in data:
|
||||
equipment = equipment_service.get_equipment(data['gnpy-api:equipment_id'])
|
||||
else:
|
||||
raise EquipmentError('No equipment found in request')
|
||||
equipment = _equipment_from_json(equipment,
|
||||
os.path.join(_examples_dir, 'std_medium_gain_advanced_config.json'))
|
||||
network = network_from_json(topology, equipment)
|
||||
|
||||
propagatedpths, reversed_propagatedpths, rqs, path_computation_id = path_request_service.path_requests_run(service,
|
||||
network,
|
||||
equipment)
|
||||
# Generate the output
|
||||
result = []
|
||||
# assumes that list of rqs and list of propgatedpths have same order
|
||||
for i, pth in enumerate(propagatedpths):
|
||||
result.append(ResultElement(rqs[i], pth, reversed_propagatedpths[i]))
|
||||
return {"result": {"response": [n.json for n in result]}}, 201, {
|
||||
'location': AUTODESIGN_PATH.replace('<path_computation_id>', path_computation_id)}
|
||||
|
||||
|
||||
@app.route(AUTODESIGN_PATH, methods=['GET'])
|
||||
def get_autodesign(path_computation_id, path_request_service: PathRequestService):
|
||||
return path_request_service.get_autodesign(path_computation_id), http.HTTPStatus.OK
|
||||
|
||||
|
||||
@app.route(AUTODESIGN_PATH, methods=['DELETE'])
|
||||
def delete_autodesign(path_computation_id, path_request_service: PathRequestService):
|
||||
path_request_service.delete_autodesign(path_computation_id)
|
||||
return '', http.HTTPStatus.NO_CONTENT
|
||||
7
gnpy/api/route/status_route.py
Normal file
7
gnpy/api/route/status_route.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# coding: utf-8
|
||||
from gnpy.api import app
|
||||
|
||||
|
||||
@app.route('/api/v1/status', methods=['GET'])
|
||||
def api_status():
|
||||
return {"version": "v1", "status": "ok"}, 200
|
||||
43
gnpy/api/route/topology_route.py
Normal file
43
gnpy/api/route/topology_route.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# coding: utf-8
|
||||
import http
|
||||
import json
|
||||
|
||||
from flask import request
|
||||
|
||||
from gnpy.api import app
|
||||
from gnpy.api.exception.topology_error import TopologyError
|
||||
from gnpy.api.model.result import Result
|
||||
from gnpy.api.service import topology_service
|
||||
|
||||
TOPOLOGY_BASE_PATH = '/api/v1/topologies'
|
||||
TOPOLOGY_ID_PATH = TOPOLOGY_BASE_PATH + '/<topology_id>'
|
||||
|
||||
|
||||
@app.route(TOPOLOGY_BASE_PATH, methods=['POST'])
|
||||
def create_topology():
|
||||
if not request.is_json:
|
||||
raise TopologyError('Request body is not json')
|
||||
topology_identifier = topology_service.save_topology(request.json)
|
||||
response = Result(message='Topology creation ok', description=topology_identifier)
|
||||
return json.dumps(response.__dict__), 201, {'location': TOPOLOGY_BASE_PATH + '/' + topology_identifier}
|
||||
|
||||
|
||||
@app.route(TOPOLOGY_ID_PATH, methods=['PUT'])
|
||||
def update_topology(topology_id):
|
||||
if not request.is_json:
|
||||
raise TopologyError('Request body is not json')
|
||||
topology_identifier = topology_service.update_topology(request.json, topology_id)
|
||||
response = Result(message='Topology update ok', description=topology_identifier)
|
||||
return json.dumps(response.__dict__), http.HTTPStatus.OK, {
|
||||
'location': TOPOLOGY_BASE_PATH + '/' + topology_identifier}
|
||||
|
||||
|
||||
@app.route(TOPOLOGY_ID_PATH, methods=['GET'])
|
||||
def get_topology(topology_id):
|
||||
return topology_service.get_topology(topology_id), http.HTTPStatus.OK
|
||||
|
||||
|
||||
@app.route(TOPOLOGY_ID_PATH, methods=['DELETE'])
|
||||
def delete_topology(topology_id):
|
||||
topology_service.delete_topology(topology_id)
|
||||
return '', http.HTTPStatus.NO_CONTENT
|
||||
1
gnpy/api/service/__init__.py
Normal file
1
gnpy/api/service/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# coding: utf-8
|
||||
45
gnpy/api/service/config_service.py
Normal file
45
gnpy/api/service/config_service.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# coding: utf-8
|
||||
import configparser
|
||||
import os
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from gnpy.api.exception.config_error import ConfigError
|
||||
|
||||
|
||||
def init_config(properties_file_path: str = os.path.join(os.path.dirname(__file__),
|
||||
'properties.ini')) -> configparser.ConfigParser:
|
||||
"""
|
||||
Read config from properties_file_path
|
||||
@param properties_file_path: the properties file to read
|
||||
@return: config parser
|
||||
"""
|
||||
if not os.path.exists(properties_file_path):
|
||||
raise ConfigError('Properties file does not exist ' + properties_file_path)
|
||||
config = configparser.ConfigParser()
|
||||
config.read(properties_file_path)
|
||||
return config
|
||||
|
||||
|
||||
def get_topology_dir() -> str:
|
||||
"""
|
||||
Get the base dir where topologies are saved
|
||||
@return: the directory of topologies
|
||||
"""
|
||||
return current_app.config['properties'].get('DIRECTORY', 'topology')
|
||||
|
||||
|
||||
def get_equipment_dir() -> str:
|
||||
"""
|
||||
Get the base dir where equipments are saved
|
||||
@return: the directory of equipments
|
||||
"""
|
||||
return current_app.config['properties'].get('DIRECTORY', 'equipment')
|
||||
|
||||
|
||||
def get_autodesign_dir() -> str:
|
||||
"""
|
||||
Get the base dir where autodesign are saved
|
||||
@return: the directory of equipments
|
||||
"""
|
||||
return current_app.config['properties'].get('DIRECTORY', 'autodesign')
|
||||
13
gnpy/api/service/encryption_service.py
Normal file
13
gnpy/api/service/encryption_service.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# coding: utf-8
|
||||
from cryptography.fernet import Fernet
|
||||
|
||||
|
||||
class EncryptionService:
|
||||
def __init__(self, key):
|
||||
self._fernet = Fernet(key)
|
||||
|
||||
def encrypt(self, data):
|
||||
return self._fernet.encrypt(data)
|
||||
|
||||
def decrypt(self, data):
|
||||
return self._fernet.decrypt(data)
|
||||
66
gnpy/api/service/equipment_service.py
Normal file
66
gnpy/api/service/equipment_service.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# coding: utf-
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from injector import Inject
|
||||
|
||||
from gnpy.api.exception.equipment_error import EquipmentError
|
||||
from gnpy.api.service import config_service
|
||||
from gnpy.api.service.encryption_service import EncryptionService
|
||||
|
||||
|
||||
class EquipmentService:
|
||||
|
||||
def __init__(self, encryption_service: EncryptionService):
|
||||
self.encryption = encryption_service
|
||||
|
||||
def save_equipment(self, equipment):
|
||||
"""
|
||||
Save equipment to file.
|
||||
@param equipment: json content
|
||||
@return: a UUID identifier to identify the equipment
|
||||
"""
|
||||
equipment_identifier = str(uuid.uuid4())
|
||||
# TODO: validate json content
|
||||
self._write_equipment(equipment, equipment_identifier)
|
||||
return equipment_identifier
|
||||
|
||||
def update_equipment(self, equipment, equipment_identifier):
|
||||
"""
|
||||
Update equipment with identifier equipment_identifier.
|
||||
@param equipment_identifier: the identifier of the equipment to be updated
|
||||
@param equipment: json content
|
||||
@return: a UUID identifier to identify the equipment
|
||||
"""
|
||||
# TODO: validate json content
|
||||
self._write_equipment(equipment, equipment_identifier)
|
||||
return equipment_identifier
|
||||
|
||||
def _write_equipment(self, equipment, equipment_identifier):
|
||||
equipment_dir = config_service.get_equipment_dir()
|
||||
with(open(os.path.join(equipment_dir, '.'.join([equipment_identifier, 'json'])), 'wb')) as file:
|
||||
file.write(self.encryption.encrypt(json.dumps(equipment).encode()))
|
||||
|
||||
def get_equipment(self, equipment_id: str) -> dict:
|
||||
"""
|
||||
Get the equipment with id equipment_id
|
||||
@param equipment_id:
|
||||
@return: the equipment in json format
|
||||
"""
|
||||
equipment_dir = config_service.get_equipment_dir()
|
||||
equipment_file = os.path.join(equipment_dir, '.'.join([equipment_id, 'json']))
|
||||
if not os.path.exists(equipment_file):
|
||||
raise EquipmentError('Equipment with id {} does not exist '.format(equipment_id))
|
||||
with(open(equipment_file, 'rb')) as file:
|
||||
return json.loads(self.encryption.decrypt(file.read()))
|
||||
|
||||
def delete_equipment(self, equipment_id: str):
|
||||
"""
|
||||
Delete equipment with id equipment_id
|
||||
@param equipment_id:
|
||||
"""
|
||||
equipment_dir = config_service.get_equipment_dir()
|
||||
equipment_file = os.path.join(equipment_dir, '.'.join([equipment_id, 'json']))
|
||||
if os.path.exists(equipment_file):
|
||||
os.remove(equipment_file)
|
||||
100
gnpy/api/service/path_request_service.py
Normal file
100
gnpy/api/service/path_request_service.py
Normal file
@@ -0,0 +1,100 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
|
||||
import gnpy.core.ansi_escapes as ansi_escapes
|
||||
from gnpy.api.exception.path_computation_error import PathComputationError
|
||||
from gnpy.api.service import config_service
|
||||
from gnpy.api.service.encryption_service import EncryptionService
|
||||
from gnpy.core.network import build_network
|
||||
from gnpy.core.utils import lin2db, automatic_nch
|
||||
from gnpy.tools.json_io import requests_from_json, disjunctions_from_json, network_to_json
|
||||
from gnpy.topology.request import (compute_path_dsjctn, requests_aggregation,
|
||||
correct_json_route_list,
|
||||
deduplicate_disjunctions, compute_path_with_disjunction)
|
||||
from gnpy.topology.spectrum_assignment import build_oms_list, pth_assign_spectrum
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PathRequestService:
|
||||
|
||||
def __init__(self, encryption_service: EncryptionService):
|
||||
self.encryption = encryption_service
|
||||
|
||||
def path_requests_run(self, service, network, equipment):
|
||||
# Build the network once using the default power defined in SI in eqpt config
|
||||
# TODO power density: db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by
|
||||
# spacing, f_min and f_max
|
||||
p_db = equipment['SI']['default'].power_dbm
|
||||
|
||||
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,
|
||||
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
|
||||
build_network(network, equipment, p_db, p_total_db)
|
||||
path_computation_identifier = str(uuid.uuid4())
|
||||
autodesign_dir = config_service.get_autodesign_dir()
|
||||
with(open(os.path.join(autodesign_dir, '.'.join([path_computation_identifier, 'json'])), 'wb')) as file:
|
||||
file.write(self.encryption.encrypt(json.dumps(network_to_json(network)).encode()))
|
||||
oms_list = build_oms_list(network, equipment)
|
||||
rqs = requests_from_json(service, equipment)
|
||||
|
||||
# check that request ids are unique. Non unique ids, may
|
||||
# mess the computation: better to stop the computation
|
||||
all_ids = [r.request_id for r in rqs]
|
||||
if len(all_ids) != len(set(all_ids)):
|
||||
for item in list(set(all_ids)):
|
||||
all_ids.remove(item)
|
||||
msg = f'Requests id {all_ids} are not unique'
|
||||
_logger.critical(msg)
|
||||
raise ValueError('Requests id ' + all_ids + ' are not unique')
|
||||
rqs = correct_json_route_list(network, rqs)
|
||||
|
||||
# pths = compute_path(network, equipment, rqs)
|
||||
dsjn = disjunctions_from_json(service)
|
||||
|
||||
# need to warn or correct in case of wrong disjunction form
|
||||
# disjunction must not be repeated with same or different ids
|
||||
dsjn = deduplicate_disjunctions(dsjn)
|
||||
|
||||
rqs, dsjn = requests_aggregation(rqs, dsjn)
|
||||
# TODO export novel set of aggregated demands in a json file
|
||||
|
||||
_logger.info(f'{ansi_escapes.blue}The following services have been requested:{ansi_escapes.reset}' + str(rqs))
|
||||
|
||||
_logger.info(f'{ansi_escapes.blue}Computing all paths with constraints{ansi_escapes.reset}')
|
||||
pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
||||
|
||||
_logger.info(f'{ansi_escapes.blue}Propagating on selected path{ansi_escapes.reset}')
|
||||
propagatedpths, reversed_pths, reversed_propagatedpths = compute_path_with_disjunction(network, equipment, rqs,
|
||||
pths)
|
||||
# Note that deepcopy used in compute_path_with_disjunction returns
|
||||
# a list of nodes which are not belonging to network (they are copies of the node objects).
|
||||
# so there can not be propagation on these nodes.
|
||||
|
||||
pth_assign_spectrum(pths, rqs, oms_list, reversed_pths)
|
||||
return propagatedpths, reversed_propagatedpths, rqs, path_computation_identifier
|
||||
|
||||
def get_autodesign(self, path_computation_id):
|
||||
"""
|
||||
Get the autodesign with id topology_id
|
||||
@param path_computation_id:
|
||||
@return: the autodesign in json format
|
||||
"""
|
||||
autodesign_dir = config_service.get_autodesign_dir()
|
||||
autodesign_file = os.path.join(autodesign_dir, '.'.join([path_computation_id, 'json']))
|
||||
if not os.path.exists(autodesign_file):
|
||||
raise PathComputationError('Autodesign with id {} does not exist '.format(path_computation_id))
|
||||
with(open(autodesign_file, 'rb')) as file:
|
||||
return json.loads(self.encryption.decrypt(file.read()))
|
||||
|
||||
def delete_autodesign(self, path_computation_id: str):
|
||||
"""
|
||||
Delete autodesign with id equipment_id
|
||||
@param path_computation_id:
|
||||
"""
|
||||
autodesign_dir = config_service.get_autodesign_dir()
|
||||
autodesign_file = os.path.join(autodesign_dir, '.'.join([path_computation_id, 'json']))
|
||||
if os.path.exists(autodesign_file):
|
||||
os.remove(autodesign_file)
|
||||
4
gnpy/api/service/properties.ini
Normal file
4
gnpy/api/service/properties.ini
Normal file
@@ -0,0 +1,4 @@
|
||||
[DIRECTORY]
|
||||
topology: /opt/application/oopt-gnpy/topology
|
||||
equipment: /opt/application/oopt-gnpy/equipment
|
||||
autodesign: /opt/application/oopt-gnpy/autodesign
|
||||
62
gnpy/api/service/topology_service.py
Normal file
62
gnpy/api/service/topology_service.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# coding: utf-
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from gnpy.api.exception.topology_error import TopologyError
|
||||
from gnpy.api.service import config_service
|
||||
|
||||
|
||||
def save_topology(topology):
|
||||
"""
|
||||
Save topology to file.
|
||||
@param topology: json content
|
||||
@return: a UUID identifier to identify the topology
|
||||
"""
|
||||
topology_identifier = str(uuid.uuid4())
|
||||
# TODO: validate json content
|
||||
_write_topology(topology, topology_identifier)
|
||||
return topology_identifier
|
||||
|
||||
|
||||
def update_topology(topology, topology_identifier):
|
||||
"""
|
||||
Update topology with identifier topology_identifier.
|
||||
@param topology_identifier: the identifier of the topology to be updated
|
||||
@param topology: json content
|
||||
@return: a UUID identifier to identify the topology
|
||||
"""
|
||||
# TODO: validate json content
|
||||
_write_topology(topology, topology_identifier)
|
||||
return topology_identifier
|
||||
|
||||
|
||||
def _write_topology(topology, topology_identifier):
|
||||
topology_dir = config_service.get_topology_dir()
|
||||
with(open(os.path.join(topology_dir, '.'.join([topology_identifier, 'json'])), 'w')) as file:
|
||||
json.dump(topology, file)
|
||||
|
||||
|
||||
def get_topology(topology_id: str) -> dict:
|
||||
"""
|
||||
Get the topology with id topology_id
|
||||
@param topology_id:
|
||||
@return: the topology in json format
|
||||
"""
|
||||
topology_dir = config_service.get_topology_dir()
|
||||
topology_file = os.path.join(topology_dir, '.'.join([topology_id, 'json']))
|
||||
if not os.path.exists(topology_file):
|
||||
raise TopologyError('Topology with id {} does not exist '.format(topology_id))
|
||||
with(open(topology_file, 'r')) as file:
|
||||
return json.load(file)
|
||||
|
||||
|
||||
def delete_topology(topology_id: str):
|
||||
"""
|
||||
Delete topology with id topology_id
|
||||
@param topology_id:
|
||||
"""
|
||||
topology_dir = config_service.get_topology_dir()
|
||||
topology_file = os.path.join(topology_dir, '.'.join([topology_id, 'json']))
|
||||
if os.path.exists(topology_file):
|
||||
os.remove(topology_file)
|
||||
@@ -14,8 +14,8 @@
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -39,8 +39,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -104,8 +104,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -129,8 +129,8 @@
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
@@ -154,8 +154,8 @@
|
||||
"trx_mode": "mode 2",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
@@ -179,8 +179,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -204,8 +204,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -229,8 +229,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
|
||||
@@ -188,6 +188,8 @@ def transmission_main_example(args=None):
|
||||
params['loose_list'] = ['strict']
|
||||
params['format'] = ''
|
||||
params['path_bandwidth'] = 0
|
||||
params['effective_freq_slot'] = None
|
||||
params['blocking_reason'] = None
|
||||
trx_params = trx_mode_params(equipment)
|
||||
if args.power:
|
||||
trx_params['power'] = db2lin(float(args.power)) * 1e-3
|
||||
|
||||
@@ -440,7 +440,10 @@ def requests_from_json(json_data, equipment):
|
||||
params['bidir'] = req['bidirectional']
|
||||
params['destination'] = req['destination']
|
||||
params['trx_type'] = req['path-constraints']['te-bandwidth']['trx_type']
|
||||
params['trx_mode'] = req['path-constraints']['te-bandwidth']['trx_mode']
|
||||
if 'trx_mode' in req['path-constraints']['te-bandwidth'].keys():
|
||||
params['trx_mode'] = req['path-constraints']['te-bandwidth']['trx_mode']
|
||||
else:
|
||||
params['trx_mode'] = None
|
||||
params['format'] = params['trx_mode']
|
||||
params['spacing'] = req['path-constraints']['te-bandwidth']['spacing']
|
||||
try:
|
||||
@@ -475,8 +478,12 @@ def requests_from_json(json_data, equipment):
|
||||
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
||||
except KeyError:
|
||||
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
||||
_check_one_request(params, f_max_from_si)
|
||||
|
||||
if 'effective-freq-slot' in req['path-constraints']['te-bandwidth']:
|
||||
# temporarily reads only the first slot
|
||||
params['effective_freq_slot'] = req['path-constraints']['te-bandwidth']['effective-freq-slot'][0]
|
||||
else:
|
||||
params['effective_freq_slot'] = None
|
||||
params['blocking_reason'] = _check_one_request(params, f_max_from_si)
|
||||
try:
|
||||
params['path_bandwidth'] = req['path-constraints']['te-bandwidth']['path_bandwidth']
|
||||
except KeyError:
|
||||
@@ -498,7 +505,7 @@ def _check_one_request(params, f_max_from_si):
|
||||
f'{params["min_spacing"]*1e-9}GHz.\nComputation stopped'
|
||||
print(msg)
|
||||
_logger.critical(msg)
|
||||
raise ServiceError(msg)
|
||||
return 'MODE_BAUDRATE_NOT_CONSISTENT_WITH_SPACING'
|
||||
if f_max > f_max_from_si:
|
||||
msg = f'''Requested channel number {params["nb_channel"]}, baud rate {params["baud_rate"]} GHz
|
||||
and requested spacing {params["spacing"]*1e-9}GHz is not consistent with frequency range
|
||||
@@ -506,6 +513,7 @@ def _check_one_request(params, f_max_from_si):
|
||||
max recommanded nb of channels is {max_recommanded_nb_channels}.'''
|
||||
_logger.critical(msg)
|
||||
raise ServiceError(msg)
|
||||
return None
|
||||
|
||||
|
||||
def disjunctions_from_json(json_data):
|
||||
|
||||
@@ -127,7 +127,7 @@ class Request_element(Element):
|
||||
'technology': 'flexi-grid',
|
||||
'trx_type': self.trx_type,
|
||||
'trx_mode': self.mode,
|
||||
'effective-freq-slot': [{'N': 'null', 'M': 'null'}],
|
||||
'effective-freq-slot': [{'N': None, 'M': None}],
|
||||
'spacing': self.spacing,
|
||||
'max-nb-of-channel': self.nb_channel,
|
||||
'output-power': self.power
|
||||
|
||||
@@ -35,7 +35,7 @@ LOGGER = getLogger(__name__)
|
||||
RequestParams = namedtuple('RequestParams', 'request_id source destination bidir trx_type' +
|
||||
' trx_mode nodes_list loose_list spacing power nb_channel f_min' +
|
||||
' f_max format baud_rate OSNR bit_rate roll_off tx_osnr' +
|
||||
' min_spacing cost path_bandwidth')
|
||||
' min_spacing cost path_bandwidth effective_freq_slot blocking_reason')
|
||||
DisjunctionParams = namedtuple('DisjunctionParams', 'disjunction_id relaxable link' +
|
||||
'_diverse node_diverse disjunctions_req')
|
||||
|
||||
@@ -68,6 +68,11 @@ class PathRequest:
|
||||
self.min_spacing = params.min_spacing
|
||||
self.cost = params.cost
|
||||
self.path_bandwidth = params.path_bandwidth
|
||||
if params.effective_freq_slot is not None:
|
||||
self.N = params.effective_freq_slot['N']
|
||||
self.M = params.effective_freq_slot['M']
|
||||
if params.blocking_reason is not None:
|
||||
self.blocking_reason = params.blocking_reason
|
||||
|
||||
def __str__(self):
|
||||
return '\n\t'.join([f'{type(self).__name__} {self.request_id}',
|
||||
@@ -127,7 +132,7 @@ class Disjunction:
|
||||
|
||||
BLOCKING_NOPATH = ['NO_PATH', 'NO_PATH_WITH_CONSTRAINT',
|
||||
'NO_FEASIBLE_BAUDRATE_WITH_SPACING',
|
||||
'NO_COMPUTED_SNR']
|
||||
'NO_COMPUTED_SNR', 'MODE_BAUDRATE_NOT_CONSISTENT_WITH_SPACING']
|
||||
BLOCKING_NOMODE = ['NO_FEASIBLE_MODE', 'MODE_NOT_FEASIBLE']
|
||||
BLOCKING_NOSPECTRUM = 'NO_SPECTRUM'
|
||||
|
||||
@@ -389,7 +394,6 @@ def propagate_and_optimize_mode(path, req, equipment):
|
||||
else:
|
||||
req.blocking_reason = 'NO_COMPUTED_SNR'
|
||||
return path, None
|
||||
|
||||
# only get to this point if no baudrate/mode satisfies OSNR requirement
|
||||
|
||||
# returns the last propagated path and mode
|
||||
@@ -1133,7 +1137,7 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
|
||||
|
||||
# reversed path is needed for correct spectrum assignment
|
||||
reversed_path = find_reversed_path(pathlist[i])
|
||||
if pathreq.bidir:
|
||||
if pathreq.bidir and pathreq.baud_rate is not None:
|
||||
# only propagate if bidir is true, but needs the reversed path anyway for
|
||||
# correct spectrum assignment
|
||||
rev_p = deepcopy(reversed_path)
|
||||
@@ -1153,7 +1157,8 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
|
||||
print(msg)
|
||||
LOGGER.warning(msg)
|
||||
# TODO selection of mode should also be on reversed direction !!
|
||||
pathreq.blocking_reason = 'MODE_NOT_FEASIBLE'
|
||||
if not hasattr(pathreq, 'blocking_reason'):
|
||||
pathreq.blocking_reason = 'MODE_NOT_FEASIBLE'
|
||||
else:
|
||||
propagated_reversed_path = []
|
||||
else:
|
||||
|
||||
@@ -395,7 +395,7 @@ def pth_assign_spectrum(pths, rqs, oms_list, rpths):
|
||||
try:
|
||||
if rqs[i].blocking_reason:
|
||||
rqs[i].blocked = True
|
||||
rqs[i].N = 0
|
||||
rqs[i].N = None
|
||||
rqs[i].M = 0
|
||||
except AttributeError:
|
||||
nb_wl = ceil(rqs[i].path_bandwidth / rqs[i].bit_rate)
|
||||
@@ -404,9 +404,25 @@ def pth_assign_spectrum(pths, rqs, oms_list, rpths):
|
||||
# assumes that all channels must be grouped
|
||||
# TODO : enables non contiguous reservation in case of blocking
|
||||
requested_m = ceil(rqs[i].spacing / 0.0125e12) * nb_wl
|
||||
# concatenate all path and reversed path elements to derive slots availability
|
||||
if hasattr(rqs[i], 'M') and rqs[i].M is not None:
|
||||
# Consistency check between the requested M and path_bandwidth
|
||||
# M value should be bigger than the computed requested_m (simple estimate)
|
||||
# TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of
|
||||
# superchannel closed packing.
|
||||
if requested_m <= rqs[i].M:
|
||||
requested_m = rqs[i].M
|
||||
else:
|
||||
# TODO : create a specific blocking reason and following process for this case instead of an exception
|
||||
raise SpectrumError(f'requested M {rqs[i].M} number of slots for request {rqs[i].request_id} ' +
|
||||
f'should be greater than {requested_m} to support request ' +
|
||||
f'{rqs[i].path_bandwidth * 1e-9} Gbit/s with {rqs[i].tsp} {rqs[i].tsp_mode}')
|
||||
# else: there is no M value so the programs uses the requested_m one
|
||||
if hasattr(rqs[i], 'N'):
|
||||
requested_n = rqs[i].N
|
||||
else:
|
||||
requested_n = None
|
||||
(center_n, startn, stopn), path_oms = spectrum_selection(pth + rpths[i], oms_list, requested_m,
|
||||
requested_n=None)
|
||||
requested_n)
|
||||
# checks that requested_m is fitting startm and stopm
|
||||
# if not None, center_n and start, stop frequencies are applicable to all oms of pth
|
||||
# checks that spectrum is not None else indicate blocking reason
|
||||
@@ -426,6 +442,6 @@ def pth_assign_spectrum(pths, rqs, oms_list, rpths):
|
||||
rqs[i].M = requested_m
|
||||
else:
|
||||
rqs[i].blocked = True
|
||||
rqs[i].N = 0
|
||||
rqs[i].N = None
|
||||
rqs[i].M = 0
|
||||
rqs[i].blocking_reason = 'NO_SPECTRUM'
|
||||
|
||||
310
gnpy/yang/api-equipment.json
Normal file
310
gnpy/yang/api-equipment.json
Normal file
@@ -0,0 +1,310 @@
|
||||
{
|
||||
"Edfa":[{
|
||||
"type_variety": "high_detail_model_example",
|
||||
"type_def": "advanced_model",
|
||||
"gain_flatmax": 25.0,
|
||||
"gain_min": 15.0,
|
||||
"p_max": 21.0,
|
||||
"advanced_config_from_json": "std_medium_gain_advanced_config.json",
|
||||
"out_voa_auto": false,
|
||||
"allowed_for_design": false
|
||||
}, {
|
||||
"type_variety": "Juniper_BoosterHG",
|
||||
"type_def": "advanced_model",
|
||||
"gain_flatmax": 25.0,
|
||||
"gain_min": 10.0,
|
||||
"p_max": 21.0,
|
||||
"advanced_config_from_json": "Juniper-BoosterHG.json",
|
||||
"out_voa_auto": false,
|
||||
"allowed_for_design": false
|
||||
},
|
||||
{
|
||||
"type_variety": "operator_model_example",
|
||||
"type_def": "variable_gain",
|
||||
"gain_flatmax": 26.0,
|
||||
"gain_min": 15.0,
|
||||
"p_max": 23.0,
|
||||
"nf_min": 6.0,
|
||||
"nf_max": 10.0,
|
||||
"out_voa_auto": false,
|
||||
"allowed_for_design": false
|
||||
},
|
||||
{
|
||||
"type_variety": "low_noise",
|
||||
"type_def": "openroadm",
|
||||
"gain_flatmax": 27.0,
|
||||
"gain_min": 12.0,
|
||||
"p_max": 22.0,
|
||||
"nf_coef": [-8.104e-4,-6.221e-2,-5.889e-1,37.62],
|
||||
"allowed_for_design": false
|
||||
},
|
||||
{
|
||||
"type_variety": "standard",
|
||||
"type_def": "openroadm",
|
||||
"gain_flatmax": 27.0,
|
||||
"gain_min": 12.0,
|
||||
"p_max": 22.0,
|
||||
"nf_coef": [-5.952e-4,-6.250e-2,-1.071,28.99],
|
||||
"allowed_for_design": false
|
||||
},
|
||||
{
|
||||
"type_variety": "std_high_gain",
|
||||
"type_def": "variable_gain",
|
||||
"gain_flatmax": 35.0,
|
||||
"gain_min": 25.0,
|
||||
"p_max": 21.0,
|
||||
"nf_min": 5.5,
|
||||
"nf_max": 7.0,
|
||||
"out_voa_auto": false,
|
||||
"allowed_for_design": true
|
||||
},
|
||||
{
|
||||
"type_variety": "std_medium_gain",
|
||||
"type_def": "variable_gain",
|
||||
"gain_flatmax": 26.0,
|
||||
"gain_min": 15.0,
|
||||
"p_max": 23.0,
|
||||
"nf_min": 6.0,
|
||||
"nf_max": 10.0,
|
||||
"out_voa_auto": false,
|
||||
"allowed_for_design": true
|
||||
},
|
||||
{
|
||||
"type_variety": "std_low_gain",
|
||||
"type_def": "variable_gain",
|
||||
"gain_flatmax": 16.0,
|
||||
"gain_min": 8.0,
|
||||
"p_max": 23.0,
|
||||
"nf_min": 6.5,
|
||||
"nf_max": 11.0,
|
||||
"out_voa_auto": false,
|
||||
"allowed_for_design": true
|
||||
},
|
||||
{
|
||||
"type_variety": "high_power",
|
||||
"type_def": "variable_gain",
|
||||
"gain_flatmax": 16.0,
|
||||
"gain_min": 8.0,
|
||||
"p_max": 25.0,
|
||||
"nf_min": 9.0,
|
||||
"nf_max": 15.0,
|
||||
"out_voa_auto": false,
|
||||
"allowed_for_design": false
|
||||
},
|
||||
{
|
||||
"type_variety": "std_fixed_gain",
|
||||
"type_def": "fixed_gain",
|
||||
"gain_flatmax": 21.0,
|
||||
"gain_min": 20.0,
|
||||
"p_max": 21.0,
|
||||
"nf0": 5.5,
|
||||
"allowed_for_design": false
|
||||
},
|
||||
{
|
||||
"type_variety": "4pumps_raman",
|
||||
"type_def": "fixed_gain",
|
||||
"gain_flatmax": 12.0,
|
||||
"gain_min": 12.0,
|
||||
"p_max": 21.0,
|
||||
"nf0": -1.0,
|
||||
"allowed_for_design": false
|
||||
},
|
||||
{
|
||||
"type_variety": "hybrid_4pumps_lowgain",
|
||||
"type_def": "dual_stage",
|
||||
"raman": true,
|
||||
"gain_min": 25.0,
|
||||
"preamp_variety": "4pumps_raman",
|
||||
"booster_variety": "std_low_gain",
|
||||
"allowed_for_design": true
|
||||
},
|
||||
{
|
||||
"type_variety": "hybrid_4pumps_mediumgain",
|
||||
"type_def": "dual_stage",
|
||||
"raman": true,
|
||||
"gain_min": 25.0,
|
||||
"preamp_variety": "4pumps_raman",
|
||||
"booster_variety": "std_medium_gain",
|
||||
"allowed_for_design": true
|
||||
},
|
||||
{
|
||||
"type_variety": "medium+low_gain",
|
||||
"type_def": "dual_stage",
|
||||
"gain_min": 25.0,
|
||||
"preamp_variety": "std_medium_gain",
|
||||
"booster_variety": "std_low_gain",
|
||||
"allowed_for_design": true
|
||||
},
|
||||
{
|
||||
"type_variety": "medium+high_power",
|
||||
"type_def": "dual_stage",
|
||||
"gain_min": 25.0,
|
||||
"preamp_variety": "std_medium_gain",
|
||||
"booster_variety": "high_power",
|
||||
"allowed_for_design": false
|
||||
}
|
||||
],
|
||||
"Fiber":[{
|
||||
"type_variety": "SSMF",
|
||||
"dispersion": 1.67e-05,
|
||||
"gamma": 0.00127,
|
||||
"pmd_coef": 1.265e-15
|
||||
},
|
||||
{
|
||||
"type_variety": "NZDF",
|
||||
"dispersion": 0.5e-05,
|
||||
"gamma": 0.00146,
|
||||
"pmd_coef": 1.265e-15
|
||||
},
|
||||
{
|
||||
"type_variety": "LOF",
|
||||
"dispersion": 2.2e-05,
|
||||
"gamma": 0.000843,
|
||||
"pmd_coef": 1.265e-15
|
||||
}
|
||||
],
|
||||
"RamanFiber":[{
|
||||
"type_variety": "SSMF",
|
||||
"dispersion": 1.67e-05,
|
||||
"gamma": 0.00127,
|
||||
"pmd_coef": 1.265e-15,
|
||||
"raman_efficiency": {
|
||||
"cr":[
|
||||
0, 9.4E-06, 2.92E-05, 4.88E-05, 6.82E-05, 8.31E-05, 9.4E-05, 0.0001014, 0.0001069, 0.0001119,
|
||||
0.0001217, 0.0001268, 0.0001365, 0.000149, 0.000165, 0.000181, 0.0001977, 0.0002192, 0.0002469,
|
||||
0.0002749, 0.0002999, 0.0003206, 0.0003405, 0.0003592, 0.000374, 0.0003826, 0.0003841, 0.0003826,
|
||||
0.0003802, 0.0003756, 0.0003549, 0.0003795, 0.000344, 0.0002933, 0.0002024, 0.0001158, 8.46E-05,
|
||||
7.14E-05, 6.86E-05, 8.5E-05, 8.93E-05, 9.01E-05, 8.15E-05, 6.67E-05, 4.37E-05, 3.28E-05, 2.96E-05,
|
||||
2.65E-05, 2.57E-05, 2.81E-05, 3.08E-05, 3.67E-05, 5.85E-05, 6.63E-05, 6.36E-05, 5.5E-05, 4.06E-05,
|
||||
2.77E-05, 2.42E-05, 1.87E-05, 1.6E-05, 1.4E-05, 1.13E-05, 1.05E-05, 9.8E-06, 9.8E-06, 1.13E-05,
|
||||
1.64E-05, 1.95E-05, 2.38E-05, 2.26E-05, 2.03E-05, 1.48E-05, 1.09E-05, 9.8E-06, 1.05E-05, 1.17E-05,
|
||||
1.25E-05, 1.21E-05, 1.09E-05, 9.8E-06, 8.2E-06, 6.6E-06, 4.7E-06, 2.7E-06, 1.9E-06, 1.2E-06, 4E-07,
|
||||
2E-07, 1E-07
|
||||
],
|
||||
"frequency_offset":[
|
||||
0, 0.5e12, 1e12, 1.5e12, 2e12, 2.5e12, 3e12, 3.5e12, 4e12, 4.5e12, 5e12, 5.5e12, 6e12, 6.5e12, 7e12,
|
||||
7.5e12, 8e12, 8.5e12, 9e12, 9.5e12, 10e12, 10.5e12, 11e12, 11.5e12, 12e12, 12.5e12, 12.75e12,
|
||||
13e12, 13.25e12, 13.5e12, 14e12, 14.5e12, 14.75e12, 15e12, 15.5e12, 16e12, 16.5e12, 17e12,
|
||||
17.5e12, 18e12, 18.25e12, 18.5e12, 18.75e12, 19e12, 19.5e12, 20e12, 20.5e12, 21e12, 21.5e12,
|
||||
22e12, 22.5e12, 23e12, 23.5e12, 24e12, 24.5e12, 25e12, 25.5e12, 26e12, 26.5e12, 27e12, 27.5e12, 28e12,
|
||||
28.5e12, 29e12, 29.5e12, 30e12, 30.5e12, 31e12, 31.5e12, 32e12, 32.5e12, 33e12, 33.5e12, 34e12, 34.5e12,
|
||||
35e12, 35.5e12, 36e12, 36.5e12, 37e12, 37.5e12, 38e12, 38.5e12, 39e12, 39.5e12, 40e12, 40.5e12, 41e12,
|
||||
41.5e12, 42e12
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"Span":[{
|
||||
"power_mode":true,
|
||||
"delta_power_range_db": [-2.0, 3.0, 0.5],
|
||||
"max_fiber_lineic_loss_for_raman": 0.25,
|
||||
"target_extended_gain": 2.5,
|
||||
"max_length": 150.0,
|
||||
"length_units": "km",
|
||||
"max_loss": 28.0,
|
||||
"padding": 10.0,
|
||||
"EOL": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
}
|
||||
],
|
||||
"Roadm":[{
|
||||
"target_pch_out_db": -20.0,
|
||||
"add_drop_osnr": 38.0,
|
||||
"pmd": 0.0,
|
||||
"restrictions": {
|
||||
"preamp_variety_list":[],
|
||||
"booster_variety_list":[]
|
||||
}
|
||||
}],
|
||||
"SI":[{
|
||||
"f_min": 191.3e12,
|
||||
"baud_rate": 32e9,
|
||||
"f_max":195.1e12,
|
||||
"spacing": 50e9,
|
||||
"power_dbm": 0.0,
|
||||
"power_range_db": [0.0,0.0,1.0],
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40.0,
|
||||
"sys_margins": 2.0
|
||||
}],
|
||||
"Transceiver":[
|
||||
{
|
||||
"type_variety": "vendorA_trx-type1",
|
||||
"frequency":{
|
||||
"min": 191.35e12,
|
||||
"max": 196.1e12
|
||||
},
|
||||
"mode":[{
|
||||
"format": "mode 1",
|
||||
"baud_rate": 32e9,
|
||||
"OSNR": 11.0,
|
||||
"bit_rate": 100e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40.0,
|
||||
"min_spacing": 37.5e9,
|
||||
"cost":1.0
|
||||
},
|
||||
{
|
||||
"format": "mode 2",
|
||||
"baud_rate": 66e9,
|
||||
"OSNR": 15.0,
|
||||
"bit_rate": 200e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40.0,
|
||||
"min_spacing": 75e9,
|
||||
"cost":1.0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type_variety": "Voyager",
|
||||
"frequency":{
|
||||
"min": 191.35e12,
|
||||
"max": 196.1e12
|
||||
},
|
||||
"mode":[
|
||||
{
|
||||
"format": "mode 1",
|
||||
"baud_rate": 32e9,
|
||||
"OSNR": 12.0,
|
||||
"bit_rate": 100e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40.0,
|
||||
"min_spacing": 37.5e9,
|
||||
"cost":1.0
|
||||
},
|
||||
{
|
||||
"format": "mode 3",
|
||||
"baud_rate": 44e9,
|
||||
"OSNR": 18.0,
|
||||
"bit_rate": 300e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40.0,
|
||||
"min_spacing": 62.5e9,
|
||||
"cost":1.0
|
||||
},
|
||||
{
|
||||
"format": "mode 2",
|
||||
"baud_rate": 66e9,
|
||||
"OSNR": 21.0,
|
||||
"bit_rate": 400e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40.0,
|
||||
"min_spacing": 75e9,
|
||||
"cost":1.0
|
||||
},
|
||||
{
|
||||
"format": "mode 4",
|
||||
"baud_rate": 66e9,
|
||||
"OSNR": 16.0,
|
||||
"bit_rate": 200e9,
|
||||
"roll_off": 0.15,
|
||||
"tx_osnr": 40.0,
|
||||
"min_spacing": 75e9,
|
||||
"cost":1.0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
180
gnpy/yang/api-request-with-id.json
Normal file
180
gnpy/yang/api-request-with-id.json
Normal file
@@ -0,0 +1,180 @@
|
||||
{
|
||||
"gnpy-api:service":{
|
||||
"path-request": [
|
||||
{
|
||||
"request-id": "0",
|
||||
"source": "trx Alice",
|
||||
"destination": "trx Bob",
|
||||
"src-tp-id": "trx Alice",
|
||||
"dst-tp-id": "trx Bob",
|
||||
"bidirectional": false,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager",
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": 0,
|
||||
"M": 12
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"path_bandwidth": 100000000000.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": "1",
|
||||
"source": "trx Alice",
|
||||
"destination": "trx Bob",
|
||||
"src-tp-id": "trx Alice",
|
||||
"dst-tp-id": "trx Bob",
|
||||
"bidirectional": false,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager",
|
||||
"trx_mode": "mode 1",
|
||||
"spacing": 50000000000.0,
|
||||
"path_bandwidth": 100000000000.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": "2",
|
||||
"source": "trx Alice",
|
||||
"destination": "trx Bob",
|
||||
"src-tp-id": "trx Alice",
|
||||
"dst-tp-id": "trx Bob",
|
||||
"bidirectional": false,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager",
|
||||
"trx_mode": "mode 2",
|
||||
"spacing": 100000000000.0,
|
||||
"path_bandwidth": 100000000000.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": "3",
|
||||
"source": "trx Alice",
|
||||
"destination": "trx Bob",
|
||||
"src-tp-id": "trx Alice",
|
||||
"dst-tp-id": "trx Bob",
|
||||
"bidirectional": true,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager",
|
||||
"spacing": 50000000000.0,
|
||||
"path_bandwidth": 100000000000.0
|
||||
}
|
||||
},
|
||||
"explicit-route-objects": {
|
||||
"route-object-include-exclude": [
|
||||
{
|
||||
"explicit-route-usage": "route-include-ero",
|
||||
"index": 0,
|
||||
"num-unnum-hop": {
|
||||
"node-id": "roadm Carol",
|
||||
"link-tp-id": "link-tp-id is not used",
|
||||
"hop-type": "LOOSE"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": "4",
|
||||
"source": "trx Alice",
|
||||
"destination": "trx Bob",
|
||||
"src-tp-id": "trx Alice",
|
||||
"dst-tp-id": "trx Bob",
|
||||
"bidirectional": true,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": -284,
|
||||
"M": 12
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"path_bandwidth": 100000000000.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": "5",
|
||||
"source": "trx Bob1",
|
||||
"destination": "trx Carol1",
|
||||
"src-tp-id": "trx Bob1",
|
||||
"dst-tp-id": "trx Carol1",
|
||||
"bidirectional": true,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "vendorA_trx-type1",
|
||||
"spacing": 100000000000.0,
|
||||
"path_bandwidth": 100000000000.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": "6",
|
||||
"source": "trx Bob1",
|
||||
"destination": "trx Carol1",
|
||||
"src-tp-id": "trx Bob1",
|
||||
"dst-tp-id": "trx Carol1",
|
||||
"bidirectional": true,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager",
|
||||
"trx_mode": "mode 1",
|
||||
"spacing": 50000000000.0,
|
||||
"path_bandwidth": 100000000000.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": "7",
|
||||
"source": "trx Bob1",
|
||||
"destination": "trx Carol",
|
||||
"src-tp-id": "trx Bob1",
|
||||
"dst-tp-id": "trx Carol",
|
||||
"bidirectional": true,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager",
|
||||
"trx_mode": "mode 1",
|
||||
"spacing": 50000000000.0,
|
||||
"path_bandwidth": 100000000000.0
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"synchronization": [
|
||||
{
|
||||
"synchronization-id": "1",
|
||||
"svec": {
|
||||
"relaxable": false,
|
||||
"disjointness": "node link",
|
||||
"request-id-number": [
|
||||
"1",
|
||||
"0"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"gnpy-api:topology_id": "5cf39d4b-be10-4ee9-b38b-7f4db7403db7",
|
||||
"gnpy-api:equipment_id": "9ed86e34-9d41-41b2-b8e4-984ca0901d47"
|
||||
|
||||
}
|
||||
2777
gnpy/yang/api-request.json
Normal file
2777
gnpy/yang/api-request.json
Normal file
File diff suppressed because it is too large
Load Diff
901
gnpy/yang/api-topology.json
Normal file
901
gnpy/yang/api-topology.json
Normal file
@@ -0,0 +1,901 @@
|
||||
{
|
||||
"elements": [
|
||||
{
|
||||
"uid": "trx Alice",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Alice",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "trx Bob",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "trx Carol",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "trx Bob1",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "trx Carol1",
|
||||
"type": "Transceiver",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Alice",
|
||||
"type": "Roadm",
|
||||
"params": {
|
||||
"target_pch_out_db": -20.0,
|
||||
"restrictions": {
|
||||
"preamp_variety_list": [],
|
||||
"booster_variety_list": []
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Alice",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Bob",
|
||||
"type": "Roadm",
|
||||
"params": {
|
||||
"target_pch_out_db": -20.0,
|
||||
"restrictions": {
|
||||
"preamp_variety_list": [],
|
||||
"booster_variety_list": []
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Carol",
|
||||
"type": "Roadm",
|
||||
"params": {
|
||||
"target_pch_out_db": -20.0,
|
||||
"restrictions": {
|
||||
"preamp_variety_list": [],
|
||||
"booster_variety_list": []
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Bob1",
|
||||
"type": "Roadm",
|
||||
"params": {
|
||||
"target_pch_out_db": -20.0,
|
||||
"restrictions": {
|
||||
"preamp_variety_list": [],
|
||||
"booster_variety_list": []
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "roadm Carol1",
|
||||
"type": "Roadm",
|
||||
"params": {
|
||||
"target_pch_out_db": -20.0,
|
||||
"restrictions": {
|
||||
"preamp_variety_list": [],
|
||||
"booster_variety_list": []
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Alice → Bob)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 75.0,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Bob → Carol)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80.0,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Bob1 → Carol1)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80.0,
|
||||
"loss_coef": 0.5,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Carol → Dan)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 83.0,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Dan → Alice)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Bob → Alice)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 75.0,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Carol → Bob)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80.0,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Carol1 → Bob1)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80.0,
|
||||
"loss_coef": 0.5,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Dan → Carol)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 83.0,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Alice → Dan)-",
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km",
|
||||
"att_in": 0.0,
|
||||
"con_in": 0.0,
|
||||
"con_out": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "null",
|
||||
"region": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Alice to Bob",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 18.5,
|
||||
"delta_p": -1.5,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Alice",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Bob to Carol",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 19.0,
|
||||
"delta_p": -1.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Bob1 to Carol1",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 19.0,
|
||||
"delta_p": -1.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Carol to Dan",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 19.0,
|
||||
"delta_p": -1.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Dan to Alice",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 15.600000000000001,
|
||||
"delta_p": -2.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Dan",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Bob to Alice",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 18.5,
|
||||
"delta_p": -1.5,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Alice to Dan",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 18.0,
|
||||
"delta_p": -2.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Alice",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Carol to Bob",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 19.0,
|
||||
"delta_p": -1.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "east edfa in Carol1 to Bob1",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 19.0,
|
||||
"delta_p": -1.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Alice to Bob",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 16.5,
|
||||
"delta_p": 0.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Alice",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Bob to Carol",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 17.0,
|
||||
"delta_p": 0.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Bob1 to Carol1",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 17.0,
|
||||
"delta_p": 0.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Carol to Dan",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 17.6,
|
||||
"delta_p": 0.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Dan to Alice",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 13.0,
|
||||
"delta_p": -1.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Dan",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Bob to Alice",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 16.5,
|
||||
"delta_p": 0.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Bob",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Alice to Dan",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 14.0,
|
||||
"delta_p": 0.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Alice",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Carol to Bob",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 17.0,
|
||||
"delta_p": 0.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "west edfa in Carol1 to Bob1",
|
||||
"type": "Edfa",
|
||||
"type_variety": "std_medium_gain",
|
||||
"operational": {
|
||||
"gain_target": 17.0,
|
||||
"delta_p": 0.0,
|
||||
"tilt_target": 0.0,
|
||||
"out_voa": 0.0
|
||||
},
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0,
|
||||
"city": "Carol",
|
||||
"region": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"from_node": "trx Alice",
|
||||
"to_node": "roadm Alice"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Bob",
|
||||
"to_node": "roadm Bob"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Bob1",
|
||||
"to_node": "roadm Bob1"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Carol",
|
||||
"to_node": "roadm Carol"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Carol1",
|
||||
"to_node": "roadm Carol1"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Alice",
|
||||
"to_node": "east edfa in Alice to Bob"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Alice",
|
||||
"to_node": "east edfa in Alice to Dan"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Alice",
|
||||
"to_node": "trx Alice"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Bob",
|
||||
"to_node": "east edfa in Bob to Alice"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Bob1",
|
||||
"to_node": "east edfa in Bob1 to Carol1"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Bob",
|
||||
"to_node": "east edfa in Bob to Carol"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Bob",
|
||||
"to_node": "trx Bob"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Bob1",
|
||||
"to_node": "trx Bob1"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Carol",
|
||||
"to_node": "east edfa in Carol to Bob"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Carol1",
|
||||
"to_node": "east edfa in Carol1 to Bob1"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Carol",
|
||||
"to_node": "east edfa in Carol to Dan"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Carol",
|
||||
"to_node": "trx Carol"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Carol1",
|
||||
"to_node": "trx Carol1"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Alice → Bob)-",
|
||||
"to_node": "west edfa in Bob to Alice"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bob → Carol)-",
|
||||
"to_node": "west edfa in Carol to Bob"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bob1 → Carol1)-",
|
||||
"to_node": "west edfa in Carol1 to Bob1"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Carol → Dan)-",
|
||||
"to_node": "east edfa in Dan to Alice"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Dan → Alice)-",
|
||||
"to_node": "west edfa in Alice to Dan"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Bob → Alice)-",
|
||||
"to_node": "west edfa in Alice to Bob"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Carol → Bob)-",
|
||||
"to_node": "west edfa in Bob to Carol"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Carol1 → Bob1)-",
|
||||
"to_node": "west edfa in Bob1 to Carol1"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Dan → Carol)-",
|
||||
"to_node": "west edfa in Carol to Dan"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Alice → Dan)-",
|
||||
"to_node": "west edfa in Dan to Alice"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Alice to Bob",
|
||||
"to_node": "fiber (Alice → Bob)-"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Bob to Carol",
|
||||
"to_node": "fiber (Bob → Carol)-"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Bob1 to Carol1",
|
||||
"to_node": "fiber (Bob1 → Carol1)-"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Carol to Dan",
|
||||
"to_node": "fiber (Carol → Dan)-"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Dan to Alice",
|
||||
"to_node": "fiber (Dan → Alice)-"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Bob to Alice",
|
||||
"to_node": "fiber (Bob → Alice)-"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Alice to Dan",
|
||||
"to_node": "fiber (Alice → Dan)-"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Carol to Bob",
|
||||
"to_node": "fiber (Carol → Bob)-"
|
||||
},
|
||||
{
|
||||
"from_node": "east edfa in Carol1 to Bob1",
|
||||
"to_node": "fiber (Carol1 → Bob1)-"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Alice to Bob",
|
||||
"to_node": "roadm Alice"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Bob to Carol",
|
||||
"to_node": "roadm Bob"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Bob1 to Carol1",
|
||||
"to_node": "roadm Bob1"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Bob1 to Carol1",
|
||||
"to_node": "roadm Bob1"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Carol to Dan",
|
||||
"to_node": "roadm Carol"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Dan to Alice",
|
||||
"to_node": "fiber (Dan → Carol)-"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Bob to Alice",
|
||||
"to_node": "roadm Bob"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Alice to Dan",
|
||||
"to_node": "roadm Alice"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Carol to Bob",
|
||||
"to_node": "roadm Carol"
|
||||
},
|
||||
{
|
||||
"from_node": "west edfa in Carol1 to Bob1",
|
||||
"to_node": "roadm Carol1"
|
||||
}
|
||||
]
|
||||
}
|
||||
53
gnpy/yang/gnpy-api@2020-10-22.yang
Normal file
53
gnpy/yang/gnpy-api@2020-10-22.yang
Normal file
@@ -0,0 +1,53 @@
|
||||
module gnpy-api {
|
||||
yang-version 1.1;
|
||||
namespace "gnpy:gnpy-api";
|
||||
prefix gnpyapi;
|
||||
|
||||
import gnpy-network-topology {
|
||||
prefix gnpynt;
|
||||
}
|
||||
import gnpy-path-computation-simplified {
|
||||
prefix gnpypc;
|
||||
}
|
||||
import gnpy-eqpt-config {
|
||||
prefix gnpyeqpt;
|
||||
}
|
||||
|
||||
organization
|
||||
"Telecom Infra Project OOPT PSE Working Group";
|
||||
contact
|
||||
"WG Web: <https://github.com/Telecominfraproject/oopt-gnpy>
|
||||
contact: <mailto:ahmed.triki@orange.com>
|
||||
contact: <mailto:esther.lerouzic@orange.com>
|
||||
";
|
||||
description
|
||||
"YANG model for gnpy api input for path computation - TransportPCE preversion";
|
||||
|
||||
revision 2020-10-22 {
|
||||
description
|
||||
"draft for experimental/2020-candi";
|
||||
reference
|
||||
"YANG model for api input for path computation with gnpy";
|
||||
}
|
||||
|
||||
container service {
|
||||
description
|
||||
"Describe the service file to connect to gnpy";
|
||||
uses gnpypc:service;
|
||||
}
|
||||
container result {
|
||||
uses gnpypc:result;
|
||||
description
|
||||
"Describe the response object to gnpy";
|
||||
}
|
||||
container topology {
|
||||
description
|
||||
"Describe the topology file to connect to gnpy";
|
||||
uses gnpynt:topo;
|
||||
}
|
||||
container equipment {
|
||||
description
|
||||
"Describe the equipment library to connect to gnpy";
|
||||
uses gnpyeqpt:eqpt;
|
||||
}
|
||||
}
|
||||
78
gnpy/yang/gnpy-api@2021-01-06.yang
Normal file
78
gnpy/yang/gnpy-api@2021-01-06.yang
Normal file
@@ -0,0 +1,78 @@
|
||||
module gnpy-api {
|
||||
yang-version 1.1;
|
||||
namespace "gnpy:gnpy-api";
|
||||
prefix gnpyapi;
|
||||
|
||||
import gnpy-network-topology {
|
||||
prefix gnpynt;
|
||||
}
|
||||
import gnpy-path-computation-simplified {
|
||||
prefix gnpypc;
|
||||
}
|
||||
import gnpy-eqpt-config {
|
||||
prefix gnpyeqpt;
|
||||
}
|
||||
import ietf-yang-types {
|
||||
prefix ietftypes;
|
||||
}
|
||||
|
||||
organization
|
||||
"Telecom Infra Project OOPT PSE Working Group";
|
||||
contact
|
||||
"WG Web: <https://github.com/Telecominfraproject/oopt-gnpy>
|
||||
contact: <mailto:ahmed.triki@orange.com>
|
||||
contact: <mailto:esther.lerouzic@orange.com>
|
||||
";
|
||||
description
|
||||
"YANG model for gnpy api input for path computation - TransportPCE preversion";
|
||||
|
||||
revision 2021-01-06 {
|
||||
description
|
||||
"draft for experimental/2020-candi.
|
||||
Add the possibility to use a topology_id or an equipment_id
|
||||
";
|
||||
reference
|
||||
"YANG model for api input for path computation with gnpy";
|
||||
}
|
||||
|
||||
container service {
|
||||
description
|
||||
"Describe the service file to connect to gnpy";
|
||||
uses gnpypc:service;
|
||||
}
|
||||
container result {
|
||||
uses gnpypc:result;
|
||||
description
|
||||
"Describe the response object to gnpy";
|
||||
}
|
||||
choice topo {
|
||||
case explicit {
|
||||
container topology {
|
||||
description
|
||||
"Describe the topology file to connect to gnpy";
|
||||
uses gnpynt:topo;
|
||||
}
|
||||
}
|
||||
case id {
|
||||
leaf topology_id {
|
||||
type ietftypes:uuid;
|
||||
mandatory true;
|
||||
}
|
||||
}
|
||||
}
|
||||
choice eqpt {
|
||||
case explicit {
|
||||
container equipment {
|
||||
description
|
||||
"Describe the equipment library to connect to gnpy";
|
||||
uses gnpyeqpt:eqpt;
|
||||
}
|
||||
}
|
||||
case id {
|
||||
leaf equipment_id {
|
||||
type ietftypes:uuid;
|
||||
mandatory true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
442
gnpy/yang/gnpy-eqpt-config@2020-10-22.yang
Normal file
442
gnpy/yang/gnpy-eqpt-config@2020-10-22.yang
Normal file
@@ -0,0 +1,442 @@
|
||||
module gnpy-eqpt-config {
|
||||
yang-version 1;
|
||||
namespace "gnpy:gnpy-eqpt-config";
|
||||
|
||||
prefix "gnpyeqpt";
|
||||
|
||||
organization
|
||||
"Telecom Infra Project OOPT PSE
|
||||
Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <https://github.com/Telecominfraproject/oopt-gnpy>
|
||||
contact: <mailto:ahmed.triki@orange.com>
|
||||
contact: <mailto:esther.lerouzic@orange.com>
|
||||
";
|
||||
|
||||
description "Base YANG model for gnpy equipment library input for path computation - 2020 - candi preversion";
|
||||
|
||||
revision "2020-10-22" {
|
||||
description "draft for experimental/2020-candi";
|
||||
reference "Base YANG model for equipment library input for path computation with gnpy";
|
||||
}
|
||||
|
||||
/*
|
||||
* Identities
|
||||
|
||||
|
||||
identity edfa-type-def {
|
||||
description "base identity for variable gain and fixed gain";
|
||||
}
|
||||
|
||||
identity variable-gain{
|
||||
base edfa-type-def ;
|
||||
description "'variable_gain' is a simplified model simulating a 2-coil
|
||||
EDFA with internal, input and output VOAs. The NF vs gain response is calculated
|
||||
accordingly based on the input parameters: nf_min, nf_max, and gain_flatmax. It
|
||||
is not a simple interpolation but a 2-stage NF calculation.";
|
||||
}
|
||||
|
||||
identity fixed-gain{
|
||||
base edfa-type-def ;
|
||||
description "'fixed_gain' is a fixed gain model. NF == Cte == nf0 if gain_min < gain < gain_flatmax";
|
||||
}
|
||||
|
||||
identity fiber-variety {
|
||||
description "base identity for fiber variety";
|
||||
}
|
||||
|
||||
identity transceiver-variety {
|
||||
description "base identity for transceiver variety";
|
||||
}
|
||||
|
||||
*/
|
||||
grouping variable-gain {
|
||||
leaf nf_min {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB;
|
||||
}
|
||||
leaf nf_max {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB;
|
||||
}
|
||||
leaf out_voa_auto{
|
||||
type boolean ;
|
||||
description "auto_design feature to optimize the amplifier output VOA. If true, output VOA is present
|
||||
and will be used to push amplifier gain to its maximum, within EOL power margins.";
|
||||
}
|
||||
}
|
||||
|
||||
grouping fixed-gain{
|
||||
leaf nf0 {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB;
|
||||
}
|
||||
}
|
||||
|
||||
grouping no-type-def{
|
||||
leaf advanced_config_from_json {
|
||||
type string ;
|
||||
description " filename with json edfa";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
grouping openroadm{
|
||||
leaf-list nf_coef {
|
||||
type decimal64 {
|
||||
fraction-digits 5;
|
||||
}
|
||||
//default [8.1e-4,6.142e-2,1.558,19.97] ;
|
||||
}
|
||||
}
|
||||
|
||||
grouping dual-stage {
|
||||
leaf raman {
|
||||
type boolean;
|
||||
}
|
||||
leaf preamp_variety {
|
||||
type leafref {
|
||||
path "../../Edfa/type_variety";
|
||||
}
|
||||
}
|
||||
leaf booster_variety {
|
||||
type leafref {
|
||||
path "../../Edfa/type_variety";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping edfa-common {
|
||||
leaf allowed_for_design{
|
||||
type boolean ;
|
||||
description "If false, the amplifier will not be picked by auto-design but it can still be used as a
|
||||
manual input (from JSON or Excel template topology files.)";
|
||||
}
|
||||
leaf gain_flatmax {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB;
|
||||
}
|
||||
leaf gain_min {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB;
|
||||
}
|
||||
leaf p_max {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dBm;
|
||||
}
|
||||
leaf type_def {
|
||||
type identityref{
|
||||
base edfa-type-def ;
|
||||
}
|
||||
}
|
||||
choice type_of_model {
|
||||
case variable-gain {
|
||||
when "type_def = 'variable-gain'";
|
||||
uses variable-gain ;
|
||||
}
|
||||
case fixed-gain{
|
||||
when "type_def = 'fixed-gain'";
|
||||
uses fixed-gain;
|
||||
}
|
||||
case no-type-def{
|
||||
when "type_def = 'no-type-def'";
|
||||
uses no-type-def;
|
||||
}
|
||||
case openroadm{
|
||||
when "type_def = 'openroadm'";
|
||||
uses openroadm;
|
||||
}
|
||||
case dual_stage {
|
||||
when "type_def = 'dual_stage'";
|
||||
uses dual-stage ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping common-fiber {
|
||||
description "common parameters for fiber and raman fiber";
|
||||
leaf type_variety {
|
||||
type string ;
|
||||
}
|
||||
description "a unique name to ID the fiber in the JSON or Excel template topology input file";
|
||||
leaf dispersion{
|
||||
type decimal64 {
|
||||
fraction-digits 8;
|
||||
}
|
||||
units s.m-1.m-1;
|
||||
}
|
||||
leaf gamma{
|
||||
type decimal64 {
|
||||
fraction-digits 8;
|
||||
}
|
||||
units w-1.m-1 ;
|
||||
description "2pi.n2/(lambda*Aeff) (w-2.m-1)";
|
||||
}
|
||||
leaf pmd_coef{
|
||||
type decimal64 {
|
||||
fraction-digits 16;
|
||||
}
|
||||
units s.sqrt(m)-1;
|
||||
}
|
||||
}
|
||||
|
||||
grouping eqpt{
|
||||
list Edfa {
|
||||
key type_variety;
|
||||
leaf type_variety {
|
||||
type string;
|
||||
description "a unique name to ID the amplifier in the JSON/Excel template topology input file";
|
||||
}
|
||||
uses edfa-common;
|
||||
}
|
||||
|
||||
list Fiber {
|
||||
key type_variety;
|
||||
uses common-fiber;
|
||||
}
|
||||
|
||||
list RamanFiber {
|
||||
uses common-fiber;
|
||||
container raman_efficiency {
|
||||
leaf-list cr {
|
||||
type decimal64 {
|
||||
fraction-digits 8;
|
||||
}
|
||||
}
|
||||
leaf-list frequency_offset {
|
||||
type decimal64 {
|
||||
fraction-digits 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list Span {
|
||||
leaf power_mode {
|
||||
type boolean ;
|
||||
}
|
||||
leaf-list delta_power_range_db {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf max_length {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units km;
|
||||
default 150.0 ;
|
||||
}
|
||||
leaf max_loss {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB;
|
||||
}
|
||||
leaf max_fiber_lineic_loss_for_raman {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB.km-1;
|
||||
}
|
||||
leaf target_extended_gain {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB;
|
||||
}
|
||||
leaf length_units{
|
||||
type string ;
|
||||
default "km";
|
||||
}
|
||||
leaf padding{
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
default 10.0 ;
|
||||
}
|
||||
leaf EOL{
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
default 0.0 ;
|
||||
}
|
||||
leaf con_in{
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
default 0.0 ;
|
||||
}
|
||||
leaf con_out{
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
default 0.0 ;
|
||||
}
|
||||
}
|
||||
|
||||
list Roadm {
|
||||
leaf target_pch_out_db {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf add_drop_osnr {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf pmd {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
container restrictions {
|
||||
leaf-list preamp_variety_list {
|
||||
type string;
|
||||
}
|
||||
leaf-list booster_variety_list {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list SI {
|
||||
leaf f_min {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf f_max {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf baud_rate {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf spacing {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf power_dbm {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf-list power_range_db {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf roll_off {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf tx_osnr {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
leaf sys_margins {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list Transceiver {
|
||||
leaf type_variety {
|
||||
type string ;
|
||||
description "a unique name to ID the transceiver in the JSON or Excel template topology input file";
|
||||
}
|
||||
container frequency {
|
||||
leaf min {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units Hz ;
|
||||
}
|
||||
leaf max {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units Hz ;
|
||||
}
|
||||
description "Min/max frequency of transponder eg 191.35e12 and 196.1e12";
|
||||
}
|
||||
list mode {
|
||||
leaf format {
|
||||
type string ;
|
||||
description "unique name of the mode";
|
||||
}
|
||||
leaf baud_rate {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units baud ;
|
||||
description "baud_rate";
|
||||
}
|
||||
leaf OSNR {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB ;
|
||||
description "min required OSNR in 0.1nm (dB)";
|
||||
}
|
||||
leaf tx_osnr {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units dB ;
|
||||
description "min required OSNR in 0.1nm (dB)";
|
||||
}
|
||||
leaf min_spacing {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units GHz ;
|
||||
description "...";
|
||||
}
|
||||
leaf bit_rate {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units bit/s ;
|
||||
description "bit rate";
|
||||
}
|
||||
leaf roll_off {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
description "...";
|
||||
}
|
||||
leaf cost {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
description "arbitrary unit";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
300
gnpy/yang/gnpy-network-topology@2020-10-22.yang
Normal file
300
gnpy/yang/gnpy-network-topology@2020-10-22.yang
Normal file
@@ -0,0 +1,300 @@
|
||||
module gnpy-network-topology {
|
||||
yang-version 1.1;
|
||||
namespace "gnpy:gnpy-network-topology";
|
||||
prefix gnpynt;
|
||||
|
||||
organization
|
||||
"Telecom Infra Project OOPT PSE Working Group";
|
||||
contact
|
||||
"WG Web: <https://github.com/Telecominfraproject/oopt-gnpy>
|
||||
contact: <mailto:ahmed.triki@orange.com>
|
||||
contact: <mailto:esther.lerouzic@orange.com>
|
||||
";
|
||||
description
|
||||
"YANG model for gnpy network input for path computation - 2020 - candi preversion";
|
||||
|
||||
revision 2020-10-22 {
|
||||
description
|
||||
"draft for experimental/2020-candi";
|
||||
reference
|
||||
"YANG model for network input for path computation with gnpy";
|
||||
}
|
||||
|
||||
identity type-element {
|
||||
description
|
||||
"Base identity for element type";
|
||||
}
|
||||
|
||||
identity Transceiver {
|
||||
base type-element;
|
||||
description
|
||||
" Transceiver element";
|
||||
}
|
||||
|
||||
identity Fiber {
|
||||
base type-element;
|
||||
description
|
||||
"Fiber element (unidirectional)";
|
||||
}
|
||||
|
||||
identity Roadm {
|
||||
base type-element;
|
||||
description
|
||||
"Roadm element";
|
||||
}
|
||||
|
||||
identity Edfa {
|
||||
base type-element;
|
||||
description
|
||||
"Edfa element";
|
||||
}
|
||||
|
||||
identity Fused {
|
||||
base type-element;
|
||||
description
|
||||
"Fused element ; non amplified connection between two fiber spans ;
|
||||
can be used to model optical distribution frame, or losses due to
|
||||
connectors or fused in a span";
|
||||
}
|
||||
|
||||
identity length-unit {
|
||||
description
|
||||
"length unit";
|
||||
}
|
||||
|
||||
identity km {
|
||||
base length-unit;
|
||||
description
|
||||
"kilometers";
|
||||
}
|
||||
|
||||
identity m {
|
||||
base length-unit;
|
||||
description
|
||||
"meter";
|
||||
}
|
||||
|
||||
typedef Coordinate {
|
||||
type decimal64 {
|
||||
fraction-digits 6;
|
||||
}
|
||||
}
|
||||
|
||||
typedef Coef {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
|
||||
grouping location-attributes {
|
||||
container location {
|
||||
leaf city {
|
||||
type string;
|
||||
mandatory true;
|
||||
}
|
||||
leaf region {
|
||||
type string;
|
||||
mandatory true;
|
||||
}
|
||||
leaf latitude {
|
||||
type Coordinate;
|
||||
mandatory true;
|
||||
}
|
||||
leaf longitude {
|
||||
type Coordinate;
|
||||
mandatory true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping fiber-params {
|
||||
description
|
||||
".....";
|
||||
leaf length {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
mandatory true;
|
||||
}
|
||||
leaf loss_coef {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
mandatory true;
|
||||
units db/km;
|
||||
description "Loss coefficient of the fiber span (dB/km)";
|
||||
}
|
||||
leaf length_units {
|
||||
type identityref {
|
||||
base length-unit;
|
||||
}
|
||||
mandatory true;
|
||||
}
|
||||
leaf att_in {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units "dB";
|
||||
mandatory true;
|
||||
}
|
||||
leaf con_in {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units "dB";
|
||||
mandatory true;
|
||||
}
|
||||
leaf con_out {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units "dB";
|
||||
mandatory true;
|
||||
}
|
||||
}
|
||||
|
||||
grouping edfa-params {
|
||||
container operational {
|
||||
description
|
||||
"Operational values for the Edfa ";
|
||||
leaf gain_target {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units "dB";
|
||||
mandatory true;
|
||||
description
|
||||
"gain target of the amplifier (before VOA and after att_in)";
|
||||
}
|
||||
leaf tilt_target {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
mandatory true;
|
||||
description
|
||||
"..";
|
||||
}
|
||||
leaf out_voa {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units "dB";
|
||||
mandatory true;
|
||||
description
|
||||
"..";
|
||||
}
|
||||
leaf delta_p {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units "dB";
|
||||
mandatory true;
|
||||
description
|
||||
"per channel target output power delta with respect to power setting in SI";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping roadm-params {
|
||||
leaf target_pch_out_db {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units "dB";
|
||||
description
|
||||
"..";
|
||||
}
|
||||
container restrictions {
|
||||
leaf-list preamp_variety_list {
|
||||
type string;
|
||||
description
|
||||
"List of authorized preamp type-variety";
|
||||
}
|
||||
leaf-list booster_variety_list {
|
||||
type string;
|
||||
description
|
||||
"List of authorized booster type-variety";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping transceiver-params;
|
||||
|
||||
grouping fused-params{
|
||||
leaf loss {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
units "dB";
|
||||
description
|
||||
"Concentrated loss of the fused element";
|
||||
}
|
||||
}
|
||||
|
||||
grouping element-type-choice {
|
||||
choice element-type {
|
||||
case Edfa {
|
||||
when "type = 'Edfa'";
|
||||
uses edfa-params;
|
||||
}
|
||||
case FiberRoadm {
|
||||
container params {
|
||||
choice fiberroadmfused {
|
||||
case Fiber {
|
||||
when "type = 'Fiber'";
|
||||
uses fiber-params;
|
||||
}
|
||||
case Roadm {
|
||||
when "type = 'Roadm'";
|
||||
uses roadm-params;
|
||||
}
|
||||
case Fused {
|
||||
when "type = 'Fused'";
|
||||
uses fused-params;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case Transceiver {
|
||||
when "type = 'Transceiver'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
grouping topo {
|
||||
list elements {
|
||||
key "uid";
|
||||
leaf uid {
|
||||
type string;
|
||||
}
|
||||
leaf type {
|
||||
type identityref {
|
||||
base type-element;
|
||||
}
|
||||
mandatory true;
|
||||
}
|
||||
leaf type_variety {
|
||||
type string;
|
||||
mandatory false;
|
||||
}
|
||||
container metadata {
|
||||
uses location-attributes;
|
||||
}
|
||||
uses element-type-choice;
|
||||
}
|
||||
list connections {
|
||||
config false;
|
||||
leaf from_node {
|
||||
type leafref {
|
||||
path "../../elements/uid";
|
||||
}
|
||||
}
|
||||
leaf to_node {
|
||||
type leafref {
|
||||
path "../../elements/uid";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
559
gnpy/yang/gnpy-path-computation-simplified@2020-10-22.yang
Normal file
559
gnpy/yang/gnpy-path-computation-simplified@2020-10-22.yang
Normal file
@@ -0,0 +1,559 @@
|
||||
module gnpy-path-computation-simplified {
|
||||
yang-version 1.1;
|
||||
namespace "gnpy:path";
|
||||
|
||||
prefix "gnpypc";
|
||||
|
||||
organization
|
||||
"Telecom Infra Project OOPT PSE Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <https://github.com/Telecominfraproject/oopt-gnpy>
|
||||
contact: <mailto:ahmed.triki@orange.com>
|
||||
contact: <mailto:esther.lerouzic@orange.com>
|
||||
";
|
||||
|
||||
description "YANG model for gnpy path computation simplified for - 2020 - candi preversion";
|
||||
|
||||
revision "2020-10-22" {
|
||||
description
|
||||
"draft for experimental/2020-candi";
|
||||
reference
|
||||
"YANG model for path computation with gnpy inputs";
|
||||
}
|
||||
|
||||
grouping effective-freq-slot{
|
||||
/* content copied from ietf-flexi-grid-media-channel, because only M and N are needed
|
||||
from the initial grouping.
|
||||
*/
|
||||
description "The effective frequency slot is an attribute
|
||||
of a media channel and, being a frequency slot, it is
|
||||
described by its nominal central frequency and slot
|
||||
width";
|
||||
reference "rfc7698";
|
||||
leaf N {
|
||||
type uint32;
|
||||
description
|
||||
"Is used to determine the Nominal Central
|
||||
Frequency. The set of nominal central frequencies
|
||||
can be built using the following expression:
|
||||
f = 193.1 THz + n x 0.00625 THz,
|
||||
where 193.1 THz is ITU-T ''anchor frequency'' for
|
||||
transmission over the C band, n is a positive or
|
||||
negative integer including 0.";
|
||||
reference "rfc7698";
|
||||
}
|
||||
leaf M {
|
||||
type int32;
|
||||
description
|
||||
"Is used to determine the slot width. A slot width
|
||||
is constrained to be M x SWG (that is, M x 12.5 GHz),
|
||||
where M is an integer greater than or equal to 1.";
|
||||
reference "rfc7698";
|
||||
}
|
||||
}
|
||||
|
||||
grouping gnpy-specific-parameters{
|
||||
description
|
||||
"This grouping defines the gnpy specific parameters for requests.";
|
||||
leaf technology {
|
||||
type string;
|
||||
default "flexi-grid";
|
||||
description
|
||||
"Data plane technology type.";
|
||||
}
|
||||
leaf trx_type {
|
||||
type string ;
|
||||
mandatory true;
|
||||
description "name of the transponder type (to be read from equipment library";
|
||||
|
||||
}
|
||||
leaf trx_mode {
|
||||
type string;
|
||||
description "name of the transponder mode (to be read from equipment library";
|
||||
|
||||
}
|
||||
list effective-freq-slot {
|
||||
key "N";
|
||||
uses effective-freq-slot ;
|
||||
}
|
||||
leaf spacing {
|
||||
mandatory true;
|
||||
type decimal64 {
|
||||
fraction-digits 1;
|
||||
}
|
||||
units Hz;
|
||||
description
|
||||
"It is the spacing between channels assuming full load with
|
||||
same channels as the requested one. multiple of 12.5 GHz";
|
||||
|
||||
}
|
||||
leaf max-nb-of-channel{
|
||||
type int32;
|
||||
description "Nb of channel to take into account for the full load case.
|
||||
";
|
||||
|
||||
}
|
||||
leaf output-power{
|
||||
type decimal64 {
|
||||
fraction-digits 5;
|
||||
}
|
||||
units W;
|
||||
description "optical power setting to be used for the propagation";
|
||||
|
||||
}
|
||||
leaf path_bandwidth{
|
||||
type decimal64 {
|
||||
fraction-digits 5;
|
||||
}
|
||||
mandatory true;
|
||||
units bit/s;
|
||||
description "Capacity required";
|
||||
}
|
||||
}
|
||||
|
||||
identity SNR-bandwidth {
|
||||
base path-metric-type;
|
||||
description
|
||||
"A metric that records SNR in signal bandwidth";
|
||||
}
|
||||
|
||||
identity OSNR-bandwidth {
|
||||
base path-metric-type;
|
||||
description
|
||||
"A metric that records OSNR in signal bandwidth";
|
||||
}
|
||||
|
||||
identity SNR-0.1nm {
|
||||
base path-metric-type;
|
||||
description
|
||||
"A metric that records SNR in 0.1nm";
|
||||
}
|
||||
|
||||
identity OSNR-0.1nm {
|
||||
base path-metric-type;
|
||||
description
|
||||
"A metric that records OSNR in 0.1nm";
|
||||
}
|
||||
|
||||
identity reference_power {
|
||||
base path-metric-type;
|
||||
description
|
||||
"to be revised";
|
||||
}
|
||||
|
||||
identity path_bandwidth {
|
||||
base path-metric-type;
|
||||
description
|
||||
"to be revised";
|
||||
}
|
||||
|
||||
grouping transponder{
|
||||
leaf transponder-type {
|
||||
type string ;
|
||||
description
|
||||
"transponder type.";
|
||||
}
|
||||
leaf transponder-mode {
|
||||
type string ;
|
||||
description
|
||||
"transponder mode.";
|
||||
}
|
||||
}
|
||||
|
||||
grouping hop-attribute{
|
||||
description
|
||||
"This grouping defines the hop attribute parameters for request or response";
|
||||
choice hop-type{
|
||||
case tsp {
|
||||
container transponder{
|
||||
uses transponder ;
|
||||
}
|
||||
}
|
||||
case regen {
|
||||
container regenerator{
|
||||
leaf regenerator-id{
|
||||
type string ;
|
||||
}
|
||||
uses transponder ;
|
||||
}
|
||||
}
|
||||
case pow {
|
||||
container optical-power{
|
||||
leaf optical-power{
|
||||
type decimal64 {
|
||||
fraction-digits 5;
|
||||
}
|
||||
units W;
|
||||
description "not used yet. hop output (input??) power";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
identity path-metric-type {
|
||||
description
|
||||
"Base identity for path metric type";
|
||||
}
|
||||
|
||||
identity route-usage-type {
|
||||
description
|
||||
"Base identity for route usage";
|
||||
}
|
||||
|
||||
identity route-include-ero {
|
||||
base route-usage-type;
|
||||
description
|
||||
"Include ERO from route";
|
||||
}
|
||||
|
||||
identity route-exclude-ero {
|
||||
base route-usage-type;
|
||||
description
|
||||
"Exclude ERO from route";
|
||||
}
|
||||
|
||||
identity route-exclude-srlg {
|
||||
base route-usage-type;
|
||||
description
|
||||
"Exclude SRLG from route";
|
||||
}
|
||||
|
||||
typedef te-hop-type {
|
||||
type enumeration {
|
||||
enum LOOSE {
|
||||
description
|
||||
"loose hop in an explicit path";
|
||||
}
|
||||
enum STRICT {
|
||||
description
|
||||
"strict hop in an explicit path";
|
||||
}
|
||||
}
|
||||
description
|
||||
"enumerated type for specifying loose or strict
|
||||
paths";
|
||||
reference "RFC3209: section-4.3.2";
|
||||
}
|
||||
|
||||
typedef te-path-disjointness {
|
||||
type bits {
|
||||
bit node {
|
||||
position 0;
|
||||
description "Node disjoint.";
|
||||
}
|
||||
bit link {
|
||||
position 1;
|
||||
description "Link disjoint.";
|
||||
}
|
||||
bit srlg {
|
||||
position 2;
|
||||
description "SRLG (Shared Risk Link Group) disjoint.";
|
||||
}
|
||||
}
|
||||
description
|
||||
"Type of the resource disjointness for a TE tunnel path.";
|
||||
reference
|
||||
"RFC4872: RSVP-TE Extensions in Support of End-to-End
|
||||
Generalized Multi-Protocol Label Switching (GMPLS)
|
||||
Recovery";
|
||||
} // te-path-disjointness
|
||||
|
||||
typedef accumulated-metric-type {
|
||||
type union {
|
||||
type uint64;
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
}
|
||||
description
|
||||
"type useable for accumulative-value";
|
||||
}
|
||||
|
||||
grouping path-route-objects {
|
||||
description
|
||||
"List of EROs to be included or excluded when performing
|
||||
the path computation.";
|
||||
container explicit-route-objects {
|
||||
description
|
||||
"Container for the route object list";
|
||||
list route-object-include-exclude {
|
||||
description
|
||||
"List of explicit route objects to include or
|
||||
exclude in path computation";
|
||||
leaf explicit-route-usage {
|
||||
type identityref {
|
||||
base route-usage-type;
|
||||
}
|
||||
description "Explicit-route usage.";
|
||||
}
|
||||
key "index";
|
||||
uses explicit-route-hop ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping generic-path-disjointness {
|
||||
description "Path disjointness grouping";
|
||||
leaf disjointness {
|
||||
type te-path-disjointness;
|
||||
description
|
||||
"The type of resource disjointness.
|
||||
Under primary path, disjointness level applies to
|
||||
all secondary LSPs. Under secondary, disjointness
|
||||
level overrides the one under primary";
|
||||
}
|
||||
}
|
||||
|
||||
grouping common-path-constraints-attributes {
|
||||
description
|
||||
"Common path constraints configuration grouping";
|
||||
uses common-constraints_config;
|
||||
}
|
||||
|
||||
grouping generic-path-constraints {
|
||||
description
|
||||
"Global named path constraints configuration
|
||||
grouping";
|
||||
container path-constraints {
|
||||
description "TE named path constraints container";
|
||||
uses common-path-constraints-attributes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
grouping explicit-route-hop {
|
||||
description
|
||||
"The explicit route subobject grouping";
|
||||
leaf index {
|
||||
type uint32;
|
||||
description "ERO subobject index";
|
||||
}
|
||||
choice type {
|
||||
description
|
||||
"The explicit route subobject type";
|
||||
case num-unnum-hop {
|
||||
container num-unnum-hop {
|
||||
leaf node-id {
|
||||
//type te-node-id;
|
||||
type string;
|
||||
description
|
||||
"The identifier of a node in the TE topology.";
|
||||
}
|
||||
leaf link-tp-id {
|
||||
//type te-tp-id;
|
||||
type string;
|
||||
description
|
||||
"TE link termination point identifier. The combination
|
||||
of TE link ID and the TE node ID is used to identify an
|
||||
unnumbered TE link.";
|
||||
}
|
||||
leaf hop-type {
|
||||
type te-hop-type;
|
||||
description "strict or loose hop";
|
||||
}
|
||||
description
|
||||
"Numbered and Unnumbered link/node explicit route
|
||||
subobject";
|
||||
}
|
||||
}
|
||||
case label {
|
||||
container label-hop {
|
||||
description "Label hop type";
|
||||
uses effective-freq-slot;
|
||||
}
|
||||
description
|
||||
"The Label ERO subobject";
|
||||
}
|
||||
case hop-attribute{
|
||||
uses gnpypc:hop-attribute ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping common-constraints_config {
|
||||
description
|
||||
"Common constraints grouping that can be set on
|
||||
a constraint set or directly on the tunnel";
|
||||
|
||||
container te-bandwidth {
|
||||
uses gnpy-specific-parameters ;
|
||||
description
|
||||
"A requested bandwidth to use for path computation";
|
||||
}
|
||||
}
|
||||
|
||||
grouping end-points {
|
||||
description
|
||||
"Common grouping to define the TE tunnel end-points";
|
||||
|
||||
leaf source {
|
||||
type string;
|
||||
description "TE tunnel source address.";
|
||||
}
|
||||
leaf destination {
|
||||
type string;
|
||||
description "P2P tunnel destination address";
|
||||
}
|
||||
leaf src-tp-id {
|
||||
type string;
|
||||
description "TE tunnel source termination point identifier.";
|
||||
}
|
||||
leaf dst-tp-id {
|
||||
type string;
|
||||
description "TE tunnel destination termination point
|
||||
identifier.";
|
||||
}
|
||||
}
|
||||
|
||||
grouping synchronization-info {
|
||||
description "Information for sync";
|
||||
list synchronization {
|
||||
key "synchronization-id";
|
||||
description "sync list";
|
||||
leaf synchronization-id {
|
||||
type string;
|
||||
description "index";
|
||||
}
|
||||
container svec {
|
||||
description
|
||||
"Synchronization VECtor";
|
||||
leaf relaxable {
|
||||
type boolean;
|
||||
default true;
|
||||
description
|
||||
"If this leaf is true, path computation process is free
|
||||
to ignore svec content.
|
||||
otherwise it must take into account this svec.";
|
||||
}
|
||||
uses generic-path-disjointness;
|
||||
leaf-list request-id-number {
|
||||
type string;
|
||||
description "This list reports the set of M path computation requests that must be synchronized.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping path-metric {
|
||||
description "TE path metric type";
|
||||
leaf metric-type {
|
||||
type identityref {
|
||||
base path-metric-type;
|
||||
}
|
||||
description "TE path metric type";
|
||||
}
|
||||
leaf accumulative-value {
|
||||
type decimal64 {
|
||||
fraction-digits 2;
|
||||
}
|
||||
description "TE path metric accumulative value";
|
||||
}
|
||||
}
|
||||
grouping generic-path-properties {
|
||||
description "TE generic path properties grouping";
|
||||
container path-properties {
|
||||
config false;
|
||||
description "The TE path properties";
|
||||
list path-metric {
|
||||
key metric-type;
|
||||
uses path-metric;
|
||||
}
|
||||
list z-a-path-metric {
|
||||
key metric-type;
|
||||
uses path-metric;
|
||||
}
|
||||
list path-route-objects {
|
||||
description
|
||||
"Container for the list of route objects either returned by
|
||||
the computation engine or actually used by an LSP";
|
||||
container path-route-object {
|
||||
description
|
||||
"List of route objects either returned by the computation
|
||||
engine or actually used by an LSP";
|
||||
uses explicit-route-hop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grouping path-info {
|
||||
uses generic-path-properties;
|
||||
description "Path computation output information";
|
||||
}
|
||||
|
||||
// adding some blocking reasons and info on path in case of blocking
|
||||
|
||||
grouping no-path-info {
|
||||
description "no-path-info";
|
||||
container no-path {
|
||||
presence "Response without path information, due to failure
|
||||
performing the path computation";
|
||||
leaf no-path {
|
||||
type string;
|
||||
mandatory true ;
|
||||
description
|
||||
"returned blocking reasons:
|
||||
NO_PATH
|
||||
NO_COMPUTED_SNR
|
||||
NO_FEASIBLE_BAUDRATE_WITH_SPACING
|
||||
NO_PATH_WITH_CONSTRAINT
|
||||
NO_FEASIBLE_MODE
|
||||
MODE_NOT_FEASIBLE
|
||||
NO_SPECTRUM
|
||||
";
|
||||
}
|
||||
uses generic-path-properties ;
|
||||
description "if path computation cannot identify a path,
|
||||
rpc returns no path.";
|
||||
}
|
||||
}
|
||||
|
||||
grouping service {
|
||||
list path-request {
|
||||
key "request-id";
|
||||
description "request-list";
|
||||
leaf request-id {
|
||||
type string;
|
||||
mandatory true;
|
||||
description "Each path computation request is uniquely identified by the request-id-number.";
|
||||
}
|
||||
leaf bidirectional {
|
||||
type boolean;
|
||||
mandatory true;
|
||||
description "Specify the bidirectionality of the path";
|
||||
}
|
||||
|
||||
uses end-points;
|
||||
uses path-route-objects;
|
||||
uses generic-path-constraints;
|
||||
}
|
||||
uses synchronization-info;
|
||||
}
|
||||
|
||||
grouping result {
|
||||
list response {
|
||||
key response-id;
|
||||
config false;
|
||||
description "response";
|
||||
leaf response-id {
|
||||
type string;
|
||||
description
|
||||
"The list key that has to reuse request-id-number.";
|
||||
}
|
||||
choice response-type {
|
||||
config false;
|
||||
description "response-type";
|
||||
case no-path-case {
|
||||
uses no-path-info;
|
||||
}
|
||||
case path-case {
|
||||
uses path-info;
|
||||
description "Path computation service.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,3 +10,9 @@ scipy>=1.5.4,<2
|
||||
Sphinx>=3.5.0,<4
|
||||
sphinxcontrib-bibtex>=0.4.2,<1
|
||||
xlrd>=1.2.0,<2
|
||||
flask>=1.1.2
|
||||
gnpy~=2.2.0
|
||||
cryptography~=3.3.1
|
||||
Werkzeug~=1.0.1
|
||||
setuptools~=50.3.1
|
||||
Flask-Injector
|
||||
@@ -51,3 +51,4 @@ console_scripts =
|
||||
gnpy-transmission-example = gnpy.tools.cli_examples:transmission_main_example
|
||||
gnpy-path-request = gnpy.tools.cli_examples:path_requests_run
|
||||
gnpy-convert-xls = gnpy.tools.convert:_do_convert
|
||||
gnpy-rest = gnpy.api.rest_example:main
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -39,8 +39,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -64,8 +64,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -39,8 +39,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -104,8 +104,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -129,8 +129,8 @@
|
||||
"trx_mode": "mode 2",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
@@ -154,8 +154,8 @@
|
||||
"trx_mode": "mode 2",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
@@ -179,8 +179,8 @@
|
||||
"trx_mode": "mode 2",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"N": "null",
|
||||
"M": "null"
|
||||
"N": null,
|
||||
"M": null
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -39,8 +39,8 @@
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -64,8 +64,8 @@
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -89,8 +89,8 @@
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -135,8 +135,8 @@
|
||||
"trx_mode": "mode 2 - fake",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
@@ -160,8 +160,8 @@
|
||||
"trx_mode": "mode 2",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
@@ -185,8 +185,8 @@
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -223,8 +223,8 @@
|
||||
"trx_mode": "mode 3",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 62500000000.0,
|
||||
@@ -261,8 +261,8 @@
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -286,8 +286,8 @@
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -332,8 +332,8 @@
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -357,8 +357,8 @@
|
||||
"trx_mode": "mode 1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -382,8 +382,8 @@
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -407,8 +407,8 @@
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -453,8 +453,8 @@
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -478,8 +478,8 @@
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
@@ -503,8 +503,8 @@
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
@@ -528,8 +528,8 @@
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
@@ -553,8 +553,8 @@
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
"N":"null",
|
||||
"M":"null"
|
||||
}
|
||||
],
|
||||
"spacing": 30000000000.0,
|
||||
|
||||
@@ -129,6 +129,8 @@ def create_rq(equipment, srce, dest, bdir, nd_list, ls_list):
|
||||
f_max_from_si = params['f_max']
|
||||
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
||||
params['path_bandwidth'] = 100000000000.0
|
||||
params['effective_freq_slot'] = None
|
||||
params['blocking_reason'] = None
|
||||
requests_list.append(PathRequest(**params))
|
||||
return requests_list
|
||||
|
||||
|
||||
@@ -424,6 +424,8 @@ def test_excel_ila_constraints(source, destination, route_list, hoptype, expecte
|
||||
'nb_channel': 0,
|
||||
'power': 0,
|
||||
'path_bandwidth': 0,
|
||||
'effective_freq_slot': None,
|
||||
'blocking_reason': None
|
||||
}
|
||||
request = PathRequest(**params)
|
||||
|
||||
|
||||
@@ -244,6 +244,8 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db):
|
||||
params['loose_list'] = ['strict']
|
||||
params['format'] = ''
|
||||
params['path_bandwidth'] = 100e9
|
||||
params['effective_freq_slot'] = None
|
||||
params['blocking_reason'] = None
|
||||
trx_params = trx_mode_params(equipment)
|
||||
params.update(trx_params)
|
||||
req = PathRequest(**params)
|
||||
|
||||
Reference in New Issue
Block a user