Example #1
0
def recovery():
    """Recover after a crash any incomplete procedure.

    It assumes that the executor is already running and that the recovery
    is sequential. In the future, we may consider optimizing this function.

    :return: False, if nothing bad happened while recovering. Otherwise,
             return True.
    """
    Checkpoint.cleanup()

    error = False
    for checkpoint in Checkpoint.unfinished():

        if checkpoint.undo_action:
            procedure = _executor.Executor().enqueue_procedure(
                False, checkpoint.undo_action,
                "Recovering %s." % (checkpoint.undo_action, ),
                checkpoint.lockable_objects, *checkpoint.param_args,
                **checkpoint.param_kwargs)
            procedure.wait()
            if procedure.status[-1]['success'] != _executor.Job.SUCCESS:
                _LOGGER.error("Error while recovering %s.",
                              (checkpoint.do_action, ))
                error = True

    actions = []
    procedure_uuid = None
    for checkpoint in Checkpoint.registered():
        actions.append({
            "job":
            checkpoint.job_uuid,
            "action":
            (checkpoint.do_action, "Recovering %s." % (checkpoint.do_action, ),
             checkpoint.param_args, checkpoint.param_kwargs)
        })

        if procedure_uuid is not None and \
            procedure_uuid != checkpoint.proc_uuid:
            _executor.Executor().reschedule_procedure(
                procedure_uuid, actions, checkpoint.lockable_objects)
            procedure_uuid = None
            actions = []

        procedure_uuid = checkpoint.proc_uuid

    if procedure_uuid is not None:
        _executor.Executor().reschedule_procedure(procedure_uuid, actions,
                                                  checkpoint.lockable_objects)

    return error
Example #2
0
 def __init__(self):
     """Constructor for Handler.
     """
     super(Handler, self).__init__()
     self.__executor = _executor.Executor()
     self.__instance_for = {}
     self.__blocks_for = {}
Example #3
0
def check_number_threads(increasing=0):
    """Check the number of threads that are running and whether the maximum
    number of connections in the state store is configured accordingly.

    :param increasing: Whether you want to increase the number of threads and
                       how many threads. Default is zero.

    It raises a ConfigurationError exception if the number of connections is
    too small.
    """
    from mysql.fabric import (
        errors as _errors,
        executor as _executor,
        persistence as _persistence,
        services as _services,
        server as _server,
    )

    n_sessions = _services.ServiceManager().get_number_sessions()
    n_executors = _executor.Executor().get_number_executors()
    n_failure_detectors = \
        len(_server.Group.groups_by_status(_server.Group.ACTIVE))
    n_controls = 1
    persister = _persistence.current_persister()
    max_allowed_connections = persister.max_allowed_connections()
    if (n_sessions +  n_executors + n_controls + n_failure_detectors +\
        increasing) > (max_allowed_connections - 1):
        raise _errors.ConfigurationError(
            "Too many threads requested. Session threads (%s), Executor "
            "threads (%s), Control threads (%s) and Failure Detector threads "
            "(%s). The maximum number of threads allowed is (%s). Increase "
            "the maximum number of connections in the state store in order "
            "to increase this limit." %
            (n_sessions, n_executors, n_controls, n_failure_detectors,
             max_allowed_connections - 1))
