Esempio n. 1
0
 def create_runner(self, logger=None):
     self.settings_manager = Mock()
     self.clients_manager = ClientsManager({})
     self.notifier_manager = NotifierManager(self.settings_manager, {})
     # noinspection PyTypeChecker
     self.engine_runner = DBEngineRunner(
         Logger() if logger is None else logger, self.settings_manager,
         self.trackers_manager, self.clients_manager, self.notifier_manager)
Esempio n. 2
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()
Esempio n. 3
0
 def create_runner(self, logger=None):
     self.clients_manager = ClientsManager({})
     self.engine_runner = DBEngineRunner(Logger() if logger is None else logger,
                                         self.trackers_manager,
                                         self.clients_manager)
Esempio n. 4
0
class DBEngineRunnerTest(DbTestCase, WithEngineRunnerTest):

    def setUp(self):
        super(DBEngineRunnerTest, self).setUp()
        self.create_trackers_manager()

    def create_runner(self, logger=None):
        self.clients_manager = ClientsManager({})
        self.engine_runner = DBEngineRunner(Logger() if logger is None else logger,
                                            self.trackers_manager,
                                            self.clients_manager)

    @data(10, 200, 3600, 7200)
    def test_set_interval(self, value):

        self.create_runner()
        self.assertEqual(7200, self.engine_runner.interval)

        self.engine_runner.interval = value

        self.stop_runner()

        self.create_runner()
        self.assertEqual(value, self.engine_runner.interval)

        self.stop_runner()

    class TestDatetime(datetime):
        mock_now = None

        @classmethod
        def now(cls, tz=None):
            return cls.mock_now

    def test_get_last_execute(self):
        self.TestDatetime.mock_now = datetime.now(pytz.utc)

        with patch('monitorrent.engine.datetime', self.TestDatetime(2015, 8, 28)):
            self.create_runner()

            self.assertIsNone(self.engine_runner.last_execute)

            self.engine_runner.execute(None)
            sleep(0.1)

            self.stop_runner()

            self.create_runner()
            self.assertEqual(self.TestDatetime.mock_now, self.engine_runner.last_execute)

            self.stop_runner()

    @data(10, 200, 3600, 7200)
    @patch('monitorrent.engine.timer')
    def test_interval_set_should_update_timer_and_persisted_value(self, expected_value, create_timer_mock):
        # arrange
        cancel_mock = Mock()
        create_timer_mock.return_value = cancel_mock
        self.create_runner()

        # act
        self.engine_runner.interval = expected_value
        self.stop_runner()

        # assert
        self.assertEqual(2, create_timer_mock.call_count)
        self.assertEqual(2, cancel_mock.call_count)

        with DBSession() as db:
            settings = db.query(ExecuteSettings).first()
            self.assertEqual(settings.interval, expected_value)

    def test_last_execute_set_should_update_persisted_value(self):
        # arrange
        last_execute_expected = datetime.now(pytz.utc)

        self.create_runner()
        self.assertIsNone(self.engine_runner.last_execute)

        # act
        self.engine_runner.last_execute = last_execute_expected
        self.stop_runner()

        # assert
        with DBSession() as db:
            settings = db.query(ExecuteSettings).first()
            self.assertEqual(settings.last_execute, last_execute_expected)

    def test_manual_execute_shouldnt_reset_timeout_for_whole_execute(self):
        executed = Event()

        # noinspection PyUnusedLocal
        def execute(*args, **kwargs):
            executed.set()

        execute_mock = Mock(side_effect=execute)
        self.trackers_manager.execute = execute_mock

        with DBSession() as db:
            db.add(ExecuteSettings(interval=1, last_execute=None))

        self.create_runner()

        sleep(0.5)

        # start manual
        self.engine_runner.execute([1, 2, 3])
        executed.wait(0.3)
        executed.clear()

        sleep(0.5)
        executed.wait(0.3)

        self.assertTrue(executed.is_set)
        self.stop_runner()

        self.assertEqual(2, execute_mock.call_count)
