Example #1
0
    def test_engine_entry_failed(self):
        inner_logger = MagicMock()

        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(inner_logger, ExecuteLogManager())

        finish_time = datetime.now(pytz.utc)
        exception = Exception('Some failed exception')

        db_logger.started(finish_time)
        db_logger.finished(finish_time, exception)

        with DBSession() as db:
            execute = db.query(Execute).first()
            db.expunge(execute)

        self.assertEqual(execute.finish_time, finish_time)
        self.assertEqual(execute.status, 'failed')
        self.assertEqual(execute.failed_message, str(exception))

        inner_logger.started.assert_called_once_with(finish_time)
        inner_logger.finished.assert_called_once_with(finish_time, exception)
        inner_logger.info.assert_not_called()
        inner_logger.failed.assert_not_called()
        inner_logger.downloaded.assert_not_called()
Example #2
0
    def test_remove_old_entries(self):
        inner_logger = Mock()
        settings_manager_mock = Mock()
        settings_manager_mock.remove_logs_interval = 10

        log_manager = ExecuteLogManager()
        log_manager.remove_old_entries = Mock()
        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(inner_logger, log_manager,
                                    settings_manager_mock)

        finish_time_1 = datetime.now(pytz.utc)

        db_logger.started(finish_time_1)
        db_logger.info(u"Message 1")
        db_logger.finished(finish_time_1, None)

        inner_logger.started.assert_called_once_with(finish_time_1)
        inner_logger.finished.assert_called_once_with(finish_time_1, None)
        inner_logger.info.assert_called_once_with("Message 1")
        inner_logger.downloaded.assert_not_called()
        inner_logger.failed.assert_not_called()

        # noinspection PyUnresolvedReferences
        log_manager.remove_old_entries.assert_called_once_with(10)
Example #3
0
    def test_engine_entry_log_failed_with_exception(self):
        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(ExecuteLogManager())

        finish_time = datetime.now(pytz.utc)
        exception_message = u'Something Not Specified'
        failed_message = u'Execute Failed'

        db_logger.started(finish_time)
        try:
            raise Exception(exception_message)
        except:
            db_logger.failed(failed_message, *sys.exc_info())
        db_logger.finished(finish_time, None)

        with DBSession() as db:
            execute = db.query(Execute).first()
            db.expunge(execute)

        assert execute.finish_time == finish_time
        assert execute.status == 'finished'
        assert execute.failed_message is None

        with DBSession() as db:
            entries = db.query(ExecuteLog).all()
            db.expunge_all()

        assert len(entries) == 1
        assert exception_message in entries[0].message
        assert failed_message in entries[0].message
        assert 'failed' == entries[0].level
Example #4
0
    def test_engine_entry_log_downloaded(self):
        inner_logger = MagicMock()

        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(inner_logger, ExecuteLogManager())

        finish_time = datetime.now(pytz.utc)
        message1 = u'Downloaded 1'
        message2 = u'Downloaded 2'

        db_logger.started(finish_time)
        downloaded_time = datetime.now(pytz.utc)
        db_logger.downloaded(message1, None)
        db_logger.downloaded(message2, None)
        db_logger.finished(finish_time, None)

        with DBSession() as db:
            execute = db.query(Execute).first()
            db.expunge(execute)

        self.assertEqual(execute.finish_time, finish_time)
        self.assertEqual(execute.status, 'finished')
        self.assertIsNone(execute.failed_message)

        inner_logger.started.assert_called_once_with(finish_time)
        inner_logger.finished.assert_called_once_with(finish_time, None)
        inner_logger.info.assert_not_called()
        inner_logger.failed.assert_not_called()
        inner_logger.downloaded.assert_has_calls(
            [call(message1, None), call(message2, None)])

        with DBSession() as db:
            entries = db.query(ExecuteLog).all()
            db.expunge_all()

        self.assertEqual(len(entries), 2)

        self.assertEqual(entries[0].message, message1)
        self.assertEqual(entries[1].message, message2)

        # 1 seconds is enought precision for call and log results
        self.assertAlmostEqual(entries[0].time,
                               downloaded_time,
                               delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[1].time,
                               downloaded_time,
                               delta=timedelta(seconds=1))

        self.assertEqual(entries[0].level, 'downloaded')
        self.assertEqual(entries[1].level, 'downloaded')

        self.assertEqual(entries[0].execute_id, execute.id)
        self.assertEqual(entries[1].execute_id, execute.id)