Example #4
0
def _configure_connections(config):
    """Configure information on database connection and remote servers.

    :param config: Configuration read from configuration file.
    """
    # Configure the number of concurrent executors.
    executor = _executor.Executor()
    executor.set_number_executors(1)

    # Fetch options to configure the state store.
    address = config.get('storage', 'address')

    try:
        host, port = address.split(':')
        port = int(port)
    except ValueError:
        host = address
        port = 3306

    user = config.get('storage', 'user')
    database = config.get('storage', 'database')

    try:
        password = config.get('storage', 'password')
    except _config.NoOptionError:
        password = _get_password("Storage password: "******"storage", "connection_timeout")
        connection_timeout = float(connection_timeout)
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        connection_timeout = None

    try:
        connection_attempts = config.get("storage", "connection_attempts")
        connection_attempts = int(connection_attempts)
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        connection_attempts = None

    try:
        connection_delay = config.get("storage", "connection_delay")
        connection_delay = int(connection_delay)
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        connection_delay = None

    try:
        auth_plugin = config.get("storage", "auth_plugin")
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        auth_plugin = None

    # Define state store configuration.
    _persistence.init(host=host,
                      port=port,
                      user=user,
                      password=password,
                      database=database,
                      connection_timeout=connection_timeout,
                      connection_attempts=connection_attempts,
                      connection_delay=connection_delay,
                      auth_plugin=auth_plugin)
    def _report_failure(self, server):
        """Mark the server as faulty and report a failure.

        The thread is created to allow the built-in failure detector
        to continue monitoring the servers so that if the report failure
        hangs, it will kill all connections to faulty servers thus
        eventually freeing the thread.

        Not though that the report failure is not crash-safe so it might
        fail without promoting a new server to master. In the future, we
        will circumvent this limitation.
        """
        try:
            _persistence.init_thread()

            server.status = MySQLServer.FAULTY
            self.__connection_manager.purge_connections(server)

            procedures = trigger(
                "REPORT_FAILURE", None, str(server.uuid),
                threading.current_thread().name, MySQLServer.FAULTY, False
            )
            executor = _executor.Executor()
            for procedure in procedures:
                executor.wait_for_procedure(procedure)

            _persistence.deinit_thread()
        finally:
            self.__thread_report_failure = False
Example #6
0
    def execute(self, proc_uuids=None):
        """Wait until a set of procedures uniquely identified by their uuids
        finish their execution.

        However, before starting waiting, the function checks if the procedures
        exist. If one of the procedures is not found, the following exception
        is raised :class:`~mysql.fabric.errors.ProcedureError`.

        :param proc_uuids: Iterable with procedures' UUIDs.
        """
        if proc_uuids is None:
            raise _errors.ProcedureError(
                "Please, specify which procedure(s) you will be waiting for.")

        procedures = []
        for proc_uuid in proc_uuids:
            proc_uuid = _uuid.UUID(proc_uuid.strip())
            procedure = _executor.Executor().get_procedure(proc_uuid)
            if not procedure:
                raise _errors.ProcedureError("Procedure (%s) was not found." %
                                             (proc_uuid, ))
            procedures.append(procedure)

        command_results = CommandResult(error=None)
        for procedure in procedures:
            command_result = ProcedureCommand.wait_for_procedures([
                procedure,
            ], True)
            if command_result.error is None:
                for result in command_result.results:
                    command_results.append_result(result)
            else:
                result = ResultSet(names=['uuid', 'error'], types=[str, str])
                result.append_row(
                    [str(procedure.uuid),
                     str(command_result.error)])
                command_results.append_result(result)

        return command_results
Example #7
0
    def execute(self, proc_uuids):
        """Wait until a set of procedures uniquely identified by their uuids
        finish their execution.

        However, before starting waiting, the function checks if the procedures
        exist. If one of the procedures is not found, the following exception
        is raised :class:`~mysql.fabric.errors.ProcedureError`.

        :param proc_uuids: Iterable with procedures' uuids.
        """
        procs = []
        it_proc_uuids = proc_uuids.split(",")
        for proc_uuid in it_proc_uuids:
            proc_uuid = _uuid.UUID(proc_uuid.strip())
            procedure = _executor.Executor().get_procedure(proc_uuid)
            if not procedure:
                raise _errors.ProcedureError("Procedure (%s) was not found." %
                                             (proc_uuid, ))
            procs.append(procedure)

        for procedure in procs:
            procedure.wait()

        return CommandResult(None)
