Commit 855fc24f authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Service component:



- Formatted code
- Fixed exception raise in method extend_optical_band()

Co-authored-by: default avatarCopilot <copilot@github.com>
parent 54bdc6f6
Loading
Loading
Loading
Loading
+150 −151
Original line number Diff line number Diff line
@@ -13,30 +13,30 @@
# limitations under the License.
# 

from common.method_wrappers.ServiceExceptions import NotFoundException
from service.service.service_handler_api.SettingsHandler import SettingsHandler
import functools, json, logging, requests, uuid
from typing import List
from context.client.ContextClient import ContextClient
from common.Constants import ServiceNameEnum 
from common.tools.context_queries.OpticalConfig import ( find_optical_band)
from typing import Dict, List, Tuple
from common.method_wrappers.ServiceExceptions import NotFoundException
from common.proto.context_pb2 import(
    Device, DeviceId, Service, Connection, EndPointId, TopologyId, ContextId, Uuid,
    ConfigRule, ConfigActionEnum, ConfigRule_Custom, Empty,OpticalBandId,OpticalBand
    ConfigActionEnum, ConfigRule, ConfigRule_Custom, Connection, ContextId,
    Device, DeviceId, Empty, EndPointId, OpticalBand, OpticalBandId, Service,
    TopologyId, Uuid
)
from common.proto.pathcomp_pb2 import PathCompReply
from common.tools.context_queries.OpticalConfig import find_optical_band
from common.Constants import ServiceNameEnum 
from common.Settings import (
    ENVVAR_SUFIX_SERVICE_BASEURL_HTTP, ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC,
    find_environment_variables, get_env_var_name
)
from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Topology import json_topology_id
from context.client.ContextClient import ContextClient
from service.service.service_handler_api.SettingsHandler import SettingsHandler
from service.service.tools.replies import (
    reply_uni_txt
    , optical_band_uni_txt
    , reply_bid_txt
    , optical_band_bid_txt
    reply_uni_txt, optical_band_uni_txt, reply_bid_txt, optical_band_bid_txt
)

log = logging.getLogger(__name__)
LOGGER = logging.getLogger(__name__)

TESTING = False

@@ -56,68 +56,66 @@ def get_optical_controller_base_url() -> str:
        VAR_NAME_OPTICAL_CTRL_PORT,
    ])
    base_url = settings.get(VAR_NAME_OPTICAL_CTRL_BASEURL_HTTP)
    if base_url is not None:
        log.debug('Optical Controller: base_url={:s}'.format(str(base_url)))
        return base_url

    if base_url is None:
        schema = settings.get(VAR_NAME_OPTICAL_CTRL_SCHEMA, 'http')
        host   = settings.get(VAR_NAME_OPTICAL_CTRL_HOST)
        port   = int(settings.get(VAR_NAME_OPTICAL_CTRL_PORT, 80))

    MSG = 'Optical Controller not found: settings={:s}'
    if host is None: raise Exception(MSG.format(str(settings)))
    if port is None: raise Exception(MSG.format(str(settings)))
        if schema is None or host is None or port is None:
            MSG = 'Missing settings for Optical Controller: settings={:s}'
            raise Exception(MSG.format(str(settings)))

    schema = settings.get(VAR_NAME_OPTICAL_CTRL_SCHEMA, 'http')
        base_url = OPTICAL_CTRL_BASE_URL.format(schema, host, port)
    log.debug('Optical Controller: base_url={:s}'.format(str(base_url)))

    LOGGER.debug('Optical Controller: base_url={:s}'.format(str(base_url)))
    return base_url


def get_uuids_from_names(devices: List[Device], device_name: str, port_name: str):
    device_uuid = ""
    port_uuid = ""
def get_uuids_from_names(
    devices : List[Device], device_name : str, port_name : str
) -> Tuple[str, str]:
    for device in devices:
        if device.name == device_name:
        if device.name != device_name: continue
        device_uuid = device.device_id.device_uuid.uuid
        for ep in device.device_endpoints:
                if ep.name == port_name:
            if ep.name != port_name: continue
            port_uuid = ep.endpoint_id.endpoint_uuid.uuid
            return device_uuid, port_uuid
    return "", ""
    return '', ''