Example #5
0
    def test_engine_entry_failed(self):
        inner_logger = MagicMock()

        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(inner_logger, ExecuteLogManager())

        finish_time = datetime.now(pytz.utc)
        exception = Exception('Some failed exception')

        db_logger.started(finish_time)
        db_logger.finished(finish_time, exception)

        with DBSession() as db:
            execute = db.query(Execute).first()
            db.expunge(execute)

        self.assertEqual(execute.finish_time, finish_time)
        self.assertEqual(execute.status, 'failed')
        self.assertEqual(execute.failed_message, str(exception))

        inner_logger.started.assert_called_once_with(finish_time)
        inner_logger.finished.assert_called_once_with(finish_time, exception)
        inner_logger.info.assert_not_called()
        inner_logger.failed.assert_not_called()
        inner_logger.downloaded.assert_not_called()
Example #6
0
    def test_engine_entry_log_infos(self):
        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(ExecuteLogManager())

        finish_time = datetime.now(pytz.utc)
        message1 = u'Message 1'
        message2 = u'Message 2'

        db_logger.started(finish_time)
        downloaded_time = datetime.now(pytz.utc)
        db_logger.info(message1)
        db_logger.info(message2)
        db_logger.finished(finish_time, None)

        with DBSession() as db:
            execute = db.query(Execute).first()
            db.expunge(execute)

        self.assertEqual(execute.finish_time, finish_time)
        self.assertEqual(execute.status, 'finished')
        self.assertIsNone(execute.failed_message)

        with DBSession() as db:
            entries = db.query(ExecuteLog).all()
            db.expunge_all()

        self.assertEqual(len(entries), 2)

        self.assertEqual(entries[0].message, message1)
        self.assertEqual(entries[1].message, message2)

        # 1 seconds is enought precision for call and log results
        self.assertAlmostEqual(entries[0].time,
                               downloaded_time,
                               delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[1].time,
                               downloaded_time,
                               delta=timedelta(seconds=1))

        self.assertEqual(entries[0].level, 'info')
        self.assertEqual(entries[1].level, 'info')

        self.assertEqual(entries[0].execute_id, execute.id)
        self.assertEqual(entries[1].execute_id, execute.id)
Example #7
0
    def test_engine_entry_log_downloaded(self):
        inner_logger = MagicMock()

        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(inner_logger, ExecuteLogManager())

        finish_time = datetime.now(pytz.utc)
        message1 = u'Downloaded 1'
        message2 = u'Downloaded 2'

        db_logger.started(finish_time)
        downloaded_time = datetime.now(pytz.utc)
        db_logger.downloaded(message1, None)
        db_logger.downloaded(message2, None)
        db_logger.finished(finish_time, None)

        with DBSession() as db:
            execute = db.query(Execute).first()
            db.expunge(execute)

        self.assertEqual(execute.finish_time, finish_time)
        self.assertEqual(execute.status, 'finished')
        self.assertIsNone(execute.failed_message)

        inner_logger.started.assert_called_once_with(finish_time)
        inner_logger.finished.assert_called_once_with(finish_time, None)
        inner_logger.info.assert_not_called()
        inner_logger.failed.assert_not_called()
        inner_logger.downloaded.assert_has_calls([call(message1, None), call(message2, None)])

        with DBSession() as db:
            entries = db.query(ExecuteLog).all()
            db.expunge_all()

        self.assertEqual(len(entries), 2)

        self.assertEqual(entries[0].message, message1)
        self.assertEqual(entries[1].message, message2)

        # 1 seconds is enought precision for call and log results
        self.assertAlmostEqual(entries[0].time, downloaded_time, delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[1].time, downloaded_time, delta=timedelta(seconds=1))

        self.assertEqual(entries[0].level, 'downloaded')
        self.assertEqual(entries[1].level, 'downloaded')

        self.assertEqual(entries[0].execute_id, execute.id)
        self.assertEqual(entries[1].execute_id, execute.id)