Example #8
0
    def wait_for_procedures(procedure_param, synchronous):
        """Wait until a procedure completes its execution and return
        detailed information on it.

        However, if the parameter synchronous is not set, only the
        procedure's uuid is returned because it is not safe to access
        the procedure's information while it may be executing.

        :param procedure_param: Iterable with procedures.
        :param synchronous: Whether should wait until the procedure
                            finishes its execution or not.
        :return: A :class:`CommandResult` instance with the execution result.
        :rtype: CommandResult
        """
        assert len(procedure_param) == 1
        synchronous = str(synchronous).upper() not in ("FALSE", "0")
        if not synchronous:
            info = ResultSet(names=['uuid'], types=[str])
            info.append_row([str(procedure_param[-1].uuid)])
            return CommandResult(None, results=info)

        executor = _executor.Executor()
        for procedure in procedure_param:
            executor.wait_for_procedure(procedure)
        _LOGGER.debug("Result after wait: uuid='%s', status='%s', result='%s'",
                      str(procedure_param[-1].uuid),
                      procedure_param[-1].status, procedure_param[-1].result)

        # We look at the diagnosis of the last entry to decide the
        # status of the procedure execution.
        operation = procedure_param[-1].status[-1]
        complete = operation['state'] == _executor.Job.COMPLETE
        success = operation['success'] == _executor.Job.SUCCESS

        if success:
            result_field = procedure_param[-1].result
            info = ResultSet(
                names=('uuid', 'finished', 'success', 'result'),
                types=(str, bool, bool, type(result_field)),
            )
            info.append_row([
                str(procedure_param[-1].uuid),
                complete,
                success,
                result_field,
            ])
            _LOGGER.debug("Success: uuid='%s', result='%s'",
                          str(procedure_param[-1].uuid),
                          str(procedure_param[-1].result))

            rset = ResultSet(
                names=('state', 'success', 'when', 'description'),
                types=(int, int, float, str),
            )
            for item in procedure_param[-1].status:
                rset.append_row([
                    item['state'],
                    item['success'],
                    item['when'],
                    item['description'],
                ])
            return CommandResult(None, results=[info, rset])
        else:
            # The error message is the last line of the diagnosis, so
            # we get it from there.
            error = operation['diagnosis'].split("\n")[-2]
            _LOGGER.debug("Failure: error='%s'", error)
            return CommandResult(error)
    def _run(self):
        """Function that verifies servers' availabilities.
        """
        from mysql.fabric.server import (
            Group,
            MySQLServer,
            ConnectionManager,
        )

        ignored_status = [MySQLServer.FAULTY]
        quarantine = {}
        interval = FailureDetector._DETECTION_INTERVAL
        detections = FailureDetector._DETECTIONS
        detection_timeout = FailureDetector._DETECTION_TIMEOUT
        connection_manager = ConnectionManager()
        slave_deep_checks = FailureDetector._SLAVE_DEEP_CHECKS

        _persistence.init_thread()

        while self.__check:
            try:
                unreachable = set()
                group = Group.fetch(self.__group_id)
                if group is not None:
                    for server in group.servers():
                        if server.status in ignored_status:

                            ### Server is FAULTY
                            connection_manager.kill_connections(server)
                            continue
                        else:
                            ### Server is Not FAULTY
                            if MySQLServer.is_alive(server, detection_timeout):

                                ### Server is alive
                                ### check depends on `slave_deep_checks` parameter
                                if slave_deep_checks:

                                    ### When server is alive and status != FAULTY
                                    is_master= (group.master == server.uuid)
                                    if not is_master:
                                        ### Checking master is dead or alive.
                                        master_server = MySQLServer.fetch(group.master)
    
                                        if MySQLServer.is_alive(master_server, detection_timeout):
    
                                            ### Checking is replication valid or not if master is alive.
                                            server.connect()
                                            slave_issues, why_slave_issues = \
                                                _replication.check_slave_issues(server)
                                            if slave_issues:
        
                                                if (why_slave_issues['io_error'] and \
                                                    why_slave_issues['io_errno'] == 2003):
        
                                                    ### Nothing to do during reconnecting, just logging
                                                    _LOGGER.info(why_slave_issues)
        
                                                else:
                                                        
                                                    ### If slave threads are not running, set status to SPARE
                                                    server.status = MySQLServer.SPARE
        
                                            ### Done slave_issues.
                                            server.disconnect()
    
                                        ### Endif MySQLServer.is_alive(master_server, detection_timeout)
                                    ### Endif not is_master
                                ### Endif slave_deep_checks
                                continue
                            ### Else MySQLServer.is_alive(server, detection_timeout)
                            else:

                                unreachable.add(server.uuid)

                                _LOGGER.warning(
                                    "Server (%s) in group (%s) is unreachable.",
                                    server.uuid, self.__group_id
                                )
        
                                unstable = False
                                failed_attempts = 0
                                if server.uuid not in quarantine:
                                    quarantine[server.uuid] = failed_attempts = 1
                                else:
                                    failed_attempts = quarantine[server.uuid] + 1
                                    quarantine[server.uuid] = failed_attempts
                                if failed_attempts >= detections:
                                    unstable = True
        
                                can_set_faulty = group.can_set_server_faulty(
                                    server, get_time()
                                )
                                if unstable and can_set_faulty:
                                    # We have to make this transactional and make the
                                    # failover (i.e. report failure) robust to failures.
                                    # Otherwise, a master might be set to faulty and
                                    # a new one never promoted.
                                    server.status = MySQLServer.FAULTY
                                    connection_manager.kill_connections(server)
                                    
                                    procedures = trigger("REPORT_FAILURE", None,
                                        str(server.uuid),
                                        threading.current_thread().name,
                                        MySQLServer.FAULTY, False
                                    )
                                    executor = _executor.Executor()
                                    for procedure in procedures:
                                        executor.wait_for_procedure(procedure)

                            ### Endif MySQLServer.is_alive(server, detection_timeout)
                        ### Endif server.status in ignored_status
                    ### End for server in group.servers()
                ### Endif group is not None
                for uuid in quarantine.keys():
                    if uuid not in unreachable:
                        del quarantine[uuid]

            except (_errors.ExecutorError, _errors.DatabaseError):
                pass
            except Exception as error:
                _LOGGER.exception(error)

            time.sleep(interval)

        _persistence.deinit_thread()
