Exemple #1
0
    def test_connect_slave_with_existing_dead_slave_creates_new_alive_instance(
            self):
        master = ClusterMaster()
        slave_registry = SlaveRegistry.singleton()

        master.connect_slave('existing-slave.turtles.gov', 10)
        existing_slave = slave_registry.get_slave(
            slave_id=None, slave_url='existing-slave.turtles.gov')
        existing_slave.set_is_alive(False)
        existing_slave_id = existing_slave.id

        connect_response = master.connect_slave('existing-slave.turtles.gov',
                                                10)
        new_slave = slave_registry.get_slave(
            slave_url='existing-slave.turtles.gov')

        self.assertNotEqual(
            str(existing_slave_id), connect_response['slave_id'],
            'The re-connected slave should have generated a new slave id.')
        self.assertTrue(
            new_slave.is_alive(use_cached=True),
            'The new slave should have been marked as alive once instantiated.'
        )
        self.assertEquals(
            2, self.mock_slave_allocator.add_idle_slave.call_count,
            'Expected slave to be added to the idle slaves list.')
Exemple #2
0
    def test_get_slave_raises_exception_on_invalid_arguments(
            self, get_slave_kwargs):
        master = ClusterMaster()
        master.connect_slave('raphael.turtles.gov', 10)

        with self.assertRaises(ValueError):
            master.get_slave(**get_slave_kwargs)
    def test_updating_slave_to_nonexistent_state_should_raise_bad_request_error(self):
        master = ClusterMaster()
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, 10)
        slave = master.get_slave(slave_url=slave_url)

        with self.assertRaises(BadRequestError):
            master.handle_slave_state_update(slave, 'NONEXISTENT_STATE')
Exemple #4
0
    def test_updating_slave_to_nonexistent_state_should_raise_bad_request_error(self):
        master = ClusterMaster()
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, 10)
        slave = master.get_slave(slave_url=slave_url)

        with self.assertRaises(BadRequestError):
            master.handle_slave_state_update(slave, 'NONEXISTENT_STATE')
    def test_connect_slave_adds_new_slave_if_slave_never_connected_before(self):
        master = ClusterMaster()

        master.connect_slave('never-before-seen.turtles.gov', 10)

        self.assertEqual(1, len(master.all_slaves_by_id()), 'Exactly one slave should be registered with the master.')
        self.assertIsNotNone(master.get_slave(slave_id=None, slave_url='never-before-seen.turtles.gov'),
                             'Registered slave does not have the expected url.')
Exemple #6
0
    def test_connect_slave_adds_new_slave_if_slave_never_connected_before(self):
        master = ClusterMaster()

        master.connect_slave('never-before-seen.turtles.gov', 10)

        self.assertEqual(1, len(master.all_slaves_by_id()), 'Exactly one slave should be registered with the master.')
        self.assertIsNotNone(master.get_slave(slave_id=None, slave_url='never-before-seen.turtles.gov'),
                             'Registered slave does not have the expected url.')
Exemple #7
0
    def test_updating_slave_to_disconnected_state_should_mark_slave_as_dead(self):
        master = ClusterMaster()
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, num_executors=10)
        slave = master.get_slave(slave_url=slave_url)
        self.assertTrue(slave.is_alive())

        master.handle_slave_state_update(slave, SlaveState.DISCONNECTED)

        self.assertFalse(slave.is_alive())