Esempio n. 5
0
class DBEngineRunnerTest(DbTestCase, WithEngineRunnerTest):
    def setUp(self):
        super(DBEngineRunnerTest, self).setUp()
        self.create_trackers_manager()

    def create_runner(self, logger=None):
        self.settings_manager = Mock()
        self.clients_manager = ClientsManager({})
        self.notifier_manager = NotifierManager(self.settings_manager, {})
        # noinspection PyTypeChecker
        self.engine_runner = DBEngineRunner(
            Logger() if logger is None else logger, self.settings_manager,
            self.trackers_manager, self.clients_manager, self.notifier_manager)

    @data(10, 200, 3600, 7200)
    def test_set_interval(self, value):

        self.create_runner()
        self.assertEqual(7200, self.engine_runner.interval)

        self.engine_runner.interval = value

        self.stop_runner()

        self.create_runner()
        self.assertEqual(value, self.engine_runner.interval)

        self.stop_runner()

    class TestDatetime(datetime):
        mock_now = None

        @classmethod
        def now(cls, tz=None):
            return cls.mock_now

    def test_get_last_execute(self):
        self.TestDatetime.mock_now = datetime.now(pytz.utc)

        with patch('monitorrent.engine.datetime',
                   self.TestDatetime(2015, 8, 28)):
            self.create_runner()

            self.assertIsNone(self.engine_runner.last_execute)

            self.engine_runner.execute(None)
            sleep(0.1)

            self.stop_runner()

            self.create_runner()
            self.assertEqual(self.TestDatetime.mock_now,
                             self.engine_runner.last_execute)

            self.stop_runner()

    @data(10, 200, 3600, 7200)
    @patch('monitorrent.engine.timer')
    def test_interval_set_should_update_timer_and_persisted_value(
            self, expected_value, create_timer_mock):
        # arrange
        cancel_mock = Mock()
        create_timer_mock.return_value = cancel_mock
        self.create_runner()

        # act
        self.engine_runner.interval = expected_value
        self.stop_runner()

        # assert
        self.assertEqual(2, create_timer_mock.call_count)
        self.assertEqual(2, cancel_mock.call_count)

        with DBSession() as db:
            settings = db.query(ExecuteSettings).first()
            self.assertEqual(settings.interval, expected_value)

    def test_last_execute_set_should_update_persisted_value(self):
        # arrange
        last_execute_expected = datetime.now(pytz.utc)

        self.create_runner()
        self.assertIsNone(self.engine_runner.last_execute)

        # act
        self.engine_runner.last_execute = last_execute_expected
        self.stop_runner()

        # assert
        with DBSession() as db:
            settings = db.query(ExecuteSettings).first()
            self.assertEqual(settings.last_execute, last_execute_expected)

    def test_manual_execute_shouldnt_reset_timeout_for_whole_execute(self):
        executed = Event()

        # noinspection PyUnusedLocal
        def execute(*args, **kwargs):
            executed.set()

        execute_mock = Mock(side_effect=execute)

        mock_tracker = Mock()
        mock_tracker.get_topics = Mock(return_value=[Topic()])
        mock_tracker.execute = execute_mock
        self.trackers_manager.trackers = {'mock.tracker': mock_tracker}

        with DBSession() as db:
            db.add(ExecuteSettings(interval=1, last_execute=None))

        self.create_runner()

        sleep(0.5)

        # start manual
        self.engine_runner.execute([1, 2, 3])
        executed.wait(0.3)
        executed.clear()

        sleep(0.5)
        executed.wait(0.3)

        self.assertTrue(executed.is_set)
        self.stop_runner()

        self.assertEqual(2, execute_mock.call_count)
