Module src.Orchestrator.rules
Expand source code
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2022 Universidade da Coruña
# Authors:
# - Jonatan Enes [main](jonatan.enes@udc.es)
# - Roberto R. Expósito
# - Juan Touriño
#
# This file is part of the ServerlessContainers framework, from
# now on referred to as ServerlessContainers.
#
# ServerlessContainers is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, either version 3
# of the License, or (at your option) any later version.
#
# ServerlessContainers is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ServerlessContainers. If not, see <http://www.gnu.org/licenses/>.
from flask import Blueprint
from flask import abort
from flask import jsonify
from flask import request
import time
from src.Orchestrator.utils import BACK_OFF_TIME_MS, MAX_TRIES, get_db
rules_routes = Blueprint('rules', __name__)
def retrieve_rule(rule_name):
try:
return get_db().get_rule(rule_name)
except ValueError:
return abort(404)
@rules_routes.route("/rule/<rule_name>", methods=['GET'])
def get_rule(rule_name):
return jsonify(retrieve_rule(rule_name))
@rules_routes.route("/rule/", methods=['GET'])
def get_rules():
return jsonify(get_db().get_rules())
@rules_routes.route("/rule/<rule_name>/activate", methods=['PUT'])
def activate_rule(rule_name):
rule = retrieve_rule(rule_name)
put_done = rule["active"]
tries = 0
while not put_done:
tries += 1
rule = retrieve_rule(rule_name)
rule["active"] = True
get_db().update_rule(rule)
rule = retrieve_rule(rule_name)
time.sleep(BACK_OFF_TIME_MS / 1000)
put_done = rule["active"]
if tries >= MAX_TRIES:
return abort(400, {"message": "MAX_TRIES updating database document"})
return jsonify(201)
@rules_routes.route("/rule/<rule_name>/deactivate", methods=['PUT'])
def deactivate_rule(rule_name):
rule = retrieve_rule(rule_name)
put_done = not rule["active"]
tries = 0
while not put_done:
tries += 1
rule = retrieve_rule(rule_name)
rule["active"] = False
get_db().update_rule(rule)
time.sleep(BACK_OFF_TIME_MS / 1000)
rule = retrieve_rule(rule_name)
put_done = not rule["active"]
if tries >= MAX_TRIES:
return abort(400, {"message": "MAX_TRIES updating database document"})
return jsonify(201)
@rules_routes.route("/rule/<rule_name>/amount", methods=['PUT'])
def change_amount_rule(rule_name):
rule = retrieve_rule(rule_name)
if rule["generates"] != "requests" or rule["rescale_type"] != "up":
return abort(400, {"message": "This rule can't have its amount changed"})
try:
amount = int(request.json["value"])
except KeyError:
return abort(400)
rule = retrieve_rule(rule_name)
put_done = rule["amount"] == amount
tries = 0
while not put_done:
tries += 1
rule = retrieve_rule(rule_name)
rule["amount"] = amount
get_db().update_rule(rule)
time.sleep(BACK_OFF_TIME_MS / 1000)
rule = retrieve_rule(rule_name)
put_done = rule["amount"] == amount
if tries >= MAX_TRIES:
return abort(400, {"message": "MAX_TRIES updating database document"})
return jsonify(201)
@rules_routes.route("/rule/<rule_name>/policy", methods=['PUT'])
def change_policy_rule(rule_name):
rule = retrieve_rule(rule_name)
if rule["generates"] != "requests" or rule["rescale_type"] != "up":
return abort(400, {"message": "This rule can't have its policy changed"})
rescale_policy = request.json["value"]
put_done = rule["rescale_policy"] == rescale_policy
tries = 0
if rescale_policy not in ["amount", "proportional"]:
return abort(400, {"message": "Invalid policy"})
else:
while not put_done:
tries += 1
rule = retrieve_rule(rule_name)
rule["rescale_policy"] = rescale_policy
get_db().update_rule(rule)
time.sleep(BACK_OFF_TIME_MS / 1000)
rule = retrieve_rule(rule_name)
put_done = rule["rescale_policy"] == rescale_policy
if tries >= MAX_TRIES:
return abort(400, {"message": "MAX_TRIES updating database document"})
return jsonify(201)
@rules_routes.route("/rule/<rule_name>/events_required", methods=['PUT'])
def change_event_up_amount(rule_name):
put_done = False
tries = 0
try:
new_amount = int(request.json["value"])
if new_amount < 0:
return abort(400, {"message": "Invalid amount, only 0 or greater are valid"})
event_type = request.json["event_type"]
if event_type not in ["down", "up"]:
return abort(400, {"message": "Invalid type of event, only 'up' or 'down' accepted"})
except KeyError:
return abort(400, {"message": "Invalid amount"})
rule = retrieve_rule(rule_name)
if rule["rescale_type"] not in ["down", "up"]:
return abort(400, {"message": "Can't apply this change to this rule"})
while not put_done:
tries += 1
rule = retrieve_rule(rule_name)
correct_key = None
list_rules_entry = 0
for part in rule["rule"]["and"]:
# Get the first and only value from the dictionary
first_key = list(part.keys())[0]
first_val = part[first_key]
rule_part = first_val[0]["var"]
rule_amount = first_val[1]
if event_type == "up":
if rule_part == "events.scale.up":
rule["rule"]["and"][list_rules_entry][first_key][1] = new_amount
correct_key = first_key
break
if event_type == "down":
if rule_part == "events.scale.down":
rule["rule"]["and"][list_rules_entry][first_key][1] = new_amount
rule["events_to_remove"] = new_amount
correct_key = first_key
break
list_rules_entry += 1
get_db().update_rule(rule)
time.sleep(BACK_OFF_TIME_MS / 1000)
rule = retrieve_rule(rule_name)
put_done = rule["rule"]["and"][list_rules_entry][correct_key][1] == new_amount
if tries >= MAX_TRIES:
return abort(400, {"message": "MAX_TRIES updating database document"})
return jsonify(201)
Functions
def activate_rule(rule_name)
-
Expand source code
@rules_routes.route("/rule/<rule_name>/activate", methods=['PUT']) def activate_rule(rule_name): rule = retrieve_rule(rule_name) put_done = rule["active"] tries = 0 while not put_done: tries += 1 rule = retrieve_rule(rule_name) rule["active"] = True get_db().update_rule(rule) rule = retrieve_rule(rule_name) time.sleep(BACK_OFF_TIME_MS / 1000) put_done = rule["active"] if tries >= MAX_TRIES: return abort(400, {"message": "MAX_TRIES updating database document"}) return jsonify(201)
def change_amount_rule(rule_name)
-
Expand source code
@rules_routes.route("/rule/<rule_name>/amount", methods=['PUT']) def change_amount_rule(rule_name): rule = retrieve_rule(rule_name) if rule["generates"] != "requests" or rule["rescale_type"] != "up": return abort(400, {"message": "This rule can't have its amount changed"}) try: amount = int(request.json["value"]) except KeyError: return abort(400) rule = retrieve_rule(rule_name) put_done = rule["amount"] == amount tries = 0 while not put_done: tries += 1 rule = retrieve_rule(rule_name) rule["amount"] = amount get_db().update_rule(rule) time.sleep(BACK_OFF_TIME_MS / 1000) rule = retrieve_rule(rule_name) put_done = rule["amount"] == amount if tries >= MAX_TRIES: return abort(400, {"message": "MAX_TRIES updating database document"}) return jsonify(201)
def change_event_up_amount(rule_name)
-
Expand source code
@rules_routes.route("/rule/<rule_name>/events_required", methods=['PUT']) def change_event_up_amount(rule_name): put_done = False tries = 0 try: new_amount = int(request.json["value"]) if new_amount < 0: return abort(400, {"message": "Invalid amount, only 0 or greater are valid"}) event_type = request.json["event_type"] if event_type not in ["down", "up"]: return abort(400, {"message": "Invalid type of event, only 'up' or 'down' accepted"}) except KeyError: return abort(400, {"message": "Invalid amount"}) rule = retrieve_rule(rule_name) if rule["rescale_type"] not in ["down", "up"]: return abort(400, {"message": "Can't apply this change to this rule"}) while not put_done: tries += 1 rule = retrieve_rule(rule_name) correct_key = None list_rules_entry = 0 for part in rule["rule"]["and"]: # Get the first and only value from the dictionary first_key = list(part.keys())[0] first_val = part[first_key] rule_part = first_val[0]["var"] rule_amount = first_val[1] if event_type == "up": if rule_part == "events.scale.up": rule["rule"]["and"][list_rules_entry][first_key][1] = new_amount correct_key = first_key break if event_type == "down": if rule_part == "events.scale.down": rule["rule"]["and"][list_rules_entry][first_key][1] = new_amount rule["events_to_remove"] = new_amount correct_key = first_key break list_rules_entry += 1 get_db().update_rule(rule) time.sleep(BACK_OFF_TIME_MS / 1000) rule = retrieve_rule(rule_name) put_done = rule["rule"]["and"][list_rules_entry][correct_key][1] == new_amount if tries >= MAX_TRIES: return abort(400, {"message": "MAX_TRIES updating database document"}) return jsonify(201)
def change_policy_rule(rule_name)
-
Expand source code
@rules_routes.route("/rule/<rule_name>/policy", methods=['PUT']) def change_policy_rule(rule_name): rule = retrieve_rule(rule_name) if rule["generates"] != "requests" or rule["rescale_type"] != "up": return abort(400, {"message": "This rule can't have its policy changed"}) rescale_policy = request.json["value"] put_done = rule["rescale_policy"] == rescale_policy tries = 0 if rescale_policy not in ["amount", "proportional"]: return abort(400, {"message": "Invalid policy"}) else: while not put_done: tries += 1 rule = retrieve_rule(rule_name) rule["rescale_policy"] = rescale_policy get_db().update_rule(rule) time.sleep(BACK_OFF_TIME_MS / 1000) rule = retrieve_rule(rule_name) put_done = rule["rescale_policy"] == rescale_policy if tries >= MAX_TRIES: return abort(400, {"message": "MAX_TRIES updating database document"}) return jsonify(201)
def deactivate_rule(rule_name)
-
Expand source code
@rules_routes.route("/rule/<rule_name>/deactivate", methods=['PUT']) def deactivate_rule(rule_name): rule = retrieve_rule(rule_name) put_done = not rule["active"] tries = 0 while not put_done: tries += 1 rule = retrieve_rule(rule_name) rule["active"] = False get_db().update_rule(rule) time.sleep(BACK_OFF_TIME_MS / 1000) rule = retrieve_rule(rule_name) put_done = not rule["active"] if tries >= MAX_TRIES: return abort(400, {"message": "MAX_TRIES updating database document"}) return jsonify(201)
def get_rule(rule_name)
-
Expand source code
@rules_routes.route("/rule/<rule_name>", methods=['GET']) def get_rule(rule_name): return jsonify(retrieve_rule(rule_name))
def get_rules()
-
Expand source code
@rules_routes.route("/rule/", methods=['GET']) def get_rules(): return jsonify(get_db().get_rules())
def retrieve_rule(rule_name)
-
Expand source code
def retrieve_rule(rule_name): try: return get_db().get_rule(rule_name) except ValueError: return abort(404)