def get_names_from_uuids(devices: List[Device], device_uuid: str, port_uuid: str):
    device_name = ""
    port_name = ""
def get_names_from_uuids(
    devices : List[Device], device_uuid : str, port_uuid : str
) -> Tuple[str, str]:
    for device in devices:
        if device.device_id.device_uuid.uuid == device_uuid:
        if device.device_id.device_uuid.uuid != device_uuid: continue
        device_name = device.name
        for ep in device.device_endpoints:
                if ep.endpoint_id.endpoint_uuid.uuid == port_uuid:
            if ep.endpoint_id.endpoint_uuid.uuid != port_uuid: continue
            port_name = ep.name
            return device_name, port_name
    return "", ""

    return '', ''

def get_device_name_from_uuid(devices: List[Device], device_uuid: str):
    device_name = ""

def get_device_name_from_uuid(
    devices : List[Device], device_uuid : str
) -> str:
    for device in devices:
        if device.device_id.device_uuid.uuid == device_uuid:
        if device.device_id.device_uuid.uuid != device_uuid: continue
        device_name = device.name
        return device_name
    return ""
    return ''


def refresh_opticalcontroller(topology_id : dict):
    topo_id_str = topology_id["topology_uuid"]["uuid"]
    cxt_id_str = topology_id["context_id"]["context_uuid"]["uuid"]
    headers = {"Content-Type": "application/json"}
def refresh_opticalcontroller(topology_id : Dict) -> None:
    topo_id_str = topology_id['topology_uuid']['uuid']
    cxt_id_str = topology_id['context_id']['context_uuid']['uuid']
    headers = {'Content-Type': 'application/json'}
    base_url = get_optical_controller_base_url()
    urlx = "{:s}/GetTopology/{:s}/{:s}".format(base_url, cxt_id_str, topo_id_str)
    urlx = '{:s}/GetTopology/{:s}/{:s}'.format(base_url, cxt_id_str, topo_id_str)
    res = requests.get(urlx, headers=headers)
    if res is not None:
        log.debug(f"GetTopology Response {res}")
        LOGGER.debug(f"GetTopology Response {res}")


def reconfig_flex_lightpath(flow_id) -> str:
@@ -127,7 +125,7 @@ def reconfig_flex_lightpath(flow_id) -> str:
        base_url = get_optical_controller_base_url()
        urlx = "{:s}/ReconfigFlexLightpath/{}".format(base_url, flow_id)
        r = requests.put(urlx, headers=headers)
        print(f"reconfig {r}")
        LOGGER.debug(f"reconfig {r}")
        reply = r.text 
        return reply
    else:
@@ -158,7 +156,7 @@ def add_flex_lightpath(src, dst, bitrate, bidir, pref, ob_band, dj_optical_band_
            else:
                urlx = "{:s}/AddFlexLightpath/{:s}/{:s}/{:s}/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(prefs), str(bidir), str(ob_band), str(dj_optical_band_id))                
        r = requests.put(urlx, headers=headers)
        print(f"addpathlight {r}")
        LOGGER.debug(f"addpathlight {r}")
        reply = r.text 
        return reply
    else:
@@ -189,7 +187,7 @@ def add_lightpath(src, dst, bitrate, bidir) -> str:
            bidir = 1
        urlx = "{:s}/AddLightpath/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(bidir))
        r = requests.put(urlx, headers=headers)
        print(f"addpathlight {r}")
        LOGGER.debug(f"addpathlight {r}")
        reply = r.text 
        return reply
    else:
@@ -202,8 +200,8 @@ def add_lightpath(src, dst, bitrate, bidir) -> str:
def get_optical_band(idx) -> str:
    if not TESTING:
        base_url = get_optical_controller_base_url()
        urlx = "{:s}/GetOpticalBand/{:s}".format(base_url, str(idx))
        headers = {"Content-Type": "application/json"}
        urlx = '{:s}/GetOpticalBand/{:s}'.format(base_url, str(idx))
        headers = {'Content-Type': 'application/json'}
        r = requests.get(urlx, headers=headers)
        reply = r.text 
        return reply
@@ -304,16 +302,16 @@ def adapt_reply_ob(devices, service, reply_json, context_id, topology_id, optica
        bidir_ob = ob["bidir"]
        # in case the service is built upon existed optical band , don't clacluate the endpoints of it 
        for devxb in ob["flows"].keys():
            log.debug("optical-band device {}".format(devxb))
            LOGGER.debug("optical-band device {}".format(devxb))
            in_end_point_b = "0"
            out_end_point_b = "0"
            in_end_point_f = ob["flows"][devxb]["f"]["in"]
            out_end_point_f = ob["flows"][devxb]["f"]["out"]
            log.debug("optical-band ports {}, {}".format(in_end_point_f, out_end_point_f))
            LOGGER.debug("optical-band ports {}, {}".format(in_end_point_f, out_end_point_f))
            if bidir_ob:
                in_end_point_b = ob["flows"][devxb]["b"]["in"]
                out_end_point_b = ob["flows"][devxb]["b"]["out"]
                log.debug("optical-band ports {}, {}".format(in_end_point_b, out_end_point_b))
                LOGGER.debug("optical-band ports {}, {}".format(in_end_point_b, out_end_point_b))
            #if (in_end_point_f == "0" or out_end_point_f == "0") and (in_end_point_b == "0" or out_end_point_b == "0"):
            if in_end_point_f != "0":
                d_ob, p_ob = get_uuids_from_names(devices, devxb, in_end_point_f)
@@ -321,7 +319,7 @@ def adapt_reply_ob(devices, service, reply_json, context_id, topology_id, optica
                    end_point_b = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d_ob)), endpoint_uuid=Uuid(uuid=p_ob))
                    connection_ob.path_hops_endpoint_ids.add().CopyFrom(end_point_b)
                else:
                    log.info("no map device port for device {} port {}".format(devxb, in_end_point_f))
                    LOGGER.info("no map device port for device {} port {}".format(devxb, in_end_point_f))

            if out_end_point_f != "0":
                d_ob, p_ob = get_uuids_from_names(devices, devxb, out_end_point_f)
