Commit 92bcac51 authored by Mohammad Ismaeel's avatar Mohammad Ismaeel
Browse files

TAPI with standard request

parent 4f9fcd17
Loading
Loading
Loading
Loading
+11 −15
Original line number Diff line number Diff line
@@ -93,9 +93,13 @@ service ContextService {
  rpc GetOpticalBand         (Empty            ) returns (OpticalBandList)  {}
  rpc SelectOpticalBand      (OpticalBandId    ) returns (OpticalBand)  {}

  rpc ListChildTopology         (Empty            ) returns (ChildTopologyList)  {}

  rpc ListChildTopologies     (ContextId     ) returns (       ChildTopologyList    ) {}
  rpc GetChildTopology        (TopologyId    ) returns (       ChildTopology        ) {}
  rpc GetChildTopologyDetails (TopologyId    ) returns (       TopologyDetails ) {}
  rpc SetChildTopology        (ChildTopology      ) returns (       TopologyId      ) {}
  rpc RemoveChildTopology     (TopologyId    ) returns (       Empty           ) {}


  rpc DeleteServiceConfigRule(ServiceConfigRule) returns (Empty            ) {}
}
@@ -765,20 +769,12 @@ message OpticalBandList {
}


message ChildEndpoint {
  EndPointId endpoint_id =1 ; 
  DeviceId device_id = 2 ; 
  string endpoint_name = 3; 
  string device_name =4 ;
  
}

message ChildTopology {

  TopologyId topology_id = 2 ;
  string host = 3; 
  int32 port = 4 ;
  repeated ChildEndpoint endpoints =5;
  string host = 1; 
  int32 port = 2;
  Topology topology = 3 ;

}

