# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) # # 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. from flask import make_response from flask.json import jsonify from flask_restful import Resource from common.orm.Database import Database from common.proto.context_pb2 import ConnectionId, ContextId, DeviceId, Empty, LinkId, ServiceId, SliceId, TopologyId from common.tools.grpc.Tools import grpc_message_to_json from context.service.grpc_server.ContextServiceServicerImpl import ContextServiceServicerImpl def format_grpc_to_json(grpc_reply): return jsonify(grpc_message_to_json(grpc_reply)) def grpc_connection_id(connection_uuid): return ConnectionId(**{ 'connection_uuid': {'uuid': connection_uuid} }) def grpc_context_id(context_uuid): return ContextId(**{ 'context_uuid': {'uuid': context_uuid} }) def grpc_device_id(device_uuid): return DeviceId(**{ 'device_uuid': {'uuid': device_uuid} }) def grpc_link_id(link_uuid): return LinkId(**{ 'link_uuid': {'uuid': link_uuid} }) def grpc_service_id(context_uuid, service_uuid): return ServiceId(**{ 'context_id': {'context_uuid': {'uuid': context_uuid}}, 'service_uuid': {'uuid': service_uuid} }) def grpc_slice_id(context_uuid, slice_uuid): return SliceId(**{ 'context_id': {'context_uuid': {'uuid': context_uuid}}, 'slice_uuid': {'uuid': slice_uuid} }) def grpc_topology_id(context_uuid, topology_uuid): return TopologyId(**{ 'context_id': {'context_uuid': {'uuid': context_uuid}}, 'topology_uuid': {'uuid': topology_uuid} }) class _Resource(Resource): def __init__(self, database : Database) -> None: super().__init__() self.database = database self.servicer = ContextServiceServicerImpl(self.database, None) class ContextIds(_Resource): def get(self): return format_grpc_to_json(self.servicer.ListContextIds(Empty(), None)) class Contexts(_Resource): def get(self): return format_grpc_to_json(self.servicer.ListContexts(Empty(), None)) class Context(_Resource): def get(self, context_uuid : str): return format_grpc_to_json(self.servicer.GetContext(grpc_context_id(context_uuid), None)) class TopologyIds(_Resource): def get(self, context_uuid : str): return format_grpc_to_json(self.servicer.ListTopologyIds(grpc_context_id(context_uuid), None)) class Topologies(_Resource): def get(self, context_uuid : str): return format_grpc_to_json(self.servicer.ListTopologies(grpc_context_id(context_uuid), None)) class Topology(_Resource): def get(self, context_uuid : str, topology_uuid : str): return format_grpc_to_json(self.servicer.GetTopology(grpc_topology_id(context_uuid, topology_uuid), None)) class ServiceIds(_Resource): def get(self, context_uuid : str): return format_grpc_to_json(self.servicer.ListServiceIds(grpc_context_id(context_uuid), None)) class Services(_Resource): def get(self, context_uuid : str): return format_grpc_to_json(self.servicer.ListServices(grpc_context_id(context_uuid), None)) class Service(_Resource): def get(self, context_uuid : str, service_uuid : str): return format_grpc_to_json(self.servicer.GetService(grpc_service_id(context_uuid, service_uuid), None)) class SliceIds(_Resource): def get(self, context_uuid : str): return format_grpc_to_json(self.servicer.ListSliceIds(grpc_context_id(context_uuid), None)) class Slices(_Resource): def get(self, context_uuid : str): return format_grpc_to_json(self.servicer.ListSlices(grpc_context_id(context_uuid), None)) class Slice(_Resource): def get(self, context_uuid : str, slice_uuid : str): return format_grpc_to_json(self.servicer.GetSlice(grpc_slice_id(context_uuid, slice_uuid), None)) class DeviceIds(_Resource): def get(self): return format_grpc_to_json(self.servicer.ListDeviceIds(Empty(), None)) class Devices(_Resource): def get(self): return format_grpc_to_json(self.servicer.ListDevices(Empty(), None)) class Device(_Resource): def get(self, device_uuid : str): return format_grpc_to_json(self.servicer.GetDevice(grpc_device_id(device_uuid), None)) class LinkIds(_Resource): def get(self): return format_grpc_to_json(self.servicer.ListLinkIds(Empty(), None)) class Links(_Resource): def get(self): return format_grpc_to_json(self.servicer.ListLinks(Empty(), None)) class Link(_Resource): def get(self, link_uuid : str): return format_grpc_to_json(self.servicer.GetLink(grpc_link_id(link_uuid), None)) class ConnectionIds(_Resource): def get(self, context_uuid : str, service_uuid : str): return format_grpc_to_json(self.servicer.ListConnectionIds(grpc_service_id(context_uuid, service_uuid), None)) class Connections(_Resource): def get(self, context_uuid : str, service_uuid : str): return format_grpc_to_json(self.servicer.ListConnections(grpc_service_id(context_uuid, service_uuid), None)) class Connection(_Resource): def get(self, connection_uuid : str): return format_grpc_to_json(self.servicer.GetConnection(grpc_connection_id(connection_uuid), None)) class DumpText(Resource): def __init__(self, database : Database) -> None: super().__init__() self.database = database def get(self): db_entries = self.database.dump() num_entries = len(db_entries) response = ['----- Database Dump [{:3d} entries] -------------------------'.format(num_entries)] for db_entry in db_entries: response.append(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover response.append('-----------------------------------------------------------') headers = {'Content-Type': 'text/plain'} return make_response('\n'.join(response), 200, headers) class DumpHtml(Resource): def __init__(self, database : Database) -> None: super().__init__() self.database = database def get(self): db_entries = self.database.dump() num_entries = len(db_entries) response = [] response.append('Database Dump [{:3d} entries]'.format(num_entries)) response.append('

Database Dump [{:3d} entries]


'.format(num_entries)) response.append('') response.append('') for db_entry in db_entries: response.append(''.format(*db_entry)) response.append('
TypeKeyValue
{:s}{:s}{:s}
') headers = {'Content-Type': 'text/html'} return make_response(''.join(response), 200, headers) # Use 'path' type in Service and Sink because service_uuid and link_uuid might contain char '/' and Flask is unable to # recognize them in 'string' type. RESOURCES = [ # (endpoint_name, resource_class, resource_url) ('api.context_ids', ContextIds, '/context_ids'), ('api.contexts', Contexts, '/contexts'), ('api.context', Context, '/context/'), ('api.topology_ids', TopologyIds, '/context//topology_ids'), ('api.topologies', Topologies, '/context//topologies'), ('api.topology', Topology, '/context//topology/'), ('api.service_ids', ServiceIds, '/context//service_ids'), ('api.services', Services, '/context//services'), ('api.service', Service, '/context//service/'), ('api.slice_ids', SliceIds, '/context//slice_ids'), ('api.slices', Slices, '/context//slices'), ('api.slice', Slice, '/context//slice/'), ('api.device_ids', DeviceIds, '/device_ids'), ('api.devices', Devices, '/devices'), ('api.device', Device, '/device/'), ('api.link_ids', LinkIds, '/link_ids'), ('api.links', Links, '/links'), ('api.link', Link, '/link/'), ('api.connection_ids', ConnectionIds, '/context//service//connection_ids'), ('api.connections', Connections, '/context//service//connections'), ('api.connection', Connection, '/connection/'), ('api.dump.text', DumpText, '/dump/text'), ('api.dump.html', DumpHtml, '/dump/html'), ]