Newer
Older
# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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.
Alberto Gonzalez Barneo
committed
import grpc
import logging
from flask import current_app, render_template, Blueprint, flash, session, redirect, url_for
Alberto Gonzalez Barneo
committed
from common.proto.qkd_app_pb2 import App, AppId, QKDAppStatusEnum, QKDAppTypesEnum
from common.proto.context_pb2 import Uuid, ContextId
from common.tools.context_queries.Context import get_context
from common.tools.context_queries.Device import get_device
from context.client.ContextClient import ContextClient
from qkd_app.client.QKDAppClient import QKDAppClient
Alberto Gonzalez Barneo
committed
# Set up logging
LOGGER = logging.getLogger(__name__)
Alberto Gonzalez Barneo
committed
# Blueprint for QKDApp routes
qkd_app = Blueprint('qkd_app', __name__, url_prefix='/qkd_app')
Alberto Gonzalez Barneo
committed
# Initialize clients
Alberto Gonzalez Barneo
committed
qkd_app_client = QKDAppClient()
context_client = ContextClient()
def home():
if 'context_uuid' not in session or 'topology_uuid' not in session:
flash("Please select a context!", "warning")
return redirect(url_for("main.home"))
Alberto Gonzalez Barneo
committed
context_uuid = session['context_uuid']
topology_uuid = session['topology_uuid']
Alberto Gonzalez Barneo
committed
# Connect to context client
context_client.connect()
device_names = dict()
Alberto Gonzalez Barneo
committed
try:
# Fetch context object
context_obj = get_context(context_client, context_uuid, rw_copy=False)
if context_obj is None:
flash('Context({:s}) not found'.format(str(context_uuid)), 'danger')
apps = list()
else:
Alberto Gonzalez Barneo
committed
try:
# Call ListApps using the context_id
apps_response = qkd_app_client.ListApps(context_obj.context_id)
apps = apps_response.apps
except grpc.RpcError as e:
LOGGER.error(f"gRPC error while fetching apps: {e.details()}")
if e.code() != grpc.StatusCode.NOT_FOUND: raise
if e.details() != 'Context({:s}) not found'.format(context_uuid): raise
apps = list()
else:
# Map local and remote device names
for app in apps:
if app.local_device_id.device_uuid.uuid not in device_names:
device = get_device(context_client, app.local_device_id.device_uuid.uuid)
if device:
device_names[app.local_device_id.device_uuid.uuid] = device.name
Alberto Gonzalez Barneo
committed
if app.remote_device_id.device_uuid.uuid and app.remote_device_id.device_uuid.uuid not in device_names:
device = get_device(context_client, app.remote_device_id.device_uuid.uuid)
if device:
device_names[app.remote_device_id.device_uuid.uuid] = device.name
finally:
context_client.close()
# Render the template with app list and device names
return render_template(
'qkd_app/home.html',
apps=apps,
device_names=device_names,
ate=QKDAppTypesEnum,
ase=QKDAppStatusEnum
)
Alberto Gonzalez Barneo
committed
@qkd_app.route('detail/<path:app_uuid>', methods=['GET', 'POST'])
def detail(app_uuid: str):
Alberto Gonzalez Barneo
committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""
Displays details for a specific QKD app identified by its UUID.
"""
try:
qkd_app_client.connect()
# Wrap the app_uuid in a Uuid object and fetch details
uuid_message = Uuid(uuid=app_uuid)
app_id = AppId(app_uuid=uuid_message)
app_detail = qkd_app_client.GetApp(app_id)
if not app_detail:
flash(f"App with UUID {app_uuid} not found", "danger")
return redirect(url_for("qkd_app.home"))
# Fetch device details
context_client.connect()
device_names = {}
try:
if app_detail.local_device_id.device_uuid.uuid:
local_device = get_device(context_client, app_detail.local_device_id.device_uuid.uuid)
if local_device:
device_names[app_detail.local_device_id.device_uuid.uuid] = local_device.name
if app_detail.remote_device_id.device_uuid.uuid:
remote_device = get_device(context_client, app_detail.remote_device_id.device_uuid.uuid)
if remote_device:
device_names[app_detail.remote_device_id.device_uuid.uuid] = remote_device.name
except grpc.RpcError as e:
LOGGER.error(f"Failed to retrieve device details for app {app_uuid}: {e}")
flash(f"Error retrieving device details: {e.details()}", "danger")
return redirect(url_for("qkd_app.home"))
finally:
context_client.close()
return render_template(
'qkd_app/detail.html',
app=app_detail,
ase=QKDAppStatusEnum,
ate=QKDAppTypesEnum,
device_names=device_names
)
except grpc.RpcError as e:
LOGGER.error(f"Failed to retrieve app details for {app_uuid}: {e}")
flash(f"Error retrieving app details: {e.details()}", "danger")
return redirect(url_for("qkd_app.home"))
finally:
qkd_app_client.close()
@qkd_app.get('<path:app_uuid>/delete')
Alberto Gonzalez Barneo
committed
def delete(app_uuid: str):
"""
Deletes a specific QKD app identified by its UUID.
"""
Alberto Gonzalez Barneo
committed
request = AppId(app_uuid=Uuid(uuid=app_uuid))
Alberto Gonzalez Barneo
committed
qkd_app_client.connect()
qkd_app_client.DeleteApp(request) # Call the DeleteApp method
qkd_app_client.close()
Alberto Gonzalez Barneo
committed
flash(f'App "{app_uuid}" deleted successfully!', 'success')
except grpc.RpcError as e:
LOGGER.error(f"Problem deleting app {app_uuid}: {e}")
flash(f"Problem deleting app {app_uuid}: {e.details()}", 'danger')
except Exception as e:
LOGGER.exception(f"Unexpected error while deleting app {app_uuid}: {e}")
flash(f"Unexpected error: {str(e)}", 'danger')
Alberto Gonzalez Barneo
committed
return redirect(url_for('qkd_app.home'))