import grpc, logging from prometheus_client import Counter, Histogram from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID from common.exceptions.ServiceException import ServiceException from context.proto.context_pb2 import Empty, Link, LinkId, Topology from context.proto.context_pb2_grpc import ContextServiceServicer from context.service.database.api.Database import Database from .Tools import check_link_id_request, check_link_request LOGGER = logging.getLogger(__name__) GETTOPOLOGY_COUNTER_STARTED = Counter ('context_gettopology_counter_started', 'Context:GetTopology counter of requests started' ) GETTOPOLOGY_COUNTER_COMPLETED = Counter ('context_gettopology_counter_completed', 'Context:GetTopology counter of requests completed') GETTOPOLOGY_COUNTER_FAILED = Counter ('context_gettopology_counter_failed', 'Context:GetTopology counter of requests failed' ) GETTOPOLOGY_HISTOGRAM_DURATION = Histogram('context_gettopology_histogram_duration', 'Context:GetTopology histogram of request duration') ADDLINK_COUNTER_STARTED = Counter ('context_addlink_counter_started', 'Context:AddLink counter of requests started' ) ADDLINK_COUNTER_COMPLETED = Counter ('context_addlink_counter_completed', 'Context:AddLink counter of requests completed') ADDLINK_COUNTER_FAILED = Counter ('context_addlink_counter_failed', 'Context:AddLink counter of requests failed' ) ADDLINK_HISTOGRAM_DURATION = Histogram('context_addlink_histogram_duration', 'Context:AddLink histogram of request duration') DELETELINK_COUNTER_STARTED = Counter ('context_deletelink_counter_started', 'Context:DeleteLink counter of requests started' ) DELETELINK_COUNTER_COMPLETED = Counter ('context_deletelink_counter_completed', 'Context:DeleteLink counter of requests completed') DELETELINK_COUNTER_FAILED = Counter ('context_deletelink_counter_failed', 'Context:DeleteLink counter of requests failed' ) DELETELINK_HISTOGRAM_DURATION = Histogram('context_deletelink_histogram_duration', 'Context:DeleteLink histogram of request duration') class ContextServiceServicerImpl(ContextServiceServicer): def __init__(self, database : Database): LOGGER.debug('Creating Servicer...') self.database = database LOGGER.debug('Servicer Created') @GETTOPOLOGY_HISTOGRAM_DURATION.time() def GetTopology(self, request : Empty, grpc_context : grpc.ServicerContext) -> Topology: GETTOPOLOGY_COUNTER_STARTED.inc() try: LOGGER.debug('GetTopology request: {}'.format(str(request))) # ----- Validate request data and pre-conditions ----------------------------------------------------------- db_context = self.database.context(DEFAULT_CONTEXT_UUID).create() db_topology = db_context.topology(DEFAULT_TOPOLOGY_UUID).create() # ----- Retrieve data from the database -------------------------------------------------------------------- json_topology = db_topology.dump() # ----- Compose reply -------------------------------------------------------------------------------------- reply = Topology(**json_topology) LOGGER.debug('GetTopology reply: {}'.format(str(reply))) GETTOPOLOGY_COUNTER_COMPLETED.inc() return reply except ServiceException as e: # pragma: no cover (ServiceException not thrown) LOGGER.exception('GetTopology exception') GETTOPOLOGY_COUNTER_FAILED.inc() grpc_context.abort(e.code, e.details) except Exception as e: # pragma: no cover LOGGER.exception('GetTopology exception') GETTOPOLOGY_COUNTER_FAILED.inc() grpc_context.abort(grpc.StatusCode.INTERNAL, str(e)) @ADDLINK_HISTOGRAM_DURATION.time() def AddLink(self, request : Link, grpc_context : grpc.ServicerContext) -> LinkId: ADDLINK_COUNTER_STARTED.inc() try: LOGGER.debug('AddLink request: {}'.format(str(request))) # ----- Validate request data and pre-conditions ----------------------------------------------------------- link_id, db_endpoints = check_link_request('AddLink', request, self.database, LOGGER) # ----- Implement changes in the database ------------------------------------------------------------------ db_context = self.database.context(DEFAULT_CONTEXT_UUID).create() db_topology = db_context.topology(DEFAULT_TOPOLOGY_UUID).create() db_link = db_topology.link(link_id).create() for db_endpoint in db_endpoints: link_endpoint_id = '{}/{}'.format( db_endpoint.device_uuid, db_endpoint.endpoint_uuid) db_link.endpoint(link_endpoint_id).create(db_endpoint) # ----- Compose reply -------------------------------------------------------------------------------------- reply = LinkId(**db_link.dump_id()) LOGGER.debug('AddLink reply: {}'.format(str(reply))) ADDLINK_COUNTER_COMPLETED.inc() return reply except ServiceException as e: LOGGER.exception('AddLink exception') ADDLINK_COUNTER_FAILED.inc() grpc_context.abort(e.code, e.details) except Exception as e: # pragma: no cover LOGGER.exception('AddLink exception') ADDLINK_COUNTER_FAILED.inc() grpc_context.abort(grpc.StatusCode.INTERNAL, str(e)) @DELETELINK_HISTOGRAM_DURATION.time() def DeleteLink(self, request : LinkId, grpc_context : grpc.ServicerContext) -> Empty: DELETELINK_COUNTER_STARTED.inc() try: LOGGER.debug('DeleteLink request: {}'.format(str(request))) # ----- Validate request data and pre-conditions ----------------------------------------------------------- link_id = check_link_id_request('DeleteLink', request, self.database, LOGGER) # ----- Implement changes in the database ------------------------------------------------------------------ db_context = self.database.context(DEFAULT_CONTEXT_UUID).create() db_topology = db_context.topology(DEFAULT_TOPOLOGY_UUID).create() db_topology.link(link_id).delete() # ----- Compose reply -------------------------------------------------------------------------------------- reply = Empty() LOGGER.debug('DeleteLink reply: {}'.format(str(reply))) DELETELINK_COUNTER_COMPLETED.inc() return reply except ServiceException as e: LOGGER.exception('DeleteLink exception') DELETELINK_COUNTER_FAILED.inc() grpc_context.abort(e.code, e.details) except Exception as e: # pragma: no cover LOGGER.exception('DeleteLink exception') DELETELINK_COUNTER_FAILED.inc() grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))