Example #8
0
    def test_engine_entry_finished(self):
        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(ExecuteLogManager())

        finish_time = datetime.now(pytz.utc)

        db_logger.started(finish_time)
        db_logger.finished(finish_time, None)

        with DBSession() as db:
            execute = db.query(Execute).first()
            db.expunge(execute)

        self.assertEqual(execute.finish_time, finish_time)
        self.assertEqual(execute.status, 'finished')
        self.assertIsNone(execute.failed_message)
Example #9
0
    def test_remove_old_entries(self):
        inner_logger = Mock()
        settings_manager_mock = Mock()
        settings_manager_mock.remove_logs_interval = 10

        log_manager = ExecuteLogManager()
        log_manager.remove_old_entries = Mock()
        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(inner_logger, log_manager, settings_manager_mock)

        finish_time_1 = datetime.now(pytz.utc)

        db_logger.started(finish_time_1)
        db_logger.info(u"Message 1")
        db_logger.finished(finish_time_1, None)

        inner_logger.started.assert_called_once_with(finish_time_1)
        inner_logger.finished.assert_called_once_with(finish_time_1, None)
        inner_logger.info.assert_called_once_with("Message 1")
        inner_logger.downloaded.assert_not_called()
        inner_logger.failed.assert_not_called()

        # noinspection PyUnresolvedReferences
        log_manager.remove_old_entries.assert_called_once_with(10)
