Ejemplo n.º 1
0
    def __init__(self):
        """
        Load configuration and setup logging
        """
        try:
            config = get_config(self.__class__.__name__)
        except Exception as e:
            config = None

        if config is not None:
            self._logger = get_logger(self.__class__.__name__,
                                      config.get_log_file(),
                                      config.get_file_verbosity(),
                                      config.get_screen_verbosity())

            if config.has("SACCTMGR_PATH"):
                self._sacctmgr = config.get("SACCTMGR_PATH")
            else:
                self._logger.warning(
                    "The configuration does not specify a path to sacctmgr via the key "
                    +
                    "SACCTMGR_PATH. Will use the default path /usr/bin/sacctmgr"
                )
                self._sacctmgr = "/usr/bin/sacctmgr"

            if config.has("SACCT_SCHEMA"):
                self._schema = config.get("SACCT_SCHEMA")
            else:
                self._logger.warning(
                    "The configuration does not specify a SLURM account schema via the key "
                    + "SACCT_SCHEMA. Will use the default schema")
                self._schema = default_slurm_account_schema

            if config.has("DEFAULT_CLUSTER"):
                self._cluster = config.get("DEFAULT_CLUSTER") + ":"
            else:
                self._cluster = ""

            self._block_delete = False
            if config.has("BLOCK_DELETE"):
                self._block_delete = True
        else:
            print(
                "**************************************************************"
            )
            print(
                "The configuration file metaroot[-test].yaml could not be found"
            )
            print(
                "Using default parameters and logging at debug level to screen"
            )
            print(
                "***************************************************************"
            )
            self._logger = get_logger(self.__class__.__name__, "$NONE",
                                      "CRITICAL", "DEBUG")
            self._sacctmgr = "/usr/bin/sacctmgr"
            self._schema = default_slurm_account_schema
            self._cluster = ""
            self._block_delete = True
Ejemplo n.º 2
0
    def test_event_producer_consumer_integration(self):
        st = Thread(target=run_server)
        st.start()

        config = get_config("EVENT_TEST")
        with Producer(config) as p:
            for i in range(10):
                result = p.send({
                    "action": "echo",
                    "message": "hello {0}".format(i)
                })
                self.assertEqual(0, result.status)
            result = p.send("CLOSE_IMMEDIATELY")
            self.assertEqual(0, result.status)
Ejemplo n.º 3
0
    def test_rpc_client_server_integration(self):
        st = Thread(target=run_server)
        st.start()

        config = get_config("RPC_TEST")
        with RPCClient(config) as c:
            for i in range(10):
                message = "hello {0}".format(i)
                result = c.send({"action": "echo", "message": message})
                self.assertEqual(0, result.status)
                self.assertEqual(message, result.response)
            result = c.send("CLOSE_IMMEDIATELY")
            self.assertEqual(0, result.status)
            self.assertEqual("SHUTDOWN_INIT", result.response)

        st.join()
Ejemplo n.º 4
0
    def __init__(self):
        """
        Initialize a new activity stream. Creates the database if it does not exist.
        """
        config = get_config(self.__class__.__name__)

        db_file = config.get_activity_stream_db()
        need_to_create_tables = True
        if os.path.exists(db_file):
            need_to_create_tables = False

        # If the database does not exist, create it
        self._conn = sqlite3.connect(db_file)
        if need_to_create_tables:
            self._conn.execute(
                '''CREATE TABLE events (eventtime timestamp, type integer, action text, arguments text, status integer, message text)'''
            )
            self._conn.commit()
Ejemplo n.º 5
0
 def __init__(self):
     super().__init__(RPCClient(get_config(self.__class__.__name__)))
Ejemplo n.º 6
0
 def __init__(self):
     super().__init__(Producer(get_config(self.__class__.__name__)))
