Module src.EnergyManager.EnergyManager

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 __future__ import print_function

import requests
import time
import traceback
import logging

import src.MyUtils.MyUtils as MyUtils
import src.StateDatabase.couchdb as couchdb

CONFIG_DEFAULT_VALUES = {"DEBUG": True, "POLLING_FREQUENCY": 10}
SERVICE_NAME = "energy_manager"


class EnergyManager:

    def __init__(self):
        self.couchdb_handler = couchdb.CouchDBServer()

    def process(self, ):
        logging.basicConfig(filename=SERVICE_NAME + '.log', level=logging.INFO)
        while True:

            # Get service info
            service = MyUtils.get_service(self.couchdb_handler, SERVICE_NAME)
            config = service["config"]
            self.debug = MyUtils.get_config_value(config, CONFIG_DEFAULT_VALUES, "DEBUG")
            polling_frequency = MyUtils.get_config_value(config, CONFIG_DEFAULT_VALUES, "POLLING_FREQUENCY")

            # Heartbeat
            MyUtils.beat(self.couchdb_handler, SERVICE_NAME)

            # Remote database operation
            users = None
            structures = None
            try:
                structures = MyUtils.get_structures(self.couchdb_handler, self.debug, subtype="application")
                users = self.couchdb_handler.get_users()
            except requests.exceptions.HTTPError as e:
                MyUtils.log_error("Couldn't get users", self.debug)
                MyUtils.log_error(str(e), self.debug)

            for user in users:
                MyUtils.log_info("Processing user {0}".format(user["name"]), self.debug)
                max_energy = user["energy"]["max"]

                # Add up all the shares
                total_shares = 0
                for structure in structures:
                    if structure["name"] in user["clusters"]:
                        total_shares += structure["resources"]["energy"]["shares"]

                total_user_energy = 0
                for structure in structures:
                    if structure["name"] in user["clusters"]:
                        percentage = structure["resources"]["energy"]["shares"] / total_shares
                        limit_energy = max_energy * percentage
                        current_energy = structure["resources"]["energy"]["max"]

                        if current_energy != limit_energy:
                            structure["resources"]["energy"]["max"] = limit_energy
                            self.couchdb_handler.update_structure(structure)

                        MyUtils.log_info("Processed cluster {0} with an energy share of {1}% and {2} Watts".format(
                            structure["name"], str("%.2f" % (100 * percentage)), limit_energy), self.debug)

                        if "used" in structure["resources"]["energy"]:
                            total_user_energy += structure["resources"]["energy"]["used"]

                MyUtils.log_info("Updated energy consumed by user {0}".format(user["name"]), self.debug)
                user["energy"]["used"] = total_user_energy
                self.couchdb_handler.update_user(user)

            MyUtils.log_info(
                "Epoch processed at {0}".format(MyUtils.get_time_now_string()), self.debug)
            time.sleep(polling_frequency)


def main():
    try:
        energy_manager = EnergyManager()
        energy_manager.process()
    except Exception as e:
        MyUtils.log_error("{0} {1}".format(str(e), str(traceback.format_exc())), debug=True)


if __name__ == "__main__":
    main()

Functions

def main()
Expand source code
def main():
    try:
        energy_manager = EnergyManager()
        energy_manager.process()
    except Exception as e:
        MyUtils.log_error("{0} {1}".format(str(e), str(traceback.format_exc())), debug=True)

Classes

class EnergyManager
Expand source code
class EnergyManager:

    def __init__(self):
        self.couchdb_handler = couchdb.CouchDBServer()

    def process(self, ):
        logging.basicConfig(filename=SERVICE_NAME + '.log', level=logging.INFO)
        while True:

            # Get service info
            service = MyUtils.get_service(self.couchdb_handler, SERVICE_NAME)
            config = service["config"]
            self.debug = MyUtils.get_config_value(config, CONFIG_DEFAULT_VALUES, "DEBUG")
            polling_frequency = MyUtils.get_config_value(config, CONFIG_DEFAULT_VALUES, "POLLING_FREQUENCY")

            # Heartbeat
            MyUtils.beat(self.couchdb_handler, SERVICE_NAME)

            # Remote database operation
            users = None
            structures = None
            try:
                structures = MyUtils.get_structures(self.couchdb_handler, self.debug, subtype="application")
                users = self.couchdb_handler.get_users()
            except requests.exceptions.HTTPError as e:
                MyUtils.log_error("Couldn't get users", self.debug)
                MyUtils.log_error(str(e), self.debug)

            for user in users:
                MyUtils.log_info("Processing user {0}".format(user["name"]), self.debug)
                max_energy = user["energy"]["max"]

                # Add up all the shares
                total_shares = 0
                for structure in structures:
                    if structure["name"] in user["clusters"]:
                        total_shares += structure["resources"]["energy"]["shares"]

                total_user_energy = 0
                for structure in structures:
                    if structure["name"] in user["clusters"]:
                        percentage = structure["resources"]["energy"]["shares"] / total_shares
                        limit_energy = max_energy * percentage
                        current_energy = structure["resources"]["energy"]["max"]

                        if current_energy != limit_energy:
                            structure["resources"]["energy"]["max"] = limit_energy
                            self.couchdb_handler.update_structure(structure)

                        MyUtils.log_info("Processed cluster {0} with an energy share of {1}% and {2} Watts".format(
                            structure["name"], str("%.2f" % (100 * percentage)), limit_energy), self.debug)

                        if "used" in structure["resources"]["energy"]:
                            total_user_energy += structure["resources"]["energy"]["used"]

                MyUtils.log_info("Updated energy consumed by user {0}".format(user["name"]), self.debug)
                user["energy"]["used"] = total_user_energy
                self.couchdb_handler.update_user(user)

            MyUtils.log_info(
                "Epoch processed at {0}".format(MyUtils.get_time_now_string()), self.debug)
            time.sleep(polling_frequency)

Methods

def process(self)
Expand source code
def process(self, ):
    logging.basicConfig(filename=SERVICE_NAME + '.log', level=logging.INFO)
    while True:

        # Get service info
        service = MyUtils.get_service(self.couchdb_handler, SERVICE_NAME)
        config = service["config"]
        self.debug = MyUtils.get_config_value(config, CONFIG_DEFAULT_VALUES, "DEBUG")
        polling_frequency = MyUtils.get_config_value(config, CONFIG_DEFAULT_VALUES, "POLLING_FREQUENCY")

        # Heartbeat
        MyUtils.beat(self.couchdb_handler, SERVICE_NAME)

        # Remote database operation
        users = None
        structures = None
        try:
            structures = MyUtils.get_structures(self.couchdb_handler, self.debug, subtype="application")
            users = self.couchdb_handler.get_users()
        except requests.exceptions.HTTPError as e:
            MyUtils.log_error("Couldn't get users", self.debug)
            MyUtils.log_error(str(e), self.debug)

        for user in users:
            MyUtils.log_info("Processing user {0}".format(user["name"]), self.debug)
            max_energy = user["energy"]["max"]

            # Add up all the shares
            total_shares = 0
            for structure in structures:
                if structure["name"] in user["clusters"]:
                    total_shares += structure["resources"]["energy"]["shares"]

            total_user_energy = 0
            for structure in structures:
                if structure["name"] in user["clusters"]:
                    percentage = structure["resources"]["energy"]["shares"] / total_shares
                    limit_energy = max_energy * percentage
                    current_energy = structure["resources"]["energy"]["max"]

                    if current_energy != limit_energy:
                        structure["resources"]["energy"]["max"] = limit_energy
                        self.couchdb_handler.update_structure(structure)

                    MyUtils.log_info("Processed cluster {0} with an energy share of {1}% and {2} Watts".format(
                        structure["name"], str("%.2f" % (100 * percentage)), limit_energy), self.debug)

                    if "used" in structure["resources"]["energy"]:
                        total_user_energy += structure["resources"]["energy"]["used"]

            MyUtils.log_info("Updated energy consumed by user {0}".format(user["name"]), self.debug)
            user["energy"]["used"] = total_user_energy
            self.couchdb_handler.update_user(user)

        MyUtils.log_info(
            "Epoch processed at {0}".format(MyUtils.get_time_now_string()), self.debug)
        time.sleep(polling_frequency)