cloud-fog-service-broker/cfsb-backend/routes.py
Gregory Koronakos 7faee3d41d update for devices
Change-Id: I64095946049555dd2eb82ac22f9bdae44aa398e9
2024-04-30 16:56:41 +03:00

286 lines
11 KiB
Python

from flask import Blueprint, request, jsonify, render_template, session
from User_Functions import *
import data_types as attr_data_types
from Evaluation import perform_evaluation
from data_types import get_attr_data_type
import db.db_functions as db_functions
import os
import time
import get_data as file
import activemq
import traceback
import logging
logging.disable(logging.CRITICAL)
main_routes = Blueprint('main', __name__)
# List of items with Ordinal Data
Ordinal_Variables = ['attr-reputation', 'attr-assurance']
NoData_Variables = ['attr-security', 'attr-performance-capacity', 'attr-performance-suitability']
Cont_Variables = ['attr-performance', 'attr-financial', 'attr-performance-capacity-memory',
'attr-performance-capacity-memory-speed']
#Used in CriteriaSelection.vue
@main_routes.route('/get_hierarchical_category_list')
def get_hierarchical_category_list():
items_list = file.get_level_1_items() # Assume this function returns the list correctly
if items_list is not None:
# Return the list as a JSON response
return jsonify(items_list)
else:
# Return an empty list or an error message if items_list is None
return jsonify([]), 404 # or return jsonify({"error": "No items found"}), 404
# Used in DataGrid.vue
@main_routes.route('/process_selected_criteria', methods=['POST'])
def process_selected_criteria():
try:
# Get selected criteria app_id and user_id sent from Frontend
data = request.json
selected_criteria = data.get('selectedItems', [])
print("-------------------------------------------------")
# Get app_id and user_id already obtained in the Frontend from URL
application_id = data.get('app_id')
user_id = data.get('user_id')
print("user_id:", user_id)
print("application_id:", application_id)
# Prepare message to be sent to SAL
message_for_SAL = [
{
"type": "NodeTypeRequirement",
"nodeTypes": ["IAAS", "PAAS", "FAAS", "BYON", "EDGE", "SIMULATION"],
#"nodeTypes": ["EDGE"],
"jobIdForEDGE": ""
#"jobIdForEDGE": "FCRnewLight0"
}
]
body_json_string_for_SAL = json.dumps(message_for_SAL)
RequestToSal = {
"metaData": {"user": "admin"},
"body": body_json_string_for_SAL
}
print("Request to Sal:", RequestToSal)
sal_reply = activemq.call_publisher(RequestToSal)
# Parse the JSON string to a Python object
nodes_data = json.loads(sal_reply) if isinstance(sal_reply, str) else sal_reply
print("nodes_data", nodes_data)
# Check if there is any error in SAL's reply body
if 'key' in nodes_data and any(keyword in nodes_data['key'].lower() for keyword in ['error', 'exception']):
messageToDataGrid = "Error in SAL's reply" + nodes_data['message']
print("Error found in SAL's message body:", messageToDataGrid)
node_names = []
grid_data_with_names = []
else: # No error found in SAL's reply body
###--- For Review, use ONLY ONE block, SAL's response or JSON file ----------------------###
###-------- Extract data from SAL's response --------###
print("Use of SAL's response")
extracted_data, node_ids, node_names = extract_SAL_node_candidate_data_Front(nodes_data)
print("SAL's extracted_data: ", extracted_data)
###-------- Extract data from SAL's response --------###
###-------- Extract data from dummy JSON file --------###
# print("Use of dummy JSON file")
# json_file_path = 'dummySALresponse.json'
# jsondata = read_json_file_as_string(json_file_path)
# nodes_data = json.loads(jsondata)
# if nodes_data:
# extracted_data, node_ids, node_names = extract_SAL_node_candidate_data_Front(nodes_data)
###-------- Extract data from dummy JSON file --------###
###--- For Review, use ONLY ONE block, SAL's response or JSON file ----------------------###
# print("extracted_data:", extracted_data)
field_mapping = create_criteria_mapping()
# print("field_mapping", field_mapping)
default_list_criteria_mapping = {
# "Cost": "price",
"Operating cost": "price",
"Memory Price": "memoryPrice",
"Number of CPU Cores": "cores",
"Memory Size": "ram",
"Storage Capacity": "disk"
}
grid_data = {}
for node_data in extracted_data:
node_id = node_data.get('id')
# print("Before create_node_name")
node_name = create_node_name(node_data) if node_data else "Unknown"
# print("After create_node_name")
if node_id and node_id not in grid_data:
grid_data[node_id] = {"name": node_name, "criteria": []}
hardware_info = node_data.get('hardware', {}) # contains the values for criteria coming from SAL
for criterion_key in selected_criteria:
# print("criterion_key:", criterion_key)
criterion_info = file.get_subject_data(file.SMI_prefix + criterion_key) # It contains the titles of the criteria
# print("criterion_info:", criterion_info)
# Resolve title and then map title to field name
criterion_data_type = get_attr_data_type(criterion_key) # criterion_data_type: {'type': 1, 'values': ['Low', 'Medium', 'High']}
# print("criterion_data_type:", criterion_data_type)
criterion_title = criterion_info["title"]
# Fetch the values of the selected default criteria
if criterion_title in default_list_criteria_mapping:
SAL_criterion_name = field_mapping.get(criterion_title) # Map the criterion title with the criterion name in SAL's reply
value = hardware_info.get(SAL_criterion_name, "N/A") # Get the criterion values
else:
# Handle other criteria (this part may need adjustment based on your actual data structure)
# value = "N/A" # Placeholder for the logic to determine non-default criteria values
# Generate random or default values for rest criteria
type_value = criterion_data_type['type']
# print("type_value:", type_value)
if type_value == 1:
value = random.choice(["High", "Medium", "Low"])
elif type_value == 5:
value = random.choice(["True", "False"])
else:
value = round(random.uniform(1, 100), 2)
criterion_data = {
"title": criterion_title,
"value": value,
"data_type": criterion_data_type # criterion_data_type: {'type': 1, 'values': ['Low', 'Medium', 'High']}
}
grid_data[node_id]["criteria"].append(criterion_data)
grid_data_with_names = [{
'name': data["name"],
'id': node_id,
'criteria': data["criteria"]
} for node_id, data in grid_data.items()]
# print("grid_data_with_names:", grid_data_with_names)
messageToDataGrid = "True"
return jsonify({
'success': messageToDataGrid,
'gridData': grid_data_with_names,
'NodeNames': node_names
})
except Exception as e:
print(f"Error processing selected items: {e}")
return jsonify({'success': False, 'error': str(e)}), 500
# Used for Evating the node candidates
@main_routes.route('/process-evaluation-data', methods=['POST'])
def process_evaluation_data():
try:
data = request.get_json()
if data is None:
raise ValueError("Received data is not in JSON format or 'Content-Type' header is not set to 'application/json'")
# print("JSON in process_evaluation_data:", data)
# Transform grid data to table and get node names directly from the function
data_table, relative_wr_data, immediate_wr_data, node_names, node_ids = transform_grid_data_to_table(data)
print("data_table Frontend:", data_table)
# print("relative_wr_data:", relative_wr_data)
# print("immediate_wr_data:", immediate_wr_data)
# print("# node_names:", len(node_names))
# print("# node_ids:", len(node_ids))
# Convert RAM and Cores
data_table = convert_data_table(data_table) # Convert RAM and # of Cores, e.g. 1/X
# Run Optimization - Perform evaluation
results = perform_evaluation(data_table, relative_wr_data, immediate_wr_data, node_names, node_ids)
print("Results: ", results)
print("-------------------------------------------------")
# Return the results
return jsonify({'status': 'success', 'results': results})
except Exception as e:
error_message = str(e)
return jsonify({'status': 'error', 'message': error_message}), 500
# Creates a new user
@main_routes.route('/user', methods=['POST'])
def create_user():
data = request.json
result = db_functions.insert_user(data)
return jsonify(result)
# Used in front end to authenticate the user
@main_routes.route('/login', methods=['POST'])
def select_user():
data = request.json
result = db_functions.get_user(data)
return jsonify(result)
# Returns the user's apps
@main_routes.route('/apps', methods=['POST'])
def select_user_apps():
data = request.json
result = db_functions.get_user_apps(data)
return jsonify(result)
# Creates a new app in db
@main_routes.route('/app/create', methods=['POST'])
def create_app():
data = request.json
result = db_functions.insert_app(data)
return jsonify(result)
# Checks if app exists or inserts it in db
@main_routes.route('/app', methods=['POST'])
def check_for_app():
data = request.json
result = db_functions.get_app(data)
if not result:
data['title'] = "Demo App"
data['description'] = "Demo App description"
result = db_functions.insert_app(data)
return jsonify(result)
# Get app from db
@main_routes.route('/app/get', methods=['POST'])
def get_app():
data = request.json
result = db_functions.get_app(data)
return jsonify(result)
# Called by save project in .VUE
@main_routes.route('/app/save', methods=['POST'])
def save_app():
data = request.get_json()
result = save_app_data(data)
return result
# Emulate ActMQ functionality
@main_routes.route('/test_sender', methods=['POST'])
def send():
data = request.get_json()
body = data['body']
application_id = data['application_id']
correlation_id = data['correlation_id']
key = data['key']
sender = activemq.test_send(data)
return data