+40 −2
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ from common.proto.context_pb2 import (
    Service, ServiceConfigRule, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList,
    Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList,
    Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList,OpticalBand ,OpticalBandId,
    OpticalBandList  , ChildTopologyList , ChildTopology , ChildEndpoint 
    OpticalBandList  , ChildTopologyList , ChildTopology  
)
from common.proto.context_pb2_grpc import ContextServiceStub
from common.proto.context_policy_pb2_grpc import ContextPolicyServiceStub
@@ -565,3 +565,41 @@ class ContextClient:
        LOGGER.debug('ServiceConfigRule Delete result: {:s}'.format(grpc_message_to_json_string(response)))
        return response
  
    # ------------------------------- TAPI Child Toplogy  -----------------------
    
    
    @RETRY_DECORATOR
    def ListChildTopologies(self, request: ContextId) -> ChildTopologyList:
        LOGGER.debug('ListChildTopologies request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.ListChildTopologies(request)
        LOGGER.debug('ListChildTopologies result: {:s}'.format(grpc_message_to_json_string(response)))
        return response

    @RETRY_DECORATOR
    def GetChildTopology(self, request: TopologyId) -> ChildTopology:
        LOGGER.debug('GetChildTopology request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.GetChildTopology(request)
        LOGGER.debug('GetChildTopology result: {:s}'.format(grpc_message_to_json_string(response)))
        return response

    @RETRY_DECORATOR
    def SetChildTopology(self, request: ChildTopology) -> TopologyId:
        LOGGER.debug('SetChildTopology request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.SetChildTopology(request)
        LOGGER.debug('SetChildTopology result: {:s}'.format(grpc_message_to_json_string(response)))
        return response

    @RETRY_DECORATOR
    def RemoveChildTopology(self, request: TopologyId) -> Empty:
        LOGGER.debug('RemoveChildTopology request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.RemoveChildTopology(request)
        LOGGER.debug('RemoveChildTopology result: {:s}'.format(grpc_message_to_json_string(response)))
        return response


    @RETRY_DECORATOR
    def GetChildTopologyDetails(self, request: TopologyId) -> TopologyDetails:
        LOGGER.debug('GetChildTopologyDetails request: {:s}'.format(grpc_message_to_json_string(request)))
        response = self.stub.GetChildTopologyDetails(request)
        LOGGER.debug('GetChildTopologyDetails result: {:s}'.format(grpc_message_to_json_string(response)))
        return response
+19 −10
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ from common.proto.context_pb2 import (
    Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList,
    Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList,
    OpticalConfigList, OpticalConfigId, OpticalConfig, OpticalLink, OpticalLinkList,
    ServiceConfigRule,OpticalBand,OpticalBandId,OpticalBandList , ChildTopologyList , ChildTopology , ChildEndpoint 
    ServiceConfigRule,OpticalBand,OpticalBandId,OpticalBandList , ChildTopologyList , ChildTopology  
)
from common.proto.policy_pb2 import PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule
from common.proto.context_pb2_grpc import ContextServiceServicer
@@ -74,7 +74,8 @@ from .database.OpticalBand import (
                                   get_optical_band,set_optical_band , select_optical_band
                                   )

from .database.Tapi import ( get_child_topology , get_children_topology , set_child_topology)
from .database.Tapi import ( child_topology_get , child_topology_get_details
                            , child_topology_list_objs , child_topology_delete , child_topology_set)

LOGGER = logging.getLogger(__name__)

@@ -403,16 +404,24 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer
    def DeleteServiceConfigRule(self, request : ServiceConfigRule, context : grpc.ServicerContext) -> Empty:
        return delete_config_rule(self.db_engine,  request)
    
    # ------------------------- TAPI Child Topology ----------------------------
 
    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def ListChildTopologies(self, request : ContextId, context : grpc.ServicerContext) -> ChildTopologyList:
        return child_topology_list_objs(self.db_engine, request)

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def GetChildTopology(self, request : TopologyId, context : grpc.ServicerContext) -> ChildTopology:
        return get_child_topology(self.db_engine, request)
        return child_topology_get(self.db_engine, request)

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def ListChildTopology(self, request : Empty, context : grpc.ServicerContext) -> ChildTopologyList:
        return get_children_topology(self.db_engine, request)
    def GetChildTopologyDetails(self, request : TopologyId, context : grpc.ServicerContext) -> TopologyDetails:
        return child_topology_get_details(self.db_engine, request)

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def SetChildTopology(self, request : ChildTopology, context : grpc.ServicerContext) -> TopologyId:
        topo_id= set_child_topology(self.db_engine, request)
        return TopologyId(topology_uuid=topo_id)
 No newline at end of file
        return child_topology_set(self.db_engine, self.messagebroker, request)

    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
    def RemoveChildTopology(self, request : TopologyId, context : grpc.ServicerContext) -> Empty:
        return child_topology_delete(self.db_engine, self.messagebroker, request)
+140 −82
Original line number Diff line number Diff line
@@ -12,103 +12,161 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import json, logging ,datetime
import datetime, logging
from sqlalchemy.dialects.postgresql import insert
from common.message_broker.MessageBroker import MessageBroker
from common.DeviceTypes import DeviceTypeEnum
from sqlalchemy import inspect
from sqlalchemy.engine import Engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.orm import Session, selectinload, sessionmaker
from sqlalchemy_cockroachdb import run_transaction
from common.proto.context_pb2 import OpticalConfig, OpticalConfigId, Empty, EventTypeEnum ,ChildTopology , ChildEndpoint

from .models.TapiModel import ChildTopologyModel ,ChildEndpointsModel
from context.service.database.uuids.EndPoint import  endpoint_get_uuid
from context.service.database.uuids.Device   import    device_get_uuid 
from context.service.database.uuids.Topology import  topology_get_uuid 
from typing import Dict, List, Optional, Set
from common.proto.context_pb2 import (
    ContextId, Empty, EventTypeEnum, ChildTopology, TopologyDetails, TopologyId, ChildTopologyList , Topology)
from common.message_broker.MessageBroker import MessageBroker
from common.method_wrappers.ServiceExceptions import NotFoundException
from common.tools.object_factory.Context import json_context_id
from common.tools.object_factory.Topology import json_topology_id
from context.Config import ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY, ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY
from .models.DeviceModel import DeviceModel

from .models.OpticalLinkModel import OpticalLinkModel
from .models.TapiModel import ChildTopologyDeviceModel, ChildTopologyOpticalLinkModel, ChildTopologyModel
from .uuids.Context import context_get_uuid
from .uuids.Device import device_get_uuid
from .uuids.Link import link_get_uuid
from .uuids.Topology import topology_get_uuid
from .Events import notify_event_context, notify_event_topology

from .Events import notify_event_opticalconfig
from .OpticalBand import set_optical_band
LOGGER = logging.getLogger(__name__)
now = datetime.datetime.utcnow()

def get_children_topology(db_engine : Engine):
    def callback(session:Session):

        results = session.query(ChildTopologyModel).all()

        return [r.dump() for r in results]
def child_topology_list_objs(db_engine : Engine, request : ContextId) -> ChildTopologyList:
    context_uuid = context_get_uuid(request, allow_random=False)
    def callback(session : Session) -> List[Dict]:
        obj_list : List[ChildTopologyModel] = session.query(ChildTopologyModel)\
            .options(selectinload(ChildTopologyModel.child_topology_devices))\
            .options(selectinload(ChildTopologyModel.child_topology_optical_links))\
            .filter_by(context_uuid=context_uuid).all()
        return [obj.dump() for obj in obj_list]
    topologies = run_transaction(sessionmaker(bind=db_engine), callback)
    return ChildTopologyList(topology_list=topologies)

def child_topology_get(db_engine : Engine, request : TopologyId) -> ChildTopology:
    _,topology_uuid = topology_get_uuid(request, allow_random=False)
    def callback(session : Session) -> Optional[Dict]:
        obj : Optional[ChildTopologyModel] = session.query(ChildTopologyModel)\
            .options(selectinload(ChildTopologyModel.child_topology_devices))\
            .options(selectinload(ChildTopologyModel.child_topology_optical_links))\
            .filter_by(child_topology_uuid=topology_uuid).one_or_none()
        return None if obj is None else obj.dump()
    obj = run_transaction(sessionmaker(bind=db_engine), callback)
    return obj

def get_child_topology(db_engine : Engine , request:ChildTopology ):
    _topology_uuid = request.topology_id.topology_uuid.uuid
    def callback(session:Session):
  
        result = session.query(ChildEndpointsModel).filter_by(topology_uuid=_topology_uuid).one_or_none()
       
        return result.dump() if result else {}
    if obj is None:
        context_uuid = context_get_uuid(request.context_id, allow_random=False)
        raw_topology_uuid = '{:s}/{:s}'.format(request.context_id.context_uuid.uuid
                                               , request.topology_uuid.uuid)
        raise NotFoundException('Topology', raw_topology_uuid, extra_details=[
            'context_uuid generated was: {:s}'.format(context_uuid),
            'topology_uuid generated was: {:s}'.format(topology_uuid),
        ])
    return ChildTopology(**obj)

def child_topology_get_details(db_engine : Engine, request : TopologyId) -> TopologyDetails:
    _,topology_uuid = topology_get_uuid(request, allow_random=False)
    def callback(session : Session) -> Optional[Dict]:
        obj : Optional[ChildTopologyModel] = session.query(ChildTopologyModel)\
            .options(selectinload(ChildTopologyModel.child_topology_devices, ChildTopologyModel.device, DeviceModel.endpoints))\
            .options(selectinload(ChildTopologyModel.child_topology_optical_links
                                  , ChildTopologyOpticalLinkModel.optical_link, OpticalLinkModel.opticallink_endpoints))\
            .filter_by(child_topology_uuid=topology_uuid).one_or_none()
            #.options(selectinload(DeviceModel.components))\
        return None if obj is None else obj.dump_details()
    obj = run_transaction(sessionmaker(bind=db_engine), callback)
    return obj
    if obj is None:
        context_uuid = context_get_uuid(request.topology.context_id, allow_random=False)
        raw_topology_uuid = '{:s}/{:s}'.format(request.context_id.context_uuid.uuid, request.topology_uuid.uuid)
        raise NotFoundException('Topology', raw_topology_uuid, extra_details=[
            'context_uuid generated was: {:s}'.format(context_uuid),
            'topology_uuid generated was: {:s}'.format(topology_uuid),
        ])
    return TopologyDetails(**obj)

def child_topology_set(db_engine : Engine, messagebroker : MessageBroker, request : ChildTopology) -> TopologyId:
    topology_name = request.topology.name
    if len(topology_name) == 0: topology_name = request.topology.topology_id.topology_uuid.uuid
    context_uuid,topology_uuid = topology_get_uuid(request.topology.topology_id, topology_name=topology_name, allow_random=True)

    # By default, ignore request.device_ids and request.link_ids. They are used for retrieving
    # devices and links added into the topology. Explicit addition into the topology is done
    # automatically when creating the devices and links, based on the topologies specified in
    # the endpoints associated with the devices and links.
    # In some cases, it might be needed to add them explicitly; to allow that, activate flags
    # ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY and/or ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY.

    related_devices : List[Dict] = list()
    if ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY:
        device_uuids : Set[str] = set()
        for device_id in request.toplogy.device_ids:
            device_uuid = device_get_uuid(device_id)
            if device_uuid not in device_uuids: continue
            related_devices.append({'topology_uuid': topology_uuid, 'device_uuid': device_uuid})
            device_uuids.add(device_uuid)
    else:
        if len(request.topology.device_ids) > 0: # pragma: no cover
            MSG = 'ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY={:s}; '.format(str(ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY))
            MSG += 'Items in field "device_ids" ignored. This field is used for retrieval purposes only.'
            LOGGER.warning(MSG)

def set_child_topology(db_engine : Engine, request : ChildTopology):
  
    topology_uuid = request.topology_id.topology_uuid.uuid
  
   
    endpoints_list = []
    topology = {}
  
    #is_transpondre = False
  
    now = datetime.datetime.now(datetime.timezone.utc)
    _,topo_uuid= topology_get_uuid(request.topology_id)
    
    for endpoint in request.endpoints: 
        endpoints_list.append({
            'endpoint_uuid':endpoint.endpoint_id.endpoint_uuid.uuid,
            'device_uuid':endpoint.device_id.device_uuid.uuid,
            'endpoint_name':endpoint.endpoint_name,
            'device_name':endpoint.device_name,
            'updated_at':now , 
            'created_at':now,
            'topology_uuid':topo_uuid
        })

    topology = {
        'topology_uuid':topo_uuid,
    topology_data = [{
        'context_uuid' : context_uuid,
        'child_topology_uuid': topology_uuid,
        'topology_name': topology_name,
        'created_at'   : now,
        'updated_at'   : now,
        'host'         : request.host,
        'port':request.port
    }
    def callback(session:Session)->bool:
        'port'         : request.port,
    }]

        stmt = insert(ChildTopologyModel).values(topology)
    def callback(session : Session) -> bool:
        stmt = insert(ChildTopologyModel).values(topology_data)
        stmt = stmt.on_conflict_do_update(
            index_elements=[ChildTopologyModel.topology_uuid],
            index_elements=[ChildTopologyModel.child_topology_uuid],
            set_=dict(
                host = stmt.excluded.host,
                port= stmt.excluded.port,
                topology_name = stmt.excluded.topology_name,
                updated_at    = stmt.excluded.updated_at,
            )
        )
        stmt = stmt.returning(ChildTopologyModel.topology_uuid)
        topology_uuid = session.execute(stmt).fetchone()
        
        if topology_uuid and len(endpoints_list) > 0:   
                en_list=[]  
                for en in endpoints_list :  
                    stmt = insert(ChildEndpointsModel).values(**en)
                    update_stmt = stmt.on_conflict_do_update(
                        index_elements=[ChildEndpointsModel.endpoint_uuid],
                        set_=dict(
                            endpoint_name                 = stmt.excluded.endpoint_name,
                            device_name                   = stmt.excluded.device_name,
                            created_at                    = stmt.excluded.created_at,
                            updated_at                    = stmt.excluded.updated_at,
        stmt = stmt.returning(ChildTopologyModel.created_at, ChildTopologyModel.updated_at)
        created_at,updated_at = session.execute(stmt).fetchone()

        updated = updated_at > created_at

        updated_topology_device = False
        if len(related_devices) > 0:
            stmt = insert(ChildTopologyDeviceModel).values(related_devices)
            stmt = stmt.on_conflict_do_nothing(
                index_elements=[ChildTopologyDeviceModel.topology_uuid, ChildTopologyDeviceModel.device_uuid]
            )
                    ).returning(ChildEndpointsModel.endpoint_uuid)
                    result = session.execute(update_stmt).fetchone()     
                    en_list.append(result)        
            topology_device_inserts = session.execute(stmt)
            updated_topology_device = int(topology_device_inserts.rowcount) > 0

        

        return updated or updated_topology_device 

    updated = run_transaction(sessionmaker(bind=db_engine), callback)
    context_id = json_context_id(context_uuid)
    topology_id = json_topology_id(topology_uuid, context_id=context_id)
   
    return TopologyId(**topology_id)

def child_topology_delete(db_engine : Engine, messagebroker : MessageBroker, request : TopologyId) -> Empty:
    context_uuid,topology_uuid = topology_get_uuid(request, allow_random=False)
    def callback(session : Session) -> bool:
        num_deleted = session.query(ChildTopologyModel).filter_by(child_topology_uuid=topology_uuid).delete()
        return num_deleted > 0
    deleted = run_transaction(sessionmaker(bind=db_engine), callback)
    context_id = json_context_id(context_uuid)
    topology_id = json_topology_id(topology_uuid, context_id=context_id)
   
    topology_uuid = run_transaction(sessionmaker(bind=db_engine), callback)
    return {'uuid': topology_uuid}
 No newline at end of file
    return Empty()
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ class OpticalLinkModel(_Base):
    s_slots                   = Column (S_Slot,nullable=True)
    opticallink_endpoints     = relationship('OpticalLinkEndPointModel')
    topology_optical_links    = relationship('TopologyOpticalLinkModel', back_populates='optical_link')
    child_topology_optical_links    = relationship('ChildTopologyOpticalLinkModel', back_populates='optical_link')

    def dump_id(self) -> Dict:
        return {'link_uuid': {'uuid': self.opticallink_uuid}}
Loading