Example #10
0
    def _run(self):
        """Function that verifies servers' availabilities.
        """
        from mysql.fabric.server import (
            Group,
            MySQLServer,
            ConnectionManager,
        )

        ignored_status = [MySQLServer.FAULTY]
        quarantine = {}
        interval = FailureDetector._DETECTION_INTERVAL
        detections = FailureDetector._DETECTIONS
        detection_timeout = FailureDetector._DETECTION_TIMEOUT
        connection_manager = ConnectionManager()

        _persistence.init_thread()

        while self.__check:
            try:
                unreachable = set()
                group = Group.fetch(self.__group_id)
                if group is not None:
                    for server in group.servers():
                        if server.status in ignored_status or \
                            MySQLServer.is_alive(server, detection_timeout):
                            if server.status == MySQLServer.FAULTY:
                                connection_manager.kill_connections(server)
                            continue

                        unreachable.add(server.uuid)

                        _LOGGER.warning(
                            "Server (%s) in group (%s) is unreachable.",
                            server.uuid, self.__group_id
                        )

                        unstable = False
                        failed_attempts = 0
                        if server.uuid not in quarantine:
                            quarantine[server.uuid] = failed_attempts = 1
                        else:
                            failed_attempts = quarantine[server.uuid] + 1
                            quarantine[server.uuid] = failed_attempts
                        if failed_attempts >= detections:
                            unstable = True

                        can_set_faulty = group.can_set_server_faulty(
                            server, get_time()
                        )
                        if unstable and can_set_faulty:
                            # We have to make this transactional and make the
                            # failover (i.e. report failure) robust to failures.
                            # Otherwise, a master might be set to faulty and
                            # a new one never promoted.
                            server.status = MySQLServer.FAULTY
                            connection_manager.kill_connections(server)
                            
                            procedures = trigger("REPORT_FAILURE", None,
                                str(server.uuid),
                                threading.current_thread().name,
                                MySQLServer.FAULTY, False
                            )
                            executor = _executor.Executor()
                            for procedure in procedures:
                                executor.wait_for_procedure(procedure)

                for uuid in quarantine.keys():
                    if uuid not in unreachable:
                        del quarantine[uuid]

            except (_errors.ExecutorError, _errors.DatabaseError):
                pass
            except Exception as error:
                _LOGGER.exception(error)

            time.sleep(interval / detections)

        _persistence.deinit_thread()
    def test_recovery_chain_jobs(self):
        """Check checkpoint and recovery when a job triggers another
        job.
        """
        global COUNT_1, COUNT_2
        count_1 = 10
        count_2 = 30
        proc_uuid = _uuid.UUID("01da10ed-514e-43a4-8388-ab05c04d67e1")
        lockable_objects = set(["lock"])
        job_uuid = _uuid.UUID("e4e1ba17-ff1d-45e6-a83c-5655ea5bb646")
        job_sequence = 0
        job_uuid_registered_1 = \
            _uuid.UUID("aaa1ba17-ff1d-45e6-a83c-5655ea5bb646")
        job_sequence_1 = 1
        job_uuid_registered_2 = \
            _uuid.UUID("bbb1ba17-ff1d-45e6-a83c-5655ea5bb646")
        job_sequence_2 = 2
        do_action = check_do_action
        do_action_registered_1 = check_do_action_registered_1
        do_action_registered_2 = check_do_action_registered_2
        do_action_fqn = do_action.__module__ + "." + do_action.__name__
        do_action_registered_1_fqn = \
            do_action_registered_1.__module__ + "." + \
            do_action_registered_1.__name__
        do_action_registered_2_fqn = \
            do_action_registered_2.__module__ + "." + \
            do_action_registered_2.__name__
        args = (count_1, count_2)
        kwargs = {}

        # BEGIN DO FINISH (FAILURE)
        COUNT_1 = 0
        COUNT_2 = 0
        checkpoint = _checkpoint.Checkpoint(
            proc_uuid, lockable_objects, job_uuid, job_sequence,
            do_action_fqn, args, kwargs
            )
        registered_1 = _checkpoint.Checkpoint(
            proc_uuid, lockable_objects, job_uuid_registered_1,
            job_sequence_1, do_action_registered_1_fqn, args, kwargs
            )
        registered_2 = _checkpoint.Checkpoint(
            proc_uuid, lockable_objects, job_uuid_registered_2,
            job_sequence_2, do_action_registered_2_fqn, args, kwargs
            )
        checkpoint.register()
        checkpoint.begin()
        self.persister.begin()
        do_action(10, 30)
        checkpoint.finish()
        registered_1.register()
        registered_2.register()
        self.persister.commit()

        self.assertEqual(COUNT_1, 10)
        self.assertEqual(COUNT_2, 30)
        self.assertEqual(MyTransAction.count(), 1)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 2)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 3)
        _checkpoint.Checkpoint.cleanup()
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 3)
        _recovery.recovery()
        executor = _executor.Executor()
        procedure = executor.get_procedure(checkpoint.proc_uuid)
        if procedure is not None:
            procedure.wait()
        self.assertEqual(COUNT_1, 30)
        self.assertEqual(COUNT_2, 90)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 0)
        executor.remove_procedure(proc_uuid)
    def test_recovery_single_job(self):
        """Check checkpoint and recovery with a single job.
        """
        global COUNT_1, COUNT_2
        count_1 = 10
        count_2 = 30
        proc_uuid = _uuid.UUID("9f994e3a-a732-43ba-8aab-f1051f553437")
        lockable_objects = set(["lock"])
        job_uuid = _uuid.UUID("64835080-2114-46de-8fbf-8caba8e8cd90")
        job_sequence = 0
        do_action = check_do_action
        do_action_fqn = do_action.__module__ + "." + do_action.__name__
        args = (count_1, count_2)
        kwargs = {}

        # (FAILURE) BEGIN DO FINISH
        COUNT_1 = 0
        COUNT_2 = 0
        checkpoint = _checkpoint.Checkpoint(
            proc_uuid, lockable_objects, job_uuid, job_sequence,
            do_action_fqn, args, kwargs
        )
        checkpoint.register()

        self.assertEqual(COUNT_1, 0)
        self.assertEqual(COUNT_2, 0)

        self.assertEqual(MyTransAction.count(), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 1)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 1)
        _checkpoint.Checkpoint.cleanup()
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 1)
        _recovery.recovery()
        executor = _executor.Executor()
        procedure = executor.get_procedure(checkpoint.proc_uuid)
        if procedure is not None:
            procedure.wait()
        self.assertEqual(COUNT_1, 10)
        self.assertEqual(COUNT_2, 30)
        self.assertEqual(MyTransAction.count(), 1)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 0)
        executor.remove_procedure(proc_uuid)

        # BEGIN (FAILURE) DO FINISH
        COUNT_1 = 0
        COUNT_2 = 0
        checkpoint = _checkpoint.Checkpoint(
            proc_uuid, lockable_objects, job_uuid, job_sequence,
            do_action_fqn, args, kwargs
            )
        checkpoint.register()
        checkpoint.begin()
        self.persister.begin()
        ####### empty #######
        self.persister.rollback()

        self.assertEqual(COUNT_1, 0)
        self.assertEqual(COUNT_2, 0)
        self.assertEqual(MyTransAction.count(), 1)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 1)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 1)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 1)
        _checkpoint.Checkpoint.cleanup()
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 1)
        _recovery.recovery()
        executor = _executor.Executor()
        procedure = executor.get_procedure(checkpoint.proc_uuid)
        if procedure is not None:
            procedure.wait()
        self.assertEqual(COUNT_1, 10)
        self.assertEqual(COUNT_2, 30)
        self.assertEqual(MyTransAction.count(), 2)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 0)
        executor.remove_procedure(proc_uuid)

        # BEGIN DO (FAILURE) FINISH
        COUNT_1 = 0
        COUNT_2 = 0
        checkpoint = _checkpoint.Checkpoint(
            proc_uuid, lockable_objects, job_uuid, job_sequence,
            do_action_fqn, args, kwargs
            )
        checkpoint.register()
        checkpoint.begin()
        self.persister.begin()
        do_action(10, 30)
        checkpoint.finish()
        self.persister.rollback()

        self.assertEqual(COUNT_1, 10)
        self.assertEqual(COUNT_2, 30)
        self.assertEqual(MyTransAction.count(), 2)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 1)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 1)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 1)
        _checkpoint.Checkpoint.cleanup()
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 1)
        _recovery.recovery()
        executor = _executor.Executor()
        procedure = executor.get_procedure(checkpoint.proc_uuid)
        if procedure is not None:
            procedure.wait()
        self.assertEqual(COUNT_1, 10)
        self.assertEqual(COUNT_2, 30)
        self.assertEqual(MyTransAction.count(), 3)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 0)
        executor.remove_procedure(proc_uuid)

        # BEGIN DO FINISH (FAILURE)
        COUNT_1 = 0
        COUNT_2 = 0
        checkpoint = _checkpoint.Checkpoint(
            proc_uuid, lockable_objects, job_uuid, job_sequence,
            do_action_fqn, args, kwargs,
            )
        checkpoint.register()
        checkpoint.begin()
        self.persister.begin()
        do_action(10, 30)
        checkpoint.finish()
        self.persister.commit()

        self.assertEqual(COUNT_1, 10)
        self.assertEqual(COUNT_2, 30)
        self.assertEqual(MyTransAction.count(), 4)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 1)
        _recovery.recovery()
        executor = _executor.Executor()
        procedure = executor.get_procedure(checkpoint.proc_uuid)
        if procedure is not None:
            procedure.wait()
        self.assertEqual(COUNT_1, 10)
        self.assertEqual(COUNT_2, 30)
        self.assertEqual(MyTransAction.count(), 4)
        self.assertEqual(len(_checkpoint.Checkpoint.unfinished()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.registered()), 0)
        self.assertEqual(len(_checkpoint.Checkpoint.fetch(proc_uuid)), 0)
        executor.remove_procedure(proc_uuid)
 def tearDown(self):
     """Clean up the existing environment
     """
     _executor.Executor().shutdown()
     tests.utils.cleanup_environment()
     _executor.Executor().start()