Esempio n. 6
0
    def test_get_last_execute(self):
        execute_mock = Mock()
        self.trackers_manager.execute = execute_mock
        clients_manager = ClientsManager({})

        self.TestDatetime.mock_now = datetime.now(pytz.utc)

        with patch('monitorrent.engine.datetime', self.TestDatetime(2015, 8, 28)):
            engine_runner = DBEngineRunner(Logger(), self.trackers_manager, clients_manager)

            self.assertIsNone(engine_runner.last_execute)

            engine_runner.execute(None)
            sleep(0.1)

            engine_runner.stop()
            engine_runner.join(1)
            self.assertFalse(engine_runner.is_alive())
            engine_runner = DBEngineRunner(Logger(), self.trackers_manager, clients_manager)

            self.assertEqual(self.TestDatetime.mock_now, engine_runner.last_execute)

            engine_runner.stop()
            engine_runner.join(1)
            self.assertFalse(engine_runner.is_alive())
Esempio n. 7
0
    def test_set_interval(self, value):
        execute_mock = Mock()
        self.trackers_manager.execute = execute_mock
        clients_manager = ClientsManager({})
        engine_runner = DBEngineRunner(Logger(), self.trackers_manager, clients_manager)

        self.assertEqual(7200, engine_runner.interval)

        engine_runner.interval = value

        engine_runner.stop()
        engine_runner.join(1)
        self.assertFalse(engine_runner.is_alive())
        engine_runner = DBEngineRunner(Logger(), self.trackers_manager, clients_manager)

        self.assertEqual(value, engine_runner.interval)

        engine_runner.stop()
        engine_runner.join(1)
        self.assertFalse(engine_runner.is_alive())
Esempio n. 8
0
    def test_get_last_execute(self):
        execute_mock = Mock()
        self.trackers_manager.execute = execute_mock
        clients_manager = ClientsManager({})

        self.TestDatetime.mock_now = datetime.now(pytz.utc)

        with patch('monitorrent.engine.datetime',
                   self.TestDatetime(2015, 8, 28)):
            engine_runner = DBEngineRunner(Logger(), self.trackers_manager,
                                           clients_manager)

            self.assertIsNone(engine_runner.last_execute)

            engine_runner.execute(None)
            sleep(0.1)

            engine_runner.stop()
            engine_runner.join(1)
            self.assertFalse(engine_runner.is_alive())
            engine_runner = DBEngineRunner(Logger(), self.trackers_manager,
                                           clients_manager)

            self.assertEqual(self.TestDatetime.mock_now,
                             engine_runner.last_execute)

            engine_runner.stop()
            engine_runner.join(1)
            self.assertFalse(engine_runner.is_alive())
Esempio n. 9
0
    def test_set_interval(self, value):
        execute_mock = Mock()
        self.trackers_manager.execute = execute_mock
        clients_manager = ClientsManager({})
        engine_runner = DBEngineRunner(Logger(), self.trackers_manager,
                                       clients_manager)

        self.assertEqual(7200, engine_runner.interval)

        engine_runner.interval = value

        engine_runner.stop()
        engine_runner.join(1)
        self.assertFalse(engine_runner.is_alive())
        engine_runner = DBEngineRunner(Logger(), self.trackers_manager,
                                       clients_manager)

        self.assertEqual(value, engine_runner.interval)

        engine_runner.stop()
        engine_runner.join(1)
        self.assertFalse(engine_runner.is_alive())
Esempio n. 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.tracker_settings, get_plugins('tracker'))
    clients_manager = DbClientsManager(get_plugins('client'), settings_manager)
    notifier_manager = NotifierManager(get_plugins('notifier'))

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

    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)
    d = wsgiserver.WSGIPathInfoDispatcher({'/': app})
    server_start_params = (config.ip, config.port)
    server = wsgiserver.CherryPyWSGIServer(server_start_params, d)
    print('Server started on {0}:{1}'.format(*server_start_params))

    try:
        server.start()
    except KeyboardInterrupt:
        engine_runner.stop()
        server.stop()