Exemple #8
0
    def test_updating_slave_to_disconnected_state_should_reset_slave_current_build_id(self):
        master = ClusterMaster()
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, num_executors=10)
        slave = master.get_slave(slave_url=slave_url)
        slave.current_build_id = 4

        master.handle_slave_state_update(slave, SlaveState.DISCONNECTED)

        self.assertIsNone(slave.current_build_id)
    def test_updating_slave_to_shutdown_should_call_slave_set_shutdown_mode(self):
        master = ClusterMaster()
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, 10)
        slave = master.get_slave(slave_url=slave_url)
        slave.set_shutdown_mode = Mock()

        master.handle_slave_state_update(slave, SlaveState.SHUTDOWN)

        slave.set_shutdown_mode.assert_called_once_with()
    def test_updating_slave_to_disconnected_state_should_reset_slave_current_build_id(self):
        master = ClusterMaster()
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, num_executors=10)
        slave = master.get_slave(slave_url=slave_url)
        slave.current_build_id = 4

        master.handle_slave_state_update(slave, SlaveState.DISCONNECTED)

        self.assertIsNone(slave.current_build_id)
    def test_updating_slave_to_disconnected_state_should_mark_slave_as_dead(self):
        master = ClusterMaster()
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, num_executors=10)
        slave = master.get_slave(slave_url=slave_url)
        self.assertTrue(slave.is_alive())

        master.handle_slave_state_update(slave, SlaveState.DISCONNECTED)

        self.assertFalse(slave.is_alive())
Exemple #12
0
    def test_updating_slave_to_shutdown_should_call_slave_set_shutdown_mode(self):
        master = ClusterMaster()
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, 10)
        slave = master.get_slave(slave_url=slave_url)
        slave.set_shutdown_mode = Mock()

        master.handle_slave_state_update(slave, SlaveState.SHUTDOWN)

        slave.set_shutdown_mode.assert_called_once_with()
    def test_updating_slave_to_setup_completed_state_should_tell_build_to_begin_subjob_execution(self):
        master = ClusterMaster()
        fake_build = MagicMock()
        master.get_build = MagicMock(return_value=fake_build)
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, 10)
        slave = master.get_slave(slave_url=slave_url)

        master.handle_slave_state_update(slave, SlaveState.SETUP_COMPLETED)

        fake_build.begin_subjob_executions_on_slave.assert_called_once_with(slave)
    def test_connect_slave_with_existing_slave_running_build_cancels_build(self):
        master = ClusterMaster()
        master.connect_slave('running-slave.turtles.gov', 10)
        build_mock = MagicMock(spec_set=Build)
        master._all_builds_by_id[1] = build_mock
        existing_slave = master.get_slave(slave_id=None, slave_url='running-slave.turtles.gov')
        existing_slave.current_build_id = 1

        master.connect_slave('running-slave.turtles.gov', 10)

        self.assertTrue(build_mock.cancel.called, 'The build was not cancelled.')
Exemple #15
0
    def test_connect_slave_with_existing_slave_running_build_cancels_build(self):
        master = ClusterMaster()
        master.connect_slave('running-slave.turtles.gov', 10)
        build_mock = MagicMock(spec_set=Build)
        master._all_builds_by_id[1] = build_mock
        existing_slave = master.get_slave(slave_id=None, slave_url='running-slave.turtles.gov')
        existing_slave.current_build_id = 1

        master.connect_slave('running-slave.turtles.gov', 10)

        self.assertTrue(build_mock.cancel.called, 'The build was not cancelled.')