Example #14
0
def _configure_connections(config):
    """Configure information on database connection and remote
    servers.
    """
    # Configure the number of concurrent executors.
    try:
        number_executors = config.get('executor', "executors")
        number_executors = int(number_executors)
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        number_executors = DEFAULT_N_EXECUTORS
    executor = _executor.Executor()
    executor.set_number_executors(number_executors)

    services = {}
    ssl_config = {}

    # XML-RPC service
    try:
        services['protocol.xmlrpc'] = config.get('protocol.xmlrpc', "address")

        try:
            number_threads = config.get('protocol.xmlrpc', "threads")
            number_threads = int(number_threads)
        except (_config.NoOptionError, ValueError):
            number_threads = DEFAULT_N_THREADS

        try:
            for option in ('ssl_ca', 'ssl_key', 'ssl_cert'):
                ssl_config[option] = config.get('protocol.xmlrpc', option)
        except _config.NoOptionError:
            ssl_config = {}
    except _config.NoSectionError:
        raise _errors.ConfigurationError(
            'Configuration for protocol.xmlrpc is required')

    # MySQL-RPC service
    try:
        services['protocol.mysql'] = config.get('protocol.mysql', "address")
    except _config.NoSectionError:
        # No MySQL-RPC configured
        pass

    # Define service configuration
    _services.ServiceManager(services, number_threads, ssl_config)

    # Fetch options to configure the state store.
    address = config.get('storage', 'address')

    try:
        host, port = address.split(':')
        port = int(port)
    except ValueError:
        host = address
        port = _MYSQL_PORT

    user = config.get('storage', 'user')
    database = config.get('storage', 'database')

    try:
        password = config.get('storage', 'password')
    except _config.NoOptionError:
        password = getpass.getpass()

    try:
        connection_timeout = config.get("storage", "connection_timeout")
        connection_timeout = float(connection_timeout)
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        connection_timeout = None

    try:
        connection_attempts = config.get("storage", "connection_attempts")
        connection_attempts = int(connection_attempts)
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        connection_attempts = None

    try:
        connection_delay = config.get("storage", "connection_delay")
        connection_delay = int(connection_delay)
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        connection_delay = None

    try:
        auth_plugin = config.get("storage", "auth_plugin")
    except (_config.NoOptionError, _config.NoSectionError, ValueError):
        auth_plugin = None

    # Define state store configuration.
    _persistence.init(host=host,
                      port=port,
                      user=user,
                      password=password,
                      database=database,
                      connection_timeout=connection_timeout,
                      connection_attempts=connection_attempts,
                      connection_delay=connection_delay,
                      auth_plugin=auth_plugin)
Example #15
0
 def setUp(self):
     """Configure the existing environment
     """
     tests.utils.cleanup_environment()
     self.executor = _executor.Executor()