def main(args=None): print('Starting cook executor...') 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 {}'.format(executor_id)) logging.info('Log level is {}'.format(log_level)) config = cc.initialize_config(environment) def handle_interrupt(interrupt_code, _): logging.info( 'Received interrupt code {}, preparing to terminate executor'. format(interrupt_code)) stop_signal.set() signal.signal(signal.SIGINT, handle_interrupt) signal.signal(signal.SIGTERM, handle_interrupt) stop_signal = Event() driver_thread = Thread(target=ce.run_mesos_driver, args=(stop_signal, config)) driver_thread.start() logging.info('Driver thread has started') driver_thread.join() logging.info('Driver thread has completed') exit_code = 1 if stop_signal.isSet() else 0 logging.info('Executor exiting with code {}'.format(exit_code)) sys.exit(exit_code)
def test_initialize_config_custom(self): environment = {'EXECUTOR_MAX_BYTES_READ_PER_LINE': '1234', 'EXECUTOR_MAX_MESSAGE_LENGTH': '1024', 'EXECUTOR_MEMORY_USAGE_INTERVAL_SECS': '120', 'EXECUTOR_PROGRESS_OUTPUT_FILE': 'progress_file', 'EXECUTOR_RESET_VARS': 'VAR_A,VAR_B', 'MESOS_CHECKPOINT': '1', 'MESOS_DIRECTORY': '/mesos/directory', 'MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD': '4secs', 'MESOS_RECOVERY_TIMEOUT': '5mins', 'MESOS_SANDBOX': '/sandbox/location', 'PROGRESS_REGEX_STRING': 'progress/regex', 'PROGRESS_SAMPLE_INTERVAL_MS': '2500'} config = cc.initialize_config(environment) self.assertEqual(True, config.checkpoint) self.assertEqual(1234, config.max_bytes_read_per_line) self.assertEqual(1024, config.max_message_length) self.assertEqual(120, config.memory_usage_interval_secs) self.assertEqual('/mesos/directory', config.mesos_directory) self.assertEqual('EXECUTOR_PROGRESS_OUTPUT_FILE', config.progress_output_env_variable) self.assertEqual('progress_file', config.progress_output_name) self.assertEqual('progress/regex', config.progress_regex_string) self.assertEqual(5 * 60 * 1000, config.recovery_timeout_ms) self.assertEqual(2500, config.progress_sample_interval_ms) self.assertEqual(['VAR_A', 'VAR_B'], config.reset_vars) self.assertEqual('/sandbox/location', config.sandbox_directory) self.assertEqual(4000, config.shutdown_grace_period_ms)
def test_initialize_config_configured_progress_file_name_is_dev_null(self): environment = { 'EXECUTOR_DEFAULT_PROGRESS_OUTPUT_NAME': 'stderr_file', 'EXECUTOR_MAX_BYTES_READ_PER_LINE': '1234', 'EXECUTOR_MAX_MESSAGE_LENGTH': '1024', 'EXECUTOR_PROGRESS_OUTPUT_FILE_ENV': 'OUTPUT_TARGET_FILE', 'MESOS_EXECUTOR_ID': 'e123456', 'MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD': '4secs', 'MESOS_SANDBOX': '/sandbox/location', 'OUTPUT_TARGET_FILE': '/dev/null', 'PROGRESS_REGEX_STRING': 'progress/regex', 'PROGRESS_SAMPLE_INTERVAL_MS': '2500' } config = cc.initialize_config(environment) self.assertEqual(1234, config.max_bytes_read_per_line) self.assertEqual(1024, config.max_message_length) self.assertEqual(3600, config.memory_usage_interval_secs) self.assertEqual('OUTPUT_TARGET_FILE', config.progress_output_env_variable) self.assertEqual('/dev/null', config.progress_output_name) self.assertEqual('progress/regex', config.progress_regex_string) self.assertEqual(2500, config.progress_sample_interval_ms) self.assertEqual('/sandbox/location', config.sandbox_directory) self.assertEqual(4000, config.shutdown_grace_period_ms)
def test_initialize_config_defaults(self): environment = {} config = cc.initialize_config(environment) self.assertEqual(4 * 1024, config.max_bytes_read_per_line) self.assertEqual(512, config.max_message_length) self.assertEqual('stdout', config.progress_output_name) self.assertEqual('progress: (\\d*), (.*)', config.progress_regex_string) self.assertEqual(1000, config.progress_sample_interval_ms) self.assertEqual('', config.sandbox_directory) self.assertEqual(2000, config.shutdown_grace_period_ms)
def test_initialize_config_defaults(self): environment = {} config = cc.initialize_config(environment) self.assertEqual(False, config.checkpoint) self.assertEqual(4 * 1024, config.max_bytes_read_per_line) self.assertEqual(512, config.max_message_length) self.assertEqual('', config.mesos_directory) self.assertEqual('executor.progress', config.progress_output_name) self.assertEqual('progress: ([0-9]*\\.?[0-9]+), (.*)', config.progress_regex_string) self.assertEqual(15 * 60 * 1000, config.recovery_timeout_ms) self.assertEqual(1000, config.progress_sample_interval_ms) self.assertEqual([], config.reset_vars) self.assertEqual('', config.sandbox_directory) self.assertEqual(2000, config.shutdown_grace_period_ms)
def test_initialize_config_custom(self): environment = { 'EXECUTOR_MAX_BYTES_READ_PER_LINE': '1234', 'EXECUTOR_MAX_MESSAGE_LENGTH': '1024', 'MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD': '4secs', 'MESOS_SANDBOX': '/sandbox/location', 'PROGRESS_OUTPUT_FILE': 'progress_file', 'PROGRESS_REGEX_STRING': 'progress/regex', 'PROGRESS_SAMPLE_INTERVAL_MS': '2500' } config = cc.initialize_config(environment) self.assertEqual(1234, config.max_bytes_read_per_line) self.assertEqual(1024, config.max_message_length) self.assertEqual('progress_file', config.progress_output_name) self.assertEqual('progress/regex', config.progress_regex_string) self.assertEqual(2500, config.progress_sample_interval_ms) self.assertEqual('/sandbox/location', config.sandbox_directory) self.assertEqual(4000, config.shutdown_grace_period_ms)
def test_initialize_config_custom_progress_file_without_sandbox(self): environment = {'EXECUTOR_MAX_BYTES_READ_PER_LINE': '1234', 'EXECUTOR_MAX_MESSAGE_LENGTH': '1024', 'EXECUTOR_MEMORY_USAGE_INTERVAL_SECS': '20', 'EXECUTOR_PROGRESS_OUTPUT_FILE_ENV': 'OUTPUT_TARGET_FILE', 'MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD': '4secs', 'OUTPUT_TARGET_FILE': 'progress.out', 'PROGRESS_REGEX_STRING': 'progress/regex', 'PROGRESS_SAMPLE_INTERVAL_MS': '2500'} config = cc.initialize_config(environment) self.assertEqual(1234, config.max_bytes_read_per_line) self.assertEqual(1024, config.max_message_length) self.assertEqual(30, config.memory_usage_interval_secs) self.assertEqual('OUTPUT_TARGET_FILE', config.progress_output_env_variable) self.assertEqual('progress.out', config.progress_output_name) self.assertEqual('progress/regex', config.progress_regex_string) self.assertEqual(2500, config.progress_sample_interval_ms) self.assertEqual('', config.sandbox_directory) self.assertEqual(4000, config.shutdown_grace_period_ms)
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)