Beispiel #1
0
 def test_executor_exit_env_variable(self, mock_exit):
     os.environ['EXECUTOR_TEST_EXIT'] = '5'
     try:
         config = cc.ExecutorConfig()
         stop_signal = Event()
         executor = ce.CookExecutor(stop_signal, config)
         driver = tu.FakeMesosExecutorDriver()
         executor_info = {'executor_id': {'value': 'test'}}
         framework_info = {'id': 'framework'}
         agent_info = {'id': {'value': 'agent'}}
         executor.registered(driver, executor_info, framework_info,
                             agent_info)
         mock_exit.assert_called_with(5)
     finally:
         del os.environ['EXECUTOR_TEST_EXIT']
Beispiel #2
0
    def test_executor_launch_task_and_disconnect(self):

        task_id = tu.get_random_task_id()
        stdout_name = tu.ensure_directory('build/stdout.{}'.format(task_id))
        stderr_name = tu.ensure_directory('build/stderr.{}'.format(task_id))
        output_name = tu.ensure_directory('build/output.' + str(task_id))

        tu.redirect_stdout_to_file(stdout_name)
        tu.redirect_stderr_to_file(stderr_name)

        try:
            config = cc.ExecutorConfig()
            stop_signal = Event()
            executor = ce.CookExecutor(stop_signal, config)

            driver = tu.FakeMesosExecutorDriver()
            command = 'echo "Start" >> {}; sleep 100; echo "Done." >> {}; '.format(
                output_name, output_name)
            task = {
                'task_id': {
                    'value': task_id
                },
                'data':
                pm.encode_data(
                    json.dumps({
                        'command': command
                    }).encode('utf8'))
            }

            executor.launchTask(driver, task)

            # let the process run for up to 10 seconds
            for _ in range(1000):
                time.sleep(0.01)
                if os.path.isfile(output_name):
                    with open(output_name) as f:
                        content = f.read()
                        if 'Start' in content:
                            break

            executor.disconnected(driver)
            self.assertTrue(executor.disconnect_signal.isSet())
            self.assertTrue(executor.stop_signal.isSet())

            executor.await_completion()
            logging.info('Task completed')

            if os.path.isfile(output_name):
                with open(output_name) as f:
                    file_contents = f.read()
                    self.assertTrue('Start' in file_contents)
                    self.assertTrue('Done' not in file_contents)
            else:
                self.fail('{} does not exist.'.format(stderr_name))

            expected_statuses = [{
                'task_id': {
                    'value': task_id
                },
                'state': cook.TASK_STARTING
            }, {
                'task_id': {
                    'value': task_id
                },
                'state': cook.TASK_RUNNING
            }, {
                'task_id': {
                    'value': task_id
                },
                'state': cook.TASK_KILLED
            }]
            tu.assert_statuses(self, expected_statuses, driver.statuses)

            expected_message_0 = {
                'sandbox-directory': '',
                'task-id': task_id,
                'type': 'directory'
            }
            expected_message_1 = {'exit-code': -15, 'task-id': task_id}
            tu.assert_messages(self, [expected_message_0, expected_message_1],
                               [], driver.messages)
        finally:
            tu.cleanup_output(stdout_name, stderr_name)
            tu.cleanup_file(output_name)
Beispiel #3
0
def main(args=None):
    from _version import __version__

    if len(sys.argv) == 2 and sys.argv[1] == "--version":
        print(__version__)
        sys.exit(0)

    cio.print_out('Cook Executor version {}'.format(__version__), flush=True)

    environment = os.environ
    executor_id = environment.get('MESOS_EXECUTOR_ID', '1')
    log_level = environment.get('EXECUTOR_LOG_LEVEL', 'INFO')

    logging.basicConfig(level=log_level,
                        filename='executor.log',
                        format='%(asctime)s %(levelname)s %(message)s')
    logging.info('Starting Cook Executor {} for executor-id={}'.format(
        __version__, executor_id))
    logging.info('Log level is {}'.format(log_level))

    config = cc.initialize_config(environment)

    def print_memory_usage_task():
        cu.print_memory_usage()
        timer = Timer(config.memory_usage_interval_secs,
                      print_memory_usage_task)
        timer.daemon = True
        timer.start()

    print_memory_usage_task()

    stop_signal = Event()
    non_zero_exit_signal = Event()

    def handle_interrupt(interrupt_code, _):
        logging.info(
            'Executor interrupted with code {}'.format(interrupt_code))
        cio.print_and_log(
            'Received kill for task {} with grace period of {}'.format(
                executor_id, config.shutdown_grace_period))
        stop_signal.set()
        non_zero_exit_signal.set()
        cu.print_memory_usage()

    signal.signal(signal.SIGINT, handle_interrupt)
    signal.signal(signal.SIGTERM, handle_interrupt)

    try:
        executor = ce.CookExecutor(stop_signal, config)
        driver = pm.MesosExecutorDriver(executor)

        logging.info('MesosExecutorDriver is starting...')
        driver.start()

        executor.await_completion()

        logging.info('MesosExecutorDriver requested to stop')
        driver.stop()
        logging.info('MesosExecutorDriver has been stopped')

        executor.await_disconnect()
    except Exception:
        logging.exception('Error in __main__')
        stop_signal.set()
        non_zero_exit_signal.set()

    cu.print_memory_usage()
    exit_code = 1 if non_zero_exit_signal.isSet() else 0
    logging.info('Executor exiting with code {}'.format(exit_code))
    sys.exit(exit_code)