From 5ea83f3b9ddaa412a86830a93fc1fb62583bd29c Mon Sep 17 00:00:00 2001 From: sgambelluri Date: Wed, 27 Mar 2024 13:05:27 +0000 Subject: [PATCH 01/39] Endpoints Auto Descivory --- my_deploy.sh | 2 +- .../service/ContextServiceServicerImpl.py | 6 +- src/context/service/database/OpticalConfig.py | 74 ++++--- .../database/models/OpticalConfigModel.py | 42 +++- .../database/models/OpticalLinkModel.py | 78 +++++++ .../service/database/uuids/OpticalConfig.py | 17 ++ .../service/drivers/oc_driver/OCDriver.py | 5 +- .../drivers/oc_driver/templates/Tools.py | 11 +- src/tests/ofc24/run_test.sh | 17 ++ src/webui/service/__init__.py | 3 + src/webui/service/opticalconfig/__init__.py | 14 ++ src/webui/service/opticalconfig/forms.py | 22 ++ src/webui/service/opticalconfig/routes.py | 193 ++++++++++++++++++ src/webui/service/templates/base.html | 7 + .../opticalconfig/add_transceiver.html | 40 ++++ .../templates/opticalconfig/details.html | 109 ++++++++++ .../service/templates/opticalconfig/home.html | 68 ++++++ .../opticalconfig/update_interface.html | 73 +++++++ test.py | 41 ++++ 19 files changed, 783 insertions(+), 39 deletions(-) create mode 100644 src/context/service/database/models/OpticalLinkModel.py create mode 100644 src/context/service/database/uuids/OpticalConfig.py create mode 100644 src/tests/ofc24/run_test.sh create mode 100644 src/webui/service/opticalconfig/__init__.py create mode 100644 src/webui/service/opticalconfig/forms.py create mode 100644 src/webui/service/opticalconfig/routes.py create mode 100644 src/webui/service/templates/opticalconfig/add_transceiver.html create mode 100644 src/webui/service/templates/opticalconfig/details.html create mode 100644 src/webui/service/templates/opticalconfig/home.html create mode 100644 src/webui/service/templates/opticalconfig/update_interface.html create mode 100644 test.py diff --git a/my_deploy.sh b/my_deploy.sh index 7dd5e5c3e..9e4447349 100755 --- a/my_deploy.sh +++ b/my_deploy.sh @@ -20,7 +20,7 @@ export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/" # Set the list of components, separated by spaces, you want to build images for, and deploy. -export TFS_COMPONENTS="context device pathcomp service slice nbi webui load_generator" +export TFS_COMPONENTS="context device pathcomp opticalcontroller service slice nbi webui " # Uncomment to activate Monitoring #export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" diff --git a/src/context/service/ContextServiceServicerImpl.py b/src/context/service/ContextServiceServicerImpl.py index a102fa176..1be4cdac8 100644 --- a/src/context/service/ContextServiceServicerImpl.py +++ b/src/context/service/ContextServiceServicerImpl.py @@ -305,7 +305,7 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def GetOpticalConfig(self, request : Empty, context : grpc.ServicerContext) -> OpticalConfigList: result = get_opticalconfig(self.db_engine) - return OpticalConfigList(OpticalConfigs=result) + return OpticalConfigList(opticalconfigs=result) @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def SetOpticalConfig(self, request : OpticalConfig, context : grpc.ServicerContext) -> OpticalConfigId: @@ -316,5 +316,5 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer def SelectOpticalConfig(self, request : OpticalConfigId, context : grpc.ServicerContext) -> OpticalConfig: result = select_opticalconfig(self.db_engine, request) optical_config_id = OpticalConfigId() - optical_config_id.CopyFrom(result.OpticalConfig_id) - return OpticalConfig(config=result.config, OpticalConfig_id=optical_config_id) + optical_config_id.CopyFrom(result.opticalconfig_id) + return OpticalConfig(config=result.config, opticalconfig_id=optical_config_id) diff --git a/src/context/service/database/OpticalConfig.py b/src/context/service/database/OpticalConfig.py index 9e7552bc1..973e93c33 100644 --- a/src/context/service/database/OpticalConfig.py +++ b/src/context/service/database/OpticalConfig.py @@ -18,7 +18,8 @@ from sqlalchemy.engine import Engine from sqlalchemy.orm import Session, sessionmaker from sqlalchemy_cockroachdb import run_transaction from common.proto.context_pb2 import OpticalConfig, OpticalConfigId -from .models.OpticalConfigModel import OpticalConfigModel +from .models.OpticalConfigModel import OpticalConfigModel , OpticalChannelModel +from context.service.database.uuids.OpticalConfig import channel_get_uuid LOGGER = logging.getLogger(__name__) @@ -26,44 +27,61 @@ def get_opticalconfig(db_engine : Engine): def callback(session:Session): optical_configs = list() results = session.query(OpticalConfigModel).all() + for obj in results: + LOGGER.info(f"opticaln config obj from context {obj.dump()}") + optical_config = OpticalConfig() - optical_config.config = json.dump(obj.config) - optical_config.opticalconfig_id.opticalconfig_uuid = obj.opticalconfig_uuid + optical_config.config = json.dumps(obj.dump()) + optical_config.opticalconfig_id.opticalconfig_uuid = obj.dump_id()["opticalconfig_uuid"] optical_configs.append(optical_config) return optical_configs obj = run_transaction(sessionmaker(bind=db_engine), callback) return obj def set_opticalconfig(db_engine : Engine, request : OpticalConfig): + LOGGER.info(f"request {request} ") opticalconfig_id = OpticalConfigId() opticalconfig_id.opticalconfig_uuid = request.opticalconfig_id.opticalconfig_uuid - my_config_data = [] + OpticalConfig_data = [] if request.config: channels = [] transceivers = [] config = json.loads(request.config) - if 'channels' in config and len(config['channels']) > 0: - channels = [channel['name']['index'] for channel in config['channels']] + if 'transceivers' in config and len(config['transceivers']['transceiver']) > 0: transceivers = [transceiver for transceiver in config['transceivers']['transceiver']] - - my_config_data = [ - { - "opticalconfig_uuid": request.opticalconfig_id.opticalconfig_uuid, - "channels" : channels, - "transcievers" : transceivers, - "interfaces" : json.dumps(config["interfaces"]["interface"]), - "channel_namespace" : config["channel_namespace"], - "endpoints" : [json.dumps(endpoint) for endpoint in config["endpoints"]], - "frequency" : config["frequency"] if "frequency" in config else 0, - "operational_mode" : config["operational_mode"] if "operational_mode" in config else 0, - "output_power" : config["output_power"] if "output_power" in config else '', - } - ] - + + if 'channels' in config and len(config['channels']) > 0: + #channels = [channel['name']['index'] for channel in config['channels']] + for channel_params in config['channels']: + channels.append( + { + "channel_uuid":channel_get_uuid(channel_params['name']['index']), + "opticalconfig_uuid": request.opticalconfig_id.opticalconfig_uuid, + "channel_name" : channel_params['name']['index'], + "frequency" : int(channel_params["frequency"]) if "frequency" in channel_params else 0, + "operational_mode" : int(channel_params["operational-mode"]) if "operational-mode" in channel_params else 0, + "target_output_power" : channel_params["target-output-power"] if "target-output-power" in channel_params else '', + } + ) + + OpticalConfig_data.append( + { + "opticalconfig_uuid": request.opticalconfig_id.opticalconfig_uuid, + "transcievers" : transceivers, + "interfaces" : json.dumps(config["interfaces"]["interface"]), + "channel_namespace" : config["channel_namespace"], + "endpoints" : [json.dumps(endpoint) for endpoint in config["endpoints"]],} + + ) + + + LOGGER.info(f"optical config to set {OpticalConfig_data} ") + LOGGER.info(f"channels {channels}") def callback(session:Session)->bool: - stmt = insert(OpticalConfigModel).values(my_config_data) + stmt = insert(OpticalConfigModel).values(OpticalConfig_data) + stmt = stmt.on_conflict_do_update( index_elements=[OpticalConfigModel.opticalconfig_uuid], set_=dict( @@ -71,7 +89,17 @@ def set_opticalconfig(db_engine : Engine, request : OpticalConfig): ) ) stmt = stmt.returning(OpticalConfigModel.opticalconfig_uuid) - id = session.execute(stmt).fetchone() + opticalconfig_id = session.execute(stmt).fetchone() + if (len(channels)>0) : + + stmt = insert(OpticalChannelModel).values(channels) + + stmt = stmt.on_conflict_do_nothing( + index_elements=[OpticalChannelModel.channel_uuid , OpticalConfigModel.opticalconfig_uuid], + + ) + stmt = stmt.returning(OpticalChannelModel.channel_uuid) + opticalChannel_id = session.execute(stmt).fetchone() opticalconfig_id = run_transaction(sessionmaker(bind=db_engine), callback) return {'opticalconfig_uuid': opticalconfig_id} diff --git a/src/context/service/database/models/OpticalConfigModel.py b/src/context/service/database/models/OpticalConfigModel.py index 10cf197f9..8531f37b2 100644 --- a/src/context/service/database/models/OpticalConfigModel.py +++ b/src/context/service/database/models/OpticalConfigModel.py @@ -13,30 +13,58 @@ # limitations under the License. import json -from sqlalchemy import Column, String, Integer +from sqlalchemy import Column, String, Integer , ForeignKey from sqlalchemy.dialects.postgresql import ARRAY +from sqlalchemy.orm import relationship from ._Base import _Base class OpticalConfigModel(_Base): __tablename__ = 'optical_config' opticalconfig_uuid = Column(String, primary_key=True) - channels = Column(ARRAY(String), nullable=True) + transcievers = Column(ARRAY(String), nullable=True) interfaces = Column(String, nullable=True) channel_namespace = Column(String, nullable=True) endpoints = Column(ARRAY(String), nullable=True) - frequency = Column(Integer, nullable=True) - operational_mode = Column(Integer, nullable=True) - output_power = Column(String, nullable=True) + channels = relationship("OpticalChannelModel") + + + def dump_id (self ): + return { + "opticalconfig_uuid":self.opticalconfig_uuid + } def dump(self): return { - "channels" : [{'name': {'index': channel}} for channel in self.channels], + "channels" : [channel.dump() for channel in self.channels], "transceivers" : {"transceiver": [transciever for transciever in self.transcievers]}, "interfaces" : {"interface": json.loads(self.interfaces)}, "channel_namespace" : self.channel_namespace, "endpoints" : [json.loads(endpoint) for endpoint in self.endpoints], + + } + + + +class OpticalChannelModel(_Base): + __tablename__ = 'optical_channel' + channel_uuid = Column(String, primary_key=True) + channel_name = Column (String,nullable=True) + frequency = Column(Integer, nullable=True) + operational_mode = Column(Integer, nullable=True) + target_output_power = Column(String, nullable=True) + opticalconfig_uuid = Column(ForeignKey('optical_config.opticalconfig_uuid', ondelete='CASCADE' ), primary_key=True) + opticalconfig = relationship('OpticalConfigModel', back_populates='channels') + def dump_id (self ): + return { + "channel_uuid":self.channel_uuid + } + + def dump(self): + return { + "name" :{'index':self.channel_name}, "frequency" : self.frequency, - "output_power" : self.output_power, + "target_output_power" : self.target_output_power, "operational_mode" : self.operational_mode, } + diff --git a/src/context/service/database/models/OpticalLinkModel.py b/src/context/service/database/models/OpticalLinkModel.py new file mode 100644 index 000000000..b94eeda93 --- /dev/null +++ b/src/context/service/database/models/OpticalLinkModel.py @@ -0,0 +1,78 @@ + +import operator +from sqlalchemy import CheckConstraint, Column, DateTime, Float, ForeignKey, Integer, String ,Boolean +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.types import ARRAY +from sqlalchemy.orm import relationship +from typing import Dict +from ._Base import _Base + +class OpticalLinkModel(_Base): + __tablename__ = 'opticallink' + + optical_link_uuid = Column(UUID(as_uuid=False), primary_key=True) + optical_link_name = Column(String, nullable=False) + length = Column(Integer, nullable=True) + source = Column(String, nullable=True) + target = Column(String, nullable=True) + optical_link_fiber= relationship("FiberModel") + created_at = Column(DateTime, nullable=False) + updated_at = Column(DateTime, nullable=False) + + + + + def dump_id(self) -> Dict: + return {'optical_link_uuid': {'uuid': self.link_uuid}} + + def dump(self) -> Dict: + result = { + 'optical_link_id' : self.dump_id(), + 'name' : self.optical_link_name, + 'details': { + "length" : self.length, + 'source' : self.source, + "target" : self.target, + 'fibers' : [ fiber.dump() for fiber in self.optical_link_fiber ] + } + + } + + return result + +class FiberModel(_Base): + __tablename__ = 'fiber' + fiber_uuid = Column(UUID(as_uuid=False), primary_key=True) + fiber_length = Column(Integer, nullable=True) + source_port = Column(String, nullable=True) + destination_port = Column(String, nullable=True) + local_peer_port = Column(String, nullable=True) + remote_peer_port = Column(String, nullable=True) + used = Column(Boolean ,nullable=true) + c_slots = Column (ARRAY(Integer),nullable=True) + l_slots = Column (ARRAY(Integer),nullable=True) + s_slots = Column (ARRAY(Integer),nullable=True) + optical_link_uuid = Column(ForeignKey('opticallink.optical_link_uuid', ondelete='CASCADE' ), primary_key=True) + optical_link = relationship('OpticalLinkModel', back_populates='optical_link_fibers') + + + def dump_id(self) -> Dict: + return {'fiber_uuid': {'uuid': self.fiber_uuid}} + + + def dump(self) -> Dict: + result = { + 'ID' : self.dump_id(), + 'length' : self.fiber_length, + "src_port" : self.source_port, + "dst_port" : self.destination_port, + "local_peer_port" : self.local_peer_port, + "remote_peer_port" : self.remote_peer_port, + "used" : self.used, + "c_slots" : self.c_slots , + "l_slots" : self.l_slots, + "s_slots" : self.s_slots + + } + + return result \ No newline at end of file diff --git a/src/context/service/database/uuids/OpticalConfig.py b/src/context/service/database/uuids/OpticalConfig.py new file mode 100644 index 000000000..0003b5712 --- /dev/null +++ b/src/context/service/database/uuids/OpticalConfig.py @@ -0,0 +1,17 @@ + +from common.method_wrappers.ServiceExceptions import InvalidArgumentsException +from ._Builder import get_uuid_from_string, get_uuid_random + +def channel_get_uuid( + channel_name :str , allow_random : bool = False +) -> str: + + + if len(channel_name) > 0: + return get_uuid_from_string(channel_name) + if allow_random: return get_uuid_random() + + raise InvalidArgumentsException([ + ('channel uuid', channel_name), + + ], extra_details=['Channel name is required to produce a channel UUID']) diff --git a/src/device/service/drivers/oc_driver/OCDriver.py b/src/device/service/drivers/oc_driver/OCDriver.py index 16f00cfb4..4b49c7e41 100644 --- a/src/device/service/drivers/oc_driver/OCDriver.py +++ b/src/device/service/drivers/oc_driver/OCDriver.py @@ -257,7 +257,8 @@ class OCDriver(_Driver): xml_data = self.__netconf_handler.get().data_xml transceivers,interfaces,channels_lst,channel_namespace,endpoints=extractor(data_xml=xml_data,resource_keys=filter_fields,dic=config) - + logging.info(f"xml response {xml_data}") + except Exception as e: # pylint: disable=broad-except MSG = 'Exception retrieving {:s}' self.__logger.info("error from getConfig %s",e) @@ -273,7 +274,7 @@ class OCDriver(_Driver): value_dic["interfaces"]=interfaces value_dic["channel_namespace"]=channel_namespace value_dic["endpoints"]=endpoints - + logging.info(f"parameters {value_dic}") opticalConfig.config=json.dumps(value_dic) opticalConfig.opticalconfig_id.opticalconfig_uuid=self.__device_uuid if self.__device_uuid is not None else "" config_id=context_client.SetOpticalConfig(opticalConfig) diff --git a/src/device/service/drivers/oc_driver/templates/Tools.py b/src/device/service/drivers/oc_driver/templates/Tools.py index 909bdd83b..bc69db6a6 100644 --- a/src/device/service/drivers/oc_driver/templates/Tools.py +++ b/src/device/service/drivers/oc_driver/templates/Tools.py @@ -140,9 +140,10 @@ def extract_channels_based_on_type (xml_data:str): return channel_names def extract_value(resource_key:str,xml_data:str,dic:dict,channel_name:str,channel_namespace:str): + logging.info(f"resource_key {resource_key} and channgel_name {channel_name} and channel_namespace {channel_namespace}") xml_bytes = xml_data.encode("utf-8") root = ET.fromstring(xml_bytes) - + channel_name=channel_name if 'index' not in channel_name else channel_name['index'] namespace = {'oc': 'http://openconfig.net/yang/platform', 'td': channel_namespace} @@ -153,10 +154,13 @@ def extract_value(resource_key:str,xml_data:str,dic:dict,channel_name:str,channe if (parameter is not None): value = parameter.text dic[resource_key]=value + else : + logging.info("parameter is None") else: + logging.info("element is None") print(" element not found.") - + logging.info(f"dic {dic}") return dic @@ -244,10 +248,11 @@ def extractor(data_xml:str,resource_keys:list,dic:dict): for channel_name in channel_names: dic={} - for resource_key in resource_keys : + for resource_key in resource_keys : if (resource_key != 'interface'): dic=extract_value(dic=dic,resource_key=resource_key,xml_data=data_xml,channel_name=channel_name,channel_namespace=channel_namespace) + dic["name"]=channel_name endpoints.append({"endpoint_uuid":{"uuid":channel_name}}) lst_dic.append(dic) diff --git a/src/tests/ofc24/run_test.sh b/src/tests/ofc24/run_test.sh new file mode 100644 index 000000000..660436552 --- /dev/null +++ b/src/tests/ofc24/run_test.sh @@ -0,0 +1,17 @@ +#!/bin/bash +docker stop na1 +docker rm na1 + screen -dmS t1 -T xterm sh -c "docker run -p 10.0.2.10:2023:2022 -v ~/tfs-ctrl/tempOC/files:/files --name na1 -it asgamb1/oc23bgp.img:latest +" + sleep 2 + if [ "$( docker container inspect -f '{{.State.Running}}' na1)" = "true" ]; then + + + + docker exec na1 sh -c " cp /files/platform_t1.xml demoECOC21.xml ; + + /confd/examples.confd/OC23/startNetconfAgent.sh; " + else + echo "your container is not running yet" + fi + diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py index 63192016c..196652d3f 100644 --- a/src/webui/service/__init__.py +++ b/src/webui/service/__init__.py @@ -83,6 +83,9 @@ def create_app(use_config=None, web_app_root=None): from webui.service.load_gen.routes import load_gen # pylint: disable=import-outside-toplevel app.register_blueprint(load_gen) + + from webui.service.opticalconfig.routes import opticalconfig # pylint: disable=import-outside-toplevel + app.register_blueprint(opticalconfig) from webui.service.service.routes import service # pylint: disable=import-outside-toplevel app.register_blueprint(service) diff --git a/src/webui/service/opticalconfig/__init__.py b/src/webui/service/opticalconfig/__init__.py new file mode 100644 index 000000000..1549d9811 --- /dev/null +++ b/src/webui/service/opticalconfig/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/src/webui/service/opticalconfig/forms.py b/src/webui/service/opticalconfig/forms.py new file mode 100644 index 000000000..30c133279 --- /dev/null +++ b/src/webui/service/opticalconfig/forms.py @@ -0,0 +1,22 @@ + + +from flask_wtf import FlaskForm +from wtforms import StringField, SelectField, TextAreaField, SubmitField +from wtforms.validators import DataRequired, Length, NumberRange, ValidationError +from common.proto.context_pb2 import DeviceOperationalStatusEnum + +class UpdateDeviceForm(FlaskForm): + power = StringField('Power') + frequency= StringField("Frequency") + operational_mode=StringField("Operational Mode") + line_port=SelectField("Line Port") + + + submit = SubmitField('Update') + +class AddTrancseiver (FlaskForm): + transceiver = StringField("Transceiver") + submit = SubmitField('Add') +class UpdateInterfaceForm (FlaskForm): + ip=StringField("IP Address") + prefix_length=StringField("Prefix Length") \ No newline at end of file diff --git a/src/webui/service/opticalconfig/routes.py b/src/webui/service/opticalconfig/routes.py new file mode 100644 index 000000000..5445d140e --- /dev/null +++ b/src/webui/service/opticalconfig/routes.py @@ -0,0 +1,193 @@ +import base64, json, logging #, re +from flask import jsonify, redirect, render_template, Blueprint, flash, session, url_for, request +from common.proto.context_pb2 import (ContextList, Empty, TopologyId, TopologyList +,DeviceId,DeviceList ,OpticalConfig, OpticalConfigId ,OpticalConfigList) +from common.tools.descriptor.Loader import DescriptorLoader, compose_notifications +from common.tools.grpc.Tools import grpc_message_to_json_string +from common.tools.object_factory.Context import json_context_id +from common.tools.object_factory.Topology import json_topology_id +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient +from service.client.ServiceClient import ServiceClient +from slice.client.SliceClient import SliceClient +from webui.service.main.forms import ContextTopologyForm, DescriptorForm +from .forms import UpdateDeviceForm ,AddTrancseiver ,UpdateInterfaceForm + + + +opticalconfig = Blueprint('opticalconfig', __name__,url_prefix="/opticalconfig") + +context_client = ContextClient() +device_client = DeviceClient() +service_client = ServiceClient() +slice_client = SliceClient() + +LOGGER = logging.getLogger(__name__) + +DESCRIPTOR_LOADER_NUM_WORKERS = 10 + +@opticalconfig.get("/") +def home() : + config=[] + deviceId= DeviceId() + + if 'context_uuid' not in session or 'topology_uuid' not in session: + flash("Please select a context!", "warning") + return redirect(url_for("main.home")) + context_uuid = session['context_uuid'] + topology_uuid = session['topology_uuid'] + + context_client.connect() + opticalConfig_list:OpticalConfigList = context_client.GetOpticalConfig(Empty()) + logging.info("myconfigList %s",opticalConfig_list) + + for configs in opticalConfig_list.opticalconfigs: + + value=json.loads(configs.config) if type(configs.config)==str else configs.config + value["channels_number"]=len(value['channels']) + + # value['operationalMode']=value['operational-mode'] + # value['targetOutputPower']=value['target-output-power'] + value['opticalconfig_id']=configs.opticalconfig_id + # value['line_port']=value["line-port"] + + config.append(value) + + logging.info("opticalConfig %s",config) + + context_client.close() + + return render_template( + 'opticalconfig/home.html', config=config) +@opticalconfig.route('/detail',methods=['GET']) +def show_details(config_uuid): + opticalconfigId=OpticalConfigId() + opticalconfigId.opticalconfig_uuid=config_uuid + device_details=[] + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + LOGGER.info("response %s",response) + opticalConfig = OpticalConfig() + opticalConfig.CopyFrom(response) + + config =json.loads(opticalConfig.config) + LOGGER.info("config details %s",config) + interfaces=config["interfaces"] + new_config={} + + for channel in config['channels'] : + + new_config["name"]=channel['name'] + new_config['operationalMode']=channel['operational_mode'] if 'operational_mode' in channel else '' + new_config['targetOutputPower']=channel['target_output_power'] if 'target_output_power' in channel else '' + new_config["frequency"]=channel['frequency'] if 'frequency' in channel else '' + new_config['line_port']=channel["line-port"] if 'line-port' in channel else '' + + device_details.append(new_config) + LOGGER.info("config details %s",device_details) + return render_template('opticalconfig/details.html', device=device_details,config_id=config_uuid,interfaces=interfaces) +@opticalconfig.route('//update', methods=['GET', 'POST']) +def update(config_uuid,channel_name): + form = UpdateDeviceForm() + + opticalconfigId=OpticalConfigId() + opticalconfigId.opticalconfig_uuid=config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + LOGGER.info("response %s",response) + opticalconfig = OpticalConfig() + opticalconfig.CopyFrom(response) + config =json.loads(opticalconfig.config) + new_config={} + for channel in config['channels']: + if (channel["name"] == channel_name): + new_config=channel + form.frequency.default = channel["frequency"] + form.operational_mode.default=channel["operational-mode"] + form.power.default=channel["target-output-power"] + form.line_port.choices = [("","")] + + for transceiver in config["transceivers"]['transceiver']: + + form.line_port.choices.append((transceiver,transceiver)) + # listing enum values + + if form.validate_on_submit(): + + new_config["target-output-power"] =form.power.data if form.power.data != '' else new_config['target-output-power'] + new_config["frequency"]=form.frequency.data if form.frequency.data != '' else new_config['frequency'] + new_config["operational-mode"]=form.operational_mode.data if form.operational_mode.data != '' else new_config['operational-mode'] + new_config["line-port"]=form.line_port.data if form.line_port.data != '' else new_config['line-port'] + + opticalconfig.config =json.dumps(new_config) + LOGGER.info("myconfig copied %s",opticalconfig) + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticalconfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.show_details',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template('myabout/update.html', device=response, form=form, submit_text='Update Device',channel_name=channel_name) +@opticalconfig.route('//update_interface', methods=['GET', 'POST']) +def update_interface (config_uuid,interface_name): + form = UpdateInterfaceForm() + opticalconfigId=OpticalConfigId() + opticalconfigId.opticalconfig_uuid=config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(myid) + context_client.close() + LOGGER.info("response %s",response) + opticalconfig = OpticalConfig() + opticalconfig.CopyFrom(response) + config =json.loads(opticalconfig.config) + new_config={} + if form.validate_on_submit(): + new_config["ip"]=form.ip.data if form.ip.data != "" else config["interfaces"]["interface"]["ip"] + new_config["prefix-length"]=form.prefix_length.data if form.prefix_length.data != "" else config["interfaces"]["interface"]["prefix-length"] + new_config["name"]=config["interfaces"]["interface"]["name"] + new_config["enabled"]=config["interfaces"]["interface"]["enabled"] + + opticalconfig.config=json.dumps({"update_interface":new_config}) + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticalconfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.show_details',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template('opticalconfig/update_interface.html', + device=response, form=form, submit_text='Update interface',interface_name=interface_name) + +@opticalconfig.route('/add_transceiver', methods=['GET','POST']) +def add_transceiver (config_uuid): + config={} + addtrancseiver=AddTrancseiver() + opticalconfigId=OpticalConfig() + opticalconfigId.opticalconfig_uuid=config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + opticlConfig=OpticalConfig() + opticlConfig.CopyFrom(response) + if addtrancseiver.validate_on_submit(): + config["add_transceiver"]=addtrancseiver.transceiver.data + opticlConfig.config=json.dumps(config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticlConfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.update',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template('opticalconfig/add_transceiver.html',form=addtrancseiver, submit_text='Add Trancseiver') + + + + \ No newline at end of file diff --git a/src/webui/service/templates/base.html b/src/webui/service/templates/base.html index 60cd5aebd..e081b2710 100644 --- a/src/webui/service/templates/base.html +++ b/src/webui/service/templates/base.html @@ -83,6 +83,13 @@ Slice {% endif %} +