@@ -329,25 +327,25 @@ def adapt_reply_ob(devices, service, reply_json, context_id, topology_id, optica
                    end_point_b = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d_ob)), endpoint_uuid=Uuid(uuid=p_ob))
                    connection_ob.path_hops_endpoint_ids.add().CopyFrom(end_point_b) 
                else:
                    log.info("no map device port for device {} port {}".format(devxb, out_end_point_f))
                    LOGGER.info("no map device port for device {} port {}".format(devxb, out_end_point_f))
            if in_end_point_b != "0":
                d_ob, p_ob = get_uuids_from_names(devices, devxb, in_end_point_b)
                if d_ob != "" and p_ob != "":
                    end_point_b = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d_ob)), endpoint_uuid=Uuid(uuid=p_ob))
                    connection_ob.path_hops_endpoint_ids.add().CopyFrom(end_point_b) 
                else:
                    log.info("no map device port for device {} port {}".format(devxb, in_end_point_b))
                    LOGGER.info("no map device port for device {} port {}".format(devxb, in_end_point_b))
            if out_end_point_b != "0":
                d_ob, p_ob = get_uuids_from_names(devices, devxb, out_end_point_b)
                if d_ob != "" and p_ob != "":
                    end_point_b = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d_ob)), endpoint_uuid=Uuid(uuid=p_ob))
                    connection_ob.path_hops_endpoint_ids.add().CopyFrom(end_point_b)
                else:
                    log.info("no map device port for device {} port {}".format(devxb, out_end_point_b))
            log.debug("optical-band connection {}".format(connection_ob))
                    LOGGER.info("no map device port for device {} port {}".format(devxb, out_end_point_b))
            LOGGER.debug("optical-band connection {}".format(connection_ob))
        #check that list of endpoints is not empty  
        if connection_ob is not None and  len(connection_ob.path_hops_endpoint_ids) == 0:
            log.debug("deleting empty optical-band connection")
            LOGGER.debug("deleting empty optical-band connection")
            opt_reply.connections.remove(connection_ob)

        '''
@@ -382,12 +380,11 @@ def adapt_reply_ob(devices, service, reply_json, context_id, topology_id, optica



def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_band_txt) ->  PathCompReply:
def adapt_reply(
    devices, service, reply_json, context_id : str, topology_id : str, optical_band_txt
) ->  PathCompReply:
    opt_reply = PathCompReply()
    topo = TopologyId(
        context_id=ContextId(context_uuid=Uuid(uuid=context_id)),
        topology_uuid=Uuid(uuid=topology_id)
    )
    topo = TopologyId(**json_topology_id(topology_id, context_id))
    #add optical band connection first
    rules_ob = []
    ob_id = 0
@@ -436,16 +433,16 @@ def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_b
        # in case the service is built upon existed optical band , don't clacluate the endpoints of it 
        if new_ob != 2 : 
            for devxb in ob["flows"].keys():
                log.debug("optical-band device {}".format(devxb))
                LOGGER.debug("optical-band device {}".format(devxb))
                in_end_point_b = "0"
                out_end_point_b = "0"
                in_end_point_f = ob["flows"][devxb]["f"]["in"]
                out_end_point_f = ob["flows"][devxb]["f"]["out"]
                log.debug("optical-band ports {}, {}".format(in_end_point_f, out_end_point_f))
                LOGGER.debug("optical-band ports {}, {}".format(in_end_point_f, out_end_point_f))
                if bidir_ob:
                    in_end_point_b = ob["flows"][devxb]["b"]["in"]
                    out_end_point_b = ob["flows"][devxb]["b"]["out"]
                    log.debug("optical-band ports {}, {}".format(in_end_point_b, out_end_point_b))
                    LOGGER.debug("optical-band ports {}, {}".format(in_end_point_b, out_end_point_b))
                #if (in_end_point_f == "0" or out_end_point_f == "0") and (in_end_point_b == "0" or out_end_point_b == "0"):
                if in_end_point_f != "0":
                    d_ob, p_ob = get_uuids_from_names(devices, devxb, in_end_point_f)
@@ -453,7 +450,7 @@ def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_b
                        end_point_b = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d_ob)), endpoint_uuid=Uuid(uuid=p_ob))
                        connection_ob.path_hops_endpoint_ids.add().CopyFrom(end_point_b)
                    else:
                        log.info("no map device port for device {} port {}".format(devxb, in_end_point_f))
                        LOGGER.info("no map device port for device {} port {}".format(devxb, in_end_point_f))

                if out_end_point_f != "0":
                    d_ob, p_ob = get_uuids_from_names(devices, devxb, out_end_point_f)
@@ -461,70 +458,70 @@ def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_b
                        end_point_b = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d_ob)), endpoint_uuid=Uuid(uuid=p_ob))
                        connection_ob.path_hops_endpoint_ids.add().CopyFrom(end_point_b) 
                    else:
                        log.info("no map device port for device {} port {}".format(devxb, out_end_point_f))
                        LOGGER.info("no map device port for device {} port {}".format(devxb, out_end_point_f))
                if in_end_point_b != "0":
                    d_ob, p_ob = get_uuids_from_names(devices, devxb, in_end_point_b)
                    if d_ob != "" and p_ob != "":
                        end_point_b = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d_ob)), endpoint_uuid=Uuid(uuid=p_ob))
                        connection_ob.path_hops_endpoint_ids.add().CopyFrom(end_point_b) 
                    else:
                        log.info("no map device port for device {} port {}".format(devxb, in_end_point_b))
                        LOGGER.info("no map device port for device {} port {}".format(devxb, in_end_point_b))
                if out_end_point_b != "0":
                    d_ob, p_ob = get_uuids_from_names(devices, devxb, out_end_point_b)
                    if d_ob != "" and p_ob != "":
                        end_point_b = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d_ob)), endpoint_uuid=Uuid(uuid=p_ob))
                        connection_ob.path_hops_endpoint_ids.add().CopyFrom(end_point_b)
                    else:
                        log.info("no map device port for device {} port {}".format(devxb, out_end_point_b))
                log.debug("optical-band connection {}".format(connection_ob))
                        LOGGER.info("no map device port for device {} port {}".format(devxb, out_end_point_b))
                LOGGER.debug("optical-band connection {}".format(connection_ob))
        
    connection_f = add_connection_to_reply(opt_reply)
    connection_f.connection_id.connection_uuid.uuid = str(uuid.uuid4())
    connection_f.service_id.CopyFrom(service.service_id)
    for devx in r["flows"].keys():
        log.debug("lightpath device {}".format(devx))
        LOGGER.debug("lightpath device {}".format(devx))
        in_end_point_b = "0"
        out_end_point_b = "0"
        
        in_end_point_f = r["flows"][devx]["f"]["in"]
        out_end_point_f = r["flows"][devx]["f"]["out"]
        log.debug("lightpath ports {}, {}".format(in_end_point_f, out_end_point_f))
        LOGGER.debug("lightpath ports {}, {}".format(in_end_point_f, out_end_point_f))
        if bidir_f:
            in_end_point_b = r["flows"][devx]["b"]["in"]
            out_end_point_b = r["flows"][devx]["b"]["out"]
            log.debug("lightpath ports {}, {}".format(in_end_point_b, out_end_point_b))
            LOGGER.debug("lightpath ports {}, {}".format(in_end_point_b, out_end_point_b))
        if in_end_point_f != "0":
            d, p = get_uuids_from_names(devices, devx, in_end_point_f)
            if d != "" and p != "":
                end_point = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d)), endpoint_uuid=Uuid(uuid=p))
                connection_f.path_hops_endpoint_ids.add().CopyFrom(end_point) 
            else:
                log.info("no map device port for device {} port {}".format(devx, in_end_point_f))
                LOGGER.info("no map device port for device {} port {}".format(devx, in_end_point_f))
        if out_end_point_f != "0":
            d, p = get_uuids_from_names(devices, devx, out_end_point_f)
            if d != "" and p != "":
                end_point = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d)), endpoint_uuid=Uuid(uuid=p))
                connection_f.path_hops_endpoint_ids.add().CopyFrom(end_point)
            else:
                log.info("no map device port for device {} port {}".format(devx, out_end_point_f))
                LOGGER.info("no map device port for device {} port {}".format(devx, out_end_point_f))
        if in_end_point_b != "0":
            d, p = get_uuids_from_names(devices, devx, in_end_point_b)
            if d != "" and p != "":
                end_point = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d)), endpoint_uuid=Uuid(uuid=p))
                connection_f.path_hops_endpoint_ids.add().CopyFrom(end_point) 
            else:
                log.info("no map device port for device {} port {}".format(devx, in_end_point_b))
                LOGGER.info("no map device port for device {} port {}".format(devx, in_end_point_b))
        if out_end_point_b != "0":
            d, p = get_uuids_from_names(devices, devx, out_end_point_b)
            if d != "" and p != "":
                end_point = EndPointId(topology_id=topo, device_id=DeviceId(device_uuid=Uuid(uuid=d)), endpoint_uuid=Uuid(uuid=p))
                connection_f.path_hops_endpoint_ids.add().CopyFrom(end_point) 
            else:
                log.info("no map device port for device {} port {}".format(devx, out_end_point_b))
                LOGGER.info("no map device port for device {} port {}".format(devx, out_end_point_b))

    #check that list of endpoints is not empty  
    if connection_ob is not None and  len(connection_ob.path_hops_endpoint_ids) == 0:
        log.debug("deleting empty optical-band connection")
        LOGGER.debug("deleting empty optical-band connection")
        opt_reply.connections.remove(connection_ob)

    #inizialize custom optical parameters
@@ -558,73 +555,75 @@ def adapt_reply(devices, service, reply_json, context_id, topology_id, optical_b
    return opt_reply



def add_service_to_reply(reply : PathCompReply, service : Service) -> Service:
    service_x = reply.services.add()
    service_x.CopyFrom(service)
    return service_x

def add_connection_to_reply(reply : PathCompReply) -> Connection:
    conn = reply.connections.add()
    return conn


def add_connection_to_reply(reply : PathCompReply) -> Connection:
    return reply.connections.add()


def update_config_rules (service:Service,config_to_update:dict): 
def update_config_rules(
    service : Service, config_to_update : Dict
) -> Service:
    config_rules = service.service_config.config_rules
    if len(config_rules) == 0 : return service
    for key, new_value in config_to_update.items():
        for c in config_rules:
            if c.custom.resource_key == key :
            if c.custom.resource_key != key: continue
            c.custom.resource_value = json.dumps(new_value)
           
            
    return service


    
    
def extend_optical_band(reply, optical_band_text) -> Service:
    logging.debug(f"optical-band extended {reply}")
    logging.debug(f"optical-band_text {optical_band_text}")
    LOGGER.debug('[extend_optical_band] optical-band extended {:s}'.format(str(reply)))
    LOGGER.debug('[extend_optical_band] optical-band_text {:s}'.format(str(optical_band_text)))

    optical_band_res = json.loads(optical_band_text)
    if 'optical_band_id'  not in  optical_band_res: raise KeyError(f"opticalband id not found in the reply")
    if 'optical_band_id' not in optical_band_res:
        MSG = 'optical_band_id not found in reply({:s})/optical_band_text({:s})'
        raise KeyError(MSG.format(str(reply), str(optical_band_text)))

    ob_index = optical_band_res['optical_band_id']
    band=optical_band_res['band']
    frequency=optical_band_res['freq']
    opticalband=find_optical_band(ob_index=ob_index)
    if opticalband is None  :
        raise NotFoundException(f"Optical Band is not found ",extra_details=[
            f"The requested opticla band for index {ob_index} is not found"
    optical_band = find_optical_band(ob_index=ob_index)
    if optical_band is None:
        raise NotFoundException('OpticalBand', str(ob_index), extra_details=[
            'optical_band_text={:s}'.format(str(optical_band_text)),
            'reply={:s}'.format(str(reply))
        ])

    service = opticalband.service
    connection_uuid = opticalband.connection_id.connection_uuid.uuid
    service = optical_band.service
    connection_uuid = optical_band.connection_id.connection_uuid.uuid

    setting_handler = SettingsHandler(service.service_config)
    config_to_update = {}
    setting_key = '/settings-ob_{}'.format(connection_uuid)
    config = setting_handler.get(setting_key)
   
    
    config.value['band']=band
    config.value['frequency']=frequency
    config.value['low-freq']= int(frequency - (band/2))
    config.value['up-freq']= int(frequency + (band/2))
   
    logging.debug(f"before setting the config {service}")
    config_to_update[setting_key]=config.value
    setting_key = '/settings'
    config = setting_handler.get(setting_key)
    config.value['ob-expanded']=1
    config_to_update[setting_key]=config.value
    logging.debug(f"config_to_update {config_to_update}")
    service = update_config_rules(service,config_to_update)

    setting_key_svc = '/settings'
    setting_key_ob  = '/settings-ob_{:s}'.format(connection_uuid)

    return service
    config_svc = setting_handler.get(setting_key_svc)
    config_ob  = setting_handler.get(setting_key_ob )

    band = optical_band_res['band']
    frequency = optical_band_res['freq']
    config_ob.value['band'     ] = band
    config_ob.value['frequency'] = frequency
    config_ob.value['low-freq' ] = int(frequency - (band/2))
    config_ob.value['up-freq'  ] = int(frequency + (band/2))

    config_svc.value['ob-expanded'] = 1

    MSG = '[extend_optical_band] service before setting config {:s}'
    LOGGER.debug(MSG.format(grpc_message_to_json_string(service)))

    config_to_update = {
        setting_key_svc : config_svc.value,
        setting_key_ob  : config_ob.value
    }

    MSG = '[extend_optical_band] config_to_update={:s}'
    LOGGER.debug(MSG.format(str(config_to_update)))

    service = update_config_rules(service, config_to_update)
    return service