Example #10
0
def main():
    def try_int(s, base=10, val=None):
        if s is None:
            return None
        try:
            return int(s, base)
        except ValueError:
            return val

    class Config(object):
        debug = False
        ip = '0.0.0.0'
        port = 6687
        db_path = 'monitorrent.db'
        config = 'config.py'

        def __init__(self, parsed_args):
            if parsed_args.config is not None and not os.path.isfile(parsed_args.config):
                warnings.warn('File not found: {}'.format(parsed_args.config))
            config_path = parsed_args.config or self.config
            if os.path.isfile(config_path):
                # noinspection PyBroadException
                try:
                    parsed_config = {}
                    with open(config_path) as config_file:
                        six.exec_(compile(config_file.read(), config_path, 'exec'), {}, parsed_config)
                    self.debug = parsed_config.get('debug', self.debug)
                    self.ip = parsed_config.get('ip', self.ip)
                    self.port = parsed_config.get('port', self.port)
                    self.db_path = parsed_config.get('db_path', self.db_path)
                except:
                    ex, val, tb = sys.exc_info()
                    warnings.warn('Error reading: {0}: {1} ({2}'.format(parsed_args.config, ex, val))

            env_debug = (os.environ.get('MONITORRENT_DEBUG', None) in ['true', 'True', '1'])

            self.debug = parsed_args.debug or env_debug or self.debug
            self.ip = parsed_args.ip or os.environ.get('MONITORRENT_IP', None) or self.ip
            self.port = parsed_args.port or try_int(os.environ.get('MONITORRENT_PORT', None)) or self.port
            self.db_path = parsed_args.db_path or os.environ.get('MONITORRENT_DB_PATH', None) or self.db_path

    parser = argparse.ArgumentParser(description='Monitorrent server')
    parser.add_argument('--debug', action='store_true',
                        help='Run in debug mode. Secret key is always the same.')
    parser.add_argument('--ip', type=str, dest='ip',
                        help='Bind interface. Default is {0}'.format(Config.ip))
    parser.add_argument('--port', type=int, dest='port',
                        help='Port for server. Default is {0}'.format(Config.port))
    parser.add_argument('--db-path', type=str, dest='db_path',
                        help='Path to SQL lite database. Default is to {0}'.format(Config.db_path))
    parser.add_argument('--config', type=str, dest='config',
                        default=os.environ.get('MONITORRENT_CONFIG', None),
                        help='Path to config file (default {0})'.format(Config.config))

    parsed_args = parser.parse_args()
    config = Config(parsed_args)

    db_connection_string = "sqlite:///" + config.db_path

    init_db_engine(db_connection_string, False)
    load_plugins()
    upgrade()
    create_db()

    settings_manager = SettingsManager()
    tracker_manager = TrackersManager(settings_manager, get_plugins('tracker'))
    clients_manager = DbClientsManager(settings_manager, get_plugins('client'))
    notifier_manager = NotifierManager(settings_manager, get_plugins('notifier'))

    log_manager = ExecuteLogManager()
    engine_runner_logger = DbLoggerWrapper(log_manager, settings_manager)
    engine_runner = DBEngineRunner(engine_runner_logger, settings_manager, tracker_manager,
                                   clients_manager, notifier_manager)

    include_prerelease = settings_manager.get_new_version_check_include_prerelease()
    new_version_checker = NewVersionChecker(notifier_manager, include_prerelease)
    if settings_manager.get_is_new_version_checker_enabled():
        # noinspection PyBroadException
        try:
            new_version_checker.execute()
        except:
            pass
        new_version_checker.start(settings_manager.new_version_check_interval)

    debug = config.debug

    if debug:
        secret_key = 'Secret!'
        token = 'monitorrent'
    else:
        secret_key = os.urandom(24)
        token = ''.join(random.choice(string.ascii_letters) for _ in range(8))

    app = create_app(secret_key, token, tracker_manager, clients_manager, notifier_manager, settings_manager,
                     engine_runner, log_manager, new_version_checker)
    server_start_params = (config.ip, config.port)
    server = wsgi.Server(server_start_params, app)
    print('Server started on {0}:{1}'.format(*server_start_params))

    try:
        server.start()
    except KeyboardInterrupt:
        engine_runner.stop()
        server.stop()
Example #11
0
    def test_engine_entry_log_multiple_executes(self):
        inner_logger = MagicMock()

        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(inner_logger, ExecuteLogManager())

        finish_time_1 = datetime.now(pytz.utc)
        finish_time_2 = finish_time_1 + timedelta(seconds=10)
        message1 = u'Inf 1'
        message2 = u'Downloaded 1'
        message3 = u'Failed 1'
        message4 = u'Failed 2'

        exception = Exception('Some exception message')

        db_logger.started(finish_time_1)
        entry_time_1 = datetime.now(pytz.utc)
        db_logger.info(message1)
        db_logger.downloaded(message2, None)
        db_logger.failed(message3)
        db_logger.finished(finish_time_1, None)

        db_logger.started(finish_time_2)
        entry_time_2 = datetime.now(pytz.utc)
        db_logger.failed(message4)
        db_logger.finished(finish_time_2, exception)

        with DBSession() as db:
            executes = db.query(Execute).all()
            execute1 = executes[0]
            execute2 = executes[1]
            db.expunge_all()

        self.assertEqual(execute1.finish_time, finish_time_1)
        self.assertEqual(execute1.status, 'finished')
        self.assertIsNone(execute1.failed_message)

        self.assertEqual(execute2.finish_time, finish_time_2)
        self.assertEqual(execute2.status, 'failed')
        self.assertEqual(execute2.failed_message, str(exception))

        inner_logger.started.assert_has_calls([call(finish_time_1), call(finish_time_2)])
        inner_logger.finished.assert_has_calls([call(finish_time_1, None), call(finish_time_2, exception)])
        inner_logger.info.assert_called_once_with(message1)
        inner_logger.downloaded.assert_called_once_with(message2, None)
        inner_logger.failed.assert_has_calls([call(message3), call(message4)])

        with DBSession() as db:
            entries = db.query(ExecuteLog).all()
            db.expunge_all()

        self.assertEqual(len(entries), 4)

        self.assertEqual(entries[0].message, message1)
        self.assertEqual(entries[1].message, message2)
        self.assertEqual(entries[2].message, message3)
        self.assertEqual(entries[3].message, message4)

        # 1 seconds is enought precision for call and log results
        self.assertAlmostEqual(entries[0].time, entry_time_1, delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[1].time, entry_time_1, delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[2].time, entry_time_1, delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[3].time, entry_time_2, delta=timedelta(seconds=1))

        self.assertEqual(entries[0].level, 'info')
        self.assertEqual(entries[1].level, 'downloaded')
        self.assertEqual(entries[2].level, 'failed')
        self.assertEqual(entries[3].level, 'failed')

        self.assertEqual(entries[0].execute_id, execute1.id)
        self.assertEqual(entries[1].execute_id, execute1.id)
        self.assertEqual(entries[2].execute_id, execute1.id)
        self.assertEqual(entries[3].execute_id, execute2.id)