Exemple #16
0
    def test_updating_slave_to_setup_completed_state_should_tell_build_to_begin_subjob_execution(self):
        master = ClusterMaster()
        fake_build = MagicMock(spec_set=Build)
        master.get_build = MagicMock(return_value=fake_build)
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, 10)
        slave = master.get_slave(slave_url=slave_url)
        mock_scheduler = self.mock_scheduler_pool.get(fake_build)

        master.handle_slave_state_update(slave, SlaveState.SETUP_COMPLETED)

        mock_scheduler.begin_subjob_executions_on_slave.assert_called_once_with(slave)
    def test_connect_slave_with_existing_dead_slave_removes_old_slave_entry_from_registry(self):
        master = ClusterMaster()
        slave_registry = SlaveRegistry.singleton()

        master.connect_slave('existing-slave.turtles.gov', 10)
        old_existing_slave = slave_registry.get_slave(slave_id=None, slave_url='existing-slave.turtles.gov')
        old_existing_slave_id = old_existing_slave.id

        connect_response = master.connect_slave('existing-slave.turtles.gov', 10)

        with self.assertRaises(ItemNotFoundError):
            slave_registry.get_slave(slave_id=old_existing_slave_id)
    def test_connect_slave_with_existing_dead_slave_marks_it_as_alive(self):
        master = ClusterMaster()
        master.connect_slave('existing-slave.turtles.gov', 10)
        existing_slave = master.get_slave(slave_id=None, slave_url='existing-slave.turtles.gov')
        existing_slave.set_is_alive(False)
        existing_slave_id = existing_slave.id

        connect_response = master.connect_slave('existing-slave.turtles.gov', 10)

        self.assertEqual(str(existing_slave_id), connect_response['slave_id'],
                         'The re-connected slave should not have generated a new slave id.')
        self.assertTrue(existing_slave.is_alive(use_cached=True),
                        'The re-connected slave should have been marked as alive once reconnected.')
        self.assertEquals(2, self.mock_slave_allocator.add_idle_slave.call_count,
                        'Expected slave to be added to the idle slaves list.')
    def test_connect_slave_with_existing_slave_running_build_gets_added_to_idle_slaves_list_and_cancels_build(self):
        master = ClusterMaster()
        master.connect_slave('running-slave.turtles.gov', 10)
        build_mock = MagicMock(spec_set=Build)
        master._all_builds_by_id[1] = build_mock
        existing_slave = master.get_slave(slave_id=None, slave_url='running-slave.turtles.gov')
        existing_slave.current_build_id = 1
        existing_slave_id = existing_slave.id

        connect_response = master.connect_slave('running-slave.turtles.gov', 10)

        self.assertEqual(str(existing_slave_id), connect_response['slave_id'],
                         'The re-connected slave should not have generated a new slave id.')
        self.assertEqual(2, self.mock_slave_allocator.add_idle_slave.call_count,
                         'Expected slave to be added to the idle slaves list.')
        self.assertTrue(build_mock.cancel.called, 'The build was not cancelled.')
    def test_heartbeat_disconnects_unresponsive_slave(self, slave_alive, seconds_since_last_heartbeat):
        last_heartbeat_time = self._mock_current_datetime - timedelta(seconds=seconds_since_last_heartbeat)
        master = ClusterMaster()

        mock_slave = Mock()
        self.patch('app.master.cluster_master.Slave', new=lambda *args: mock_slave)
        master.connect_slave('slave_url', 1)

        mock_slave.is_alive.return_value = slave_alive
        mock_slave.get_last_heartbeat_time.return_value = last_heartbeat_time

        master._disconnect_non_heartbeating_slaves()
        if slave_alive and seconds_since_last_heartbeat == 1000:
            self.assertEqual(mock_slave.mark_dead.call_count, 1, 'master disconnects unresponsive slave')
        else:
            self.assertEqual(mock_slave.mark_dead.call_count, 0,
                             'master should not disconnect a dead or responsive slave')
    def test_updating_slave_to_setup_completed_state_should_tell_build_to_begin_subjob_execution(self):
        master = ClusterMaster()
        slave_registry = SlaveRegistry.singleton()
        fake_build = MagicMock(spec_set=Build)
        master.get_build = MagicMock(return_value=fake_build)
        slave_url = 'raphael.turtles.gov'
        master.connect_slave(slave_url, 10)
        slave = slave_registry.get_slave(slave_url=slave_url)
        mock_scheduler = self.mock_scheduler_pool.get(fake_build)
        scheduler_begin_event = Event()
        mock_scheduler.begin_subjob_executions_on_slave.side_effect = lambda **_: scheduler_begin_event.set()

        master.handle_slave_state_update(slave, SlaveState.SETUP_COMPLETED)

        was_called = scheduler_begin_event.wait(timeout=5)
        self.assertTrue(was_called, 'scheduler.begin_subjob_executions_on_slave should be called in response '
                                    'to slave setup completing.')
        _, call_kwargs = mock_scheduler.begin_subjob_executions_on_slave.call_args
        self.assertEqual(call_kwargs.get('slave'), slave)