Ejemplo n.º 7
0
def send_email(recipient_user_name: str, subject: str, body: str):
    """
    Method to send an email notification with an HTML body

    Parameters
    ----------
    recipient_user_name: str
        The user name that should receive the notification. This is resolved to an email address using either the
        builtin default resolver, or with a custom resolver specified in the SMTP configuration
    subject: str
        Subject of the email
    body: str
        Body of the email

    Returns
    -------
    True
        If the email was sent
    False
        If the email could not be sent

    """
    try:

        try:
            config = get_config("NOTIFICATIONS")
        except Exception as e:
            config = None

        if config is not None and config.has("SMTP_SERVER") and config.has(
                "SMTP_FROM"):
            # Resolve/validate the recipient email adress
            resolver = DefaultEmailAddressResolver()
            if config.has("SMTP_ADDRESS_RESOLVER"):
                resolver = instantiate_object_from_class_path(
                    config.get("SMTP_ADDRESS_RESOLVER"))

            # # # #
            # The following is based heavily on https://stackoverflow.com/a/32129736/3357118
            msg = email.message.Message()
            msg['Subject'] = subject
            msg['From'] = config.get("SMTP_FROM")
            msg['To'] = resolver.resolve_to_email_address(recipient_user_name)
            msg.add_header('Content-Type', 'text/html')
            msg.set_payload(body)

            s = smtplib.SMTP(config.get("SMTP_SERVER"))

            # Evaluate TLS configuration and start TLS is requested
            if config.has("SMTP_START_TLS") and config.get("SMTP_START_TLS"):
                s.starttls()
            else:
                logger.warning(
                    "The value of SMTP_START_TLS is missing or did not evaluate to True, so not using TLS"
                )

            # If a username and password were specified, authenticte to the SMPT server
            if config.has("SMTP_USER") and config.has("SMTP_PASSWORD"):
                logger.debug("Authenticating to the SMTP server")
                s.login(config.get("SMTP_USER"), config.get("SMTP_PASSWORD"))
            else:
                logger.debug("Not authenticating to the SMTP server")

            s.sendmail(msg['From'], [msg['To']], msg.as_string())
            s.quit()
            # # # # # #

            return True
        else:
            logger.warning(
                "SMTP settings are missing on incomplete. Message \"%s\" to %s could not be sent",
                subject, recipient_user_name)
            return False
    except Exception as e:
        logger.exception(e)
        logger.error("Message \"%s\" to \"%s\" could not be sent", subject,
                     recipient_user_name)
        return False
Ejemplo n.º 8
0
from metaroot.api.result import Result
from metaroot.api.notifications import send_email
from metaroot.config import get_config

config = get_config("DEFAULTREACTIONS")


class DefaultReactions:
    """
    Reactions are defined to occur relative to the result of an action. In the standard deployment, they are applied by
    the router after each action. The default reaction is to send an email any time an error is generated.
    """
    @staticmethod
    def occur_in_response_to(clazz: str, action: str, payload: object,
                             result: Result, n_priors: int) -> int:
        """
        Evaluates the result of an action and performs additional actions as necessary

        Parameters
        ----------
        clazz: str
            The class name that implemented the method handling the action
        action: str
            The name of the method implemented by clazz that was called
        payload: object
            The argument that were passed to the method
        result: Result
            The result of the method call
        n_priors: int
            A value indicating the number of reactions that have occurred during the requested operation. I.e., this
            value is set to 0 as the router begins calling methods of each manager implementing the current request
Ejemplo n.º 9
0
    def __init__(self):
        """
        Initializes the ActivityStream and list of Managers that will be contacted when API requests arrive
        """
        config = get_config(self.__class__.__name__)
        self._logger = get_logger(self.__class__.__name__,
                                  config.get_log_file(),
                                  config.get_file_verbosity(),
                                  config.get_screen_verbosity())

        # Output all config parameters when debugging
        self._logger.debug("VVVVVV Router Config VVVVVV")
        debug_config(config)

        # Instantiate an activity stream to store a record of requests/responses
        if config.get_activity_stream() != "$NONE":
            self._logger.info("Logging activity using %s",
                              config.get_activity_stream())
            self.__activity_stream = instantiate_object_from_class_path(
                config.get_activity_stream())
        else:
            self._logger.info("***Not recording an activity stream***")
            self.__activity_stream = NullActivityStream()

        # Initialize managers to receive requests
        hooks = config.get_hooks()
        self._managers = []
        for hook in hooks:
            try:
                manager = instantiate_object_from_class_path(hook)
                try:
                    # Managers must implement methods "initialize()" and "finalize()" to ensure clean statup/shutdown
                    method = getattr(manager, "initialize")
                    method()
                    getattr(manager, "finalize")
                    self._managers.append(manager)
                    self._logger.info("Loaded manager for %s", hook)
                except AttributeError as e:
                    self._logger.error(
                        "Method 'initialize' or 'finalize' is not defined for manager/hook %s",
                        manager.__class__.__name__)

            except Exception as e:
                self._logger.exception(e)
                self._logger.error("Exception while instantiating hook %s",
                                   hook)

        if len(self._managers) < len(hooks):
            self._logger.error(
                "%d of %d hooks were initialized. refusing to run with reduced set.",
                len(self._managers), len(hooks))
            exit(1)

        # Initialize reactions to take actions relative to requests outcomes
        self._reactions = None
        if config.has("REACTION_HANDLER"):
            self._reactions = instantiate_object_from_class_path(
                config.get("REACTION_HANDLER"))
        else:
            self._logger.info(
                "No reaction handle specified so using DefaultReactions")
            from metaroot.api.reactions import DefaultReactions
            self._reactions = DefaultReactions()

        # Check for read-only operation to block write requests
        self._read_only = config.get_read_only_enabled()