Example #12
0
    def test_engine_entry_log_multiple_executes(self):
        # noinspection PyTypeChecker
        db_logger = DbLoggerWrapper(ExecuteLogManager())

        finish_time_1 = datetime.now(pytz.utc)
        finish_time_2 = finish_time_1 + timedelta(seconds=10)
        message1 = u'Inf 1'
        message2 = u'Downloaded 1'
        message3 = u'Failed 1'
        message4 = u'Failed 2'

        exception = Exception('Some exception message')

        db_logger.started(finish_time_1)
        entry_time_1 = datetime.now(pytz.utc)
        db_logger.info(message1)
        db_logger.downloaded(message2, None)
        db_logger.failed(message3)
        db_logger.finished(finish_time_1, None)

        db_logger.started(finish_time_2)
        entry_time_2 = datetime.now(pytz.utc)
        db_logger.failed(message4)
        db_logger.finished(finish_time_2, exception)

        with DBSession() as db:
            executes = db.query(Execute).all()
            execute1 = executes[0]
            execute2 = executes[1]
            db.expunge_all()

        self.assertEqual(execute1.finish_time, finish_time_1)
        self.assertEqual(execute1.status, 'finished')
        self.assertIsNone(execute1.failed_message)

        self.assertEqual(execute2.finish_time, finish_time_2)
        self.assertEqual(execute2.status, 'failed')
        self.assertEqual(execute2.failed_message, str(exception))

        with DBSession() as db:
            entries = db.query(ExecuteLog).all()
            db.expunge_all()

        self.assertEqual(len(entries), 4)

        self.assertEqual(entries[0].message, message1)
        self.assertEqual(entries[1].message, message2)
        self.assertEqual(entries[2].message, message3)
        self.assertEqual(entries[3].message, message4)

        # 1 seconds is enought precision for call and log results
        self.assertAlmostEqual(entries[0].time,
                               entry_time_1,
                               delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[1].time,
                               entry_time_1,
                               delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[2].time,
                               entry_time_1,
                               delta=timedelta(seconds=1))
        self.assertAlmostEqual(entries[3].time,
                               entry_time_2,
                               delta=timedelta(seconds=1))

        self.assertEqual(entries[0].level, 'info')
        self.assertEqual(entries[1].level, 'downloaded')
        self.assertEqual(entries[2].level, 'failed')
        self.assertEqual(entries[3].level, 'failed')

        self.assertEqual(entries[0].execute_id, execute1.id)
        self.assertEqual(entries[1].execute_id, execute1.id)
        self.assertEqual(entries[2].execute_id, execute1.id)
        self.assertEqual(entries[3].execute_id, execute2.id)