Exemple #22
0
    def test_get_slave_raises_exception_on_slave_not_found(self, get_slave_kwargs):
        master = ClusterMaster()
        master.connect_slave('raphael.turtles.gov', 10)
        master.connect_slave('leonardo.turtles.gov', 10)
        master.connect_slave('donatello.turtles.gov', 10)

        with self.assertRaises(ItemNotFoundError):
            master.get_slave(**get_slave_kwargs)
    def test_get_slave_raises_exception_on_slave_not_found(self, get_slave_kwargs):
        master = ClusterMaster()
        master.connect_slave('raphael.turtles.gov', 10)
        master.connect_slave('leonardo.turtles.gov', 10)
        master.connect_slave('donatello.turtles.gov', 10)

        with self.assertRaises(ItemNotFoundError):
            master.get_slave(**get_slave_kwargs)
    def test_connect_slave_with_existing_dead_slave_creates_new_alive_instance(self):
        master = ClusterMaster()
        master.connect_slave("existing-slave.turtles.gov", 10)
        existing_slave = master.get_slave(slave_id=None, slave_url="existing-slave.turtles.gov")
        existing_slave.set_is_alive(False)
        existing_slave_id = existing_slave.id

        connect_response = master.connect_slave("existing-slave.turtles.gov", 10)
        new_slave = master._all_slaves_by_url.get("existing-slave.turtles.gov")

        self.assertNotEqual(
            str(existing_slave_id),
            connect_response["slave_id"],
            "The re-connected slave should have generated a new slave id.",
        )
        self.assertTrue(
            new_slave.is_alive(use_cached=True), "The new slave should have been marked as alive once instantiated."
        )
        self.assertEquals(
            2,
            self.mock_slave_allocator.add_idle_slave.call_count,
            "Expected slave to be added to the idle slaves list.",
        )
    def test_get_slave_returns_expected_value_given_valid_arguments(self):
        master = ClusterMaster()
        master.connect_slave('raphael.turtles.gov', 10)
        master.connect_slave('leonardo.turtles.gov', 10)
        master.connect_slave('donatello.turtles.gov', 10)

        actual_slave_by_id = master.get_slave(slave_id=2)
        actual_slave_by_url = master.get_slave(slave_url='leonardo.turtles.gov')

        self.assertEqual(2, actual_slave_by_id.id, 'Retrieved slave should have the same id as requested.')
        self.assertEqual('leonardo.turtles.gov', actual_slave_by_url.url,
                         'Retrieved slave should have the same url as requested.')
Exemple #26
0
    def test_get_slave_returns_expected_value_given_valid_arguments(self):
        master = ClusterMaster()
        master.connect_slave('raphael.turtles.gov', 10)
        master.connect_slave('leonardo.turtles.gov', 10)
        master.connect_slave('donatello.turtles.gov', 10)

        actual_slave_by_id = master.get_slave(slave_id=2)
        actual_slave_by_url = master.get_slave(slave_url='leonardo.turtles.gov')

        self.assertEqual(2, actual_slave_by_id.id, 'Retrieved slave should have the same id as requested.')
        self.assertEqual('leonardo.turtles.gov', actual_slave_by_url.url,
                         'Retrieved slave should have the same url as requested.')
    def test_get_slave_raises_exception_on_invalid_arguments(self, get_slave_kwargs):
        master = ClusterMaster()
        master.connect_slave('raphael.turtles.gov', 10)

        with self.assertRaises(ValueError):
            master.get_slave(**get_slave_kwargs)