def test_simple_process(): parameter = [] event = threading.Event() class DerpProcess(Process): def __init__(self, **kw): super(DerpProcess, self).__init__('derp', **kw) @Process.install('ping') def ping(self, value): parameter.append(value) event.set() context = Context() context.start() derp = DerpProcess() pid = context.spawn(derp) context.dispatch(pid, 'ping', 42) event.wait(timeout=1.0) assert event.is_set() assert parameter == [42] context.stop()
class TestVagrantIntegration(unittest.TestCase): def setUp(self): self.__pong = subprocess.Popen( 'vagrant ssh -- LIBPROCESS_IP=192.168.33.2 LIBPROCESS_PORT=31337 GLOG_v=5 ./pong', shell=True) self.ping_pid = PID.from_string('(1)@192.168.33.2:31337') self.context = Context(ip='192.168.33.1') self.context.start() def tearDown(self): self.__pong.kill() self.context.stop() def test_ping(self): class PongProcess(Process): def __init__(self, **kw): self.event = threading.Event() super(PongProcess, self).__init__('ponger', **kw) @Process.install('pong') def pong(self, from_pid, body): print('from_pid: %r, body: %r' % (from_pid, body)) self.event.set() pong = PongProcess() pong_pid = self.context.spawn(pong) self.context.send(pong_pid, self.ping_pid, 'ping') pong.event.wait(timeout=10.0) assert pong.event.is_set()
def test_mesos_executor_abort_on_disconnection(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) shutdown_event, shutdown_call, shutdown_side_effect = self.mock_method( ) executor = mock.create_autospec(Executor, spec_set=True) executor.shutdown = mock.Mock(side_effect=shutdown_side_effect) driver_context = Context() driver_context.start() self.close_contexts.append(driver_context) driver = PesosExecutorDriver(executor, context=driver_context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() self.slave.register_event.wait(timeout=MAX_TIMEOUT) assert self.slave.register_event.is_set() # kill connection conn = driver_context._connections[self.slave.pid] conn.close() # abort event shutdown_event.wait(timeout=MAX_TIMEOUT) assert shutdown_event.is_set() assert shutdown_call.mock_calls == [mock.call(driver)]
def test_mesos_executor_abort_on_disconnection(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) shutdown_event, shutdown_call, shutdown_side_effect = self.mock_method() executor = mock.create_autospec(Executor, spec_set=True) executor.shutdown = mock.Mock(side_effect=shutdown_side_effect) driver_context = Context() driver_context.start() self.close_contexts.append(driver_context) driver = PesosExecutorDriver(executor, context=driver_context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() self.slave.register_event.wait(timeout=MAX_TIMEOUT) assert self.slave.register_event.is_set() # kill connection conn = driver_context._connections[self.slave.pid] conn.close() # abort event shutdown_event.wait(timeout=MAX_TIMEOUT) assert shutdown_event.is_set() assert shutdown_call.mock_calls == [mock.call(driver)]
def test_protobuf_process_local_dispatch(): context = Context() context.start() try: ping_pong(context, context) finally: context.stop()
def test_protobuf_process_remote_dispatch(): context1 = Context() context1.start() context2 = Context() context2.start() try: ping_pong(context1, context2) finally: context1.stop() context2.stop()
def test_simple_message_pass(): context = Context() context.start() receiver = SimpleReceiver() sender = SimpleSender() context.spawn(receiver) context.spawn(sender) sender.send_simple(receiver.pid, 'simple_framework', 'simple_pid') receiver.receive_event.wait(timeout=1) assert receiver.receive_event.is_set() context.stop()
def test_link_race_condition(): context1 = Context() context1.start() context2 = Context() context2.start() class Leader(Process): def __init__(self): super(Leader, self).__init__('leader') self.uuid = None @Process.install('register') def register(self, from_pid, uuid): log.debug('Leader::register(%s, %s)' % (from_pid, uuid)) self.send(from_pid, 'registered', uuid) class Follower(Process): def __init__(self, leader): super(Follower, self).__init__('follower') self.leader = leader self.uuid = uuid.uuid4().bytes self.registered = threading.Event() def initialize(self): super(Follower, self).initialize() self.link(self.leader.pid) self.send(self.leader.pid, 'register', self.uuid) @Process.install('registered') def registered(self, from_pid, uuid): log.debug('Follower::registered(%s, %s)' % (from_pid, uuid)) assert uuid == self.uuid assert from_pid == self.leader.pid self.registered.set() leader = Leader() context1.spawn(leader) follower = Follower(leader) context2.spawn(follower) follower.registered.wait(timeout=MAX_TIMEOUT) assert follower.registered.is_set() context1.stop() context2.stop()
def test_mesos_executor_driver_init(): context = Context() context.start() # spawn slave slave = MockSlave() context.spawn(slave) os.environ['MESOS_SLAVE_PID'] = str(slave.pid) executor = Executor() driver = MesosExecutorDriver(executor, context=context) assert driver.start() == mesos.DRIVER_RUNNING assert driver.stop() == mesos.DRIVER_STOPPED assert driver.join() == mesos.DRIVER_STOPPED context.stop()
def test_protobuf_process(): parameter = [] event = threading.Event() recv_msg = mock.MagicMock() recv_msg.MergeFromString = mock.MagicMock() def msg_init(): return recv_msg send_msg = mock.MagicMock() send_msg.SerializeToString = mock.MagicMock() send_msg.SerializeToString.return_value = 'beepboop' class Pinger(ProtobufProcess): @ProtobufProcess.install(msg_init, endpoint='foo.bar.ping') def ping(self, from_pid, message): assert message == recv_msg message.MergeFromString.assert_called_with('beepboop') event.set() class Ponger(ProtobufProcess): pass context = Context() context.start() pinger = Pinger('pinger') ping_pid = context.spawn(pinger) context2 = Context() context2.start() ponger = Ponger('ponger') pong_pid = context2.spawn(ponger) # TODO(wickman) this doesn't actually work for local processes, hence # spawning two separate contexts. ponger.send(ping_pid, send_msg, method_name='foo.bar.ping') event.wait(timeout=1) assert event.is_set() context.stop() context2.stop()
def test_mesos_executor_register(): context = Context() context.start() # spawn slave slave = MockSlave() context.spawn(slave) os.environ['MESOS_SLAVE_PID'] = str(slave.pid) executor = mock.MagicMock() executor.registered = mock.MagicMock() driver = MesosExecutorDriver(executor, context=context) assert driver.start() == mesos.DRIVER_RUNNING command_info = mesos.CommandInfo(value='wat') framework_id = mesos.FrameworkID(value='fake_framework_id') executor_id = mesos.ExecutorID(value='fake_executor_id') executor_info = mesos.ExecutorInfo( executor_id=executor_id, framework_id=framework_id, command=command_info ) framework_info = mesos.FrameworkInfo(user='******', name='fake_framework_name') slave.send_registered( driver.executor_process.pid, executor_info, framework_id, framework_info ) driver.executor_process.connected.wait(timeout=1) assert driver.executor_process.connected.is_set() time.sleep(0.5) # We should wait a small amount of time executor.registered.assert_called_with(driver, executor_info, framework_info, slave.slave_info) assert driver.stop() == mesos.DRIVER_STOPPED context.stop()
def test_mesos_executor_register(): context = Context() context.start() # spawn slave slave = MockSlave() context.spawn(slave) os.environ['MESOS_SLAVE_PID'] = str(slave.pid) executor = mock.MagicMock() executor.registered = mock.MagicMock() driver = PesosExecutorDriver(executor, context=context) assert driver.start() == mesos.DRIVER_RUNNING command_info = mesos.CommandInfo(value='wat') framework_id = mesos.FrameworkID(value='fake_framework_id') executor_id = mesos.ExecutorID(value='fake_executor_id') executor_info = mesos.ExecutorInfo( executor_id=executor_id, framework_id=framework_id, command=command_info ) framework_info = mesos.FrameworkInfo(user='******', name='fake_framework_name') slave.send_registered( driver.executor_process.pid, executor_info, framework_id, framework_info ) driver.executor_process.connected.wait(timeout=1) assert driver.executor_process.connected.is_set() executor.registered.assert_called_with(driver, executor_info, framework_info, slave.slave_info) assert driver.stop() == mesos.DRIVER_STOPPED context.stop()
def test_link_exit_remote(self): parent_context = Context() parent_context.start() parent = ParentProcess() parent_context.spawn(parent) child = ChildProcess() self.context.spawn(child) parent.send(child.pid, 'link_me') child.link_event.wait(timeout=1.0) assert child.link_event.is_set() assert not child.exit_event.is_set() parent_context.terminate(parent.pid) parent_context.stop() child.send(parent.pid, 'this_will_break') child.exit_event.wait(timeout=1) assert child.exit_event.is_set()
def test_mesos_executor_reregister(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) os.environ['MESOS_CHECKPOINT'] = '1' os.environ['MESOS_RECOVERY_TIMEOUT'] = '15mins' reregistered_event, reregistered_call, reregistered_side_effect = self.mock_method( ) executor = mock.create_autospec(Executor, spec_set=True) executor.reregistered = mock.Mock(side_effect=reregistered_side_effect) driver_context = Context() driver_context.start() self.close_contexts.append(driver_context) driver = PesosExecutorDriver(executor, context=driver_context) assert driver.start() == mesos_pb2.DRIVER_RUNNING self.slave.register_event.wait(timeout=MAX_TIMEOUT) assert self.slave.register_event.is_set() driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # kill connection, but expect reconnect conn = driver_context._connections[self.slave.pid] conn.close() # simulate slave reconnecting self.slave.send_reconnect(driver.executor_process.pid) # wait for reregister event self.slave.reregister_event.wait(timeout=MAX_TIMEOUT) assert self.slave.reregister_event.is_set() driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # reregistered event reregistered_event.wait(timeout=MAX_TIMEOUT) assert reregistered_event.is_set() assert reregistered_call.mock_calls == [ mock.call(driver, self.slave.slave_info) ]
def test_protobuf_process_local_dispatch(): parameter = [] event = threading.Event() recv_msg = mock.MagicMock() recv_msg.MergeFromString = mock.MagicMock() def msg_init(): return recv_msg send_msg = mock.MagicMock() send_msg.SerializeToString = mock.MagicMock() send_msg.SerializeToString.return_value = 'beepboop' class Pinger(ProtobufProcess): @ProtobufProcess.install(msg_init, endpoint='foo.bar.ping') def ping(self, from_pid, message): assert message == recv_msg message.MergeFromString.assert_called_with('beepboop') event.set() class Ponger(ProtobufProcess): pass context = Context() context.start() pinger = Pinger('pinger') ping_pid = context.spawn(pinger) ponger = Ponger('ponger') pong_pid = context.spawn(ponger) ponger.send(ping_pid, send_msg, method_name='foo.bar.ping') event.wait(timeout=1) assert event.is_set() context.stop()
def test_mesos_executor_reregister(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) os.environ['MESOS_CHECKPOINT'] = '1' os.environ['MESOS_RECOVERY_TIMEOUT'] = '15mins' reregistered_event, reregistered_call, reregistered_side_effect = self.mock_method() executor = mock.create_autospec(Executor, spec_set=True) executor.reregistered = mock.Mock(side_effect=reregistered_side_effect) driver_context = Context() driver_context.start() self.close_contexts.append(driver_context) driver = PesosExecutorDriver(executor, context=driver_context) assert driver.start() == mesos_pb2.DRIVER_RUNNING self.slave.register_event.wait(timeout=MAX_TIMEOUT) assert self.slave.register_event.is_set() driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # kill connection, but expect reconnect conn = driver_context._connections[self.slave.pid] conn.close() # simulate slave reconnecting self.slave.send_reconnect(driver.executor_process.pid) # wait for reregister event self.slave.reregister_event.wait(timeout=MAX_TIMEOUT) assert self.slave.reregister_event.is_set() driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # reregistered event reregistered_event.wait(timeout=MAX_TIMEOUT) assert reregistered_event.is_set() assert reregistered_call.mock_calls == [mock.call(driver, self.slave.slave_info)]
class TestExecutor(unittest.TestCase): FRAMEWORK_ID = 'fake_framework_id' EXECUTOR_ID = 'fake_executor_id' SLAVE_ID = 'fake_slave_id' @staticmethod def mock_method(): event = threading.Event() call = mock.Mock() def side_effect(*args, **kw): call(*args, **kw) event.set() return event, call, side_effect def setUp(self): command_info = mesos_pb2.CommandInfo(value='wat') framework_id = mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID) executor_id = mesos_pb2.ExecutorID(value=self.EXECUTOR_ID) self.executor_info = mesos_pb2.ExecutorInfo( executor_id=executor_id, framework_id=framework_id, command=command_info, ) self.framework_info = mesos_pb2.FrameworkInfo( user='******', name='fake_framework_name', ) self.context = Context() self.context.start() self.slave = MockSlave( mesos_pb2.SlaveID(value=self.SLAVE_ID), {self.EXECUTOR_ID: self.executor_info}, {self.FRAMEWORK_ID: self.framework_info}, ) self.context.spawn(self.slave) self.close_contexts = [] def tearDown(self): self.context.stop() for context in self.close_contexts: context.stop() # ---- Executor callback tests def test_mesos_executor_register(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) registered_event, registered_call, registered_side_effect = self.mock_method( ) executor = mock.create_autospec(Executor, spec_set=True) executor.registered = mock.Mock(side_effect=registered_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() registered_event.wait(timeout=MAX_TIMEOUT) assert registered_event.is_set() assert registered_call.mock_calls == [ mock.call(driver, self.executor_info, self.framework_info, self.slave.slave_info) ] assert driver.stop() == mesos_pb2.DRIVER_STOPPED def test_mesos_executor_abort_on_disconnection(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) shutdown_event, shutdown_call, shutdown_side_effect = self.mock_method( ) executor = mock.create_autospec(Executor, spec_set=True) executor.shutdown = mock.Mock(side_effect=shutdown_side_effect) driver_context = Context() driver_context.start() self.close_contexts.append(driver_context) driver = PesosExecutorDriver(executor, context=driver_context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() self.slave.register_event.wait(timeout=MAX_TIMEOUT) assert self.slave.register_event.is_set() # kill connection conn = driver_context._connections[self.slave.pid] conn.close() # abort event shutdown_event.wait(timeout=MAX_TIMEOUT) assert shutdown_event.is_set() assert shutdown_call.mock_calls == [mock.call(driver)] def test_mesos_executor_reregister(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) os.environ['MESOS_CHECKPOINT'] = '1' os.environ['MESOS_RECOVERY_TIMEOUT'] = '15mins' reregistered_event, reregistered_call, reregistered_side_effect = self.mock_method( ) executor = mock.create_autospec(Executor, spec_set=True) executor.reregistered = mock.Mock(side_effect=reregistered_side_effect) driver_context = Context() driver_context.start() self.close_contexts.append(driver_context) driver = PesosExecutorDriver(executor, context=driver_context) assert driver.start() == mesos_pb2.DRIVER_RUNNING self.slave.register_event.wait(timeout=MAX_TIMEOUT) assert self.slave.register_event.is_set() driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # kill connection, but expect reconnect conn = driver_context._connections[self.slave.pid] conn.close() # simulate slave reconnecting self.slave.send_reconnect(driver.executor_process.pid) # wait for reregister event self.slave.reregister_event.wait(timeout=MAX_TIMEOUT) assert self.slave.reregister_event.is_set() driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # reregistered event reregistered_event.wait(timeout=MAX_TIMEOUT) assert reregistered_event.is_set() assert reregistered_call.mock_calls == [ mock.call(driver, self.slave.slave_info) ] def test_mesos_executor_run_task(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) launch_task_event, launch_task_call, launch_task_side_effect = self.mock_method( ) executor = mock.create_autospec(Executor, spec_set=True) executor.launchTask = mock.Mock(side_effect=launch_task_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # now launch task task_info = mesos_pb2.TaskInfo( name='task', task_id=mesos_pb2.TaskID(value='task-id'), slave_id=self.slave.slave_id, executor=self.executor_info, ) self.slave.send_run_task( driver.executor_process.pid, mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID), task_info, ) launch_task_event.wait(timeout=MAX_TIMEOUT) assert launch_task_event.is_set() assert launch_task_call.mock_calls == [mock.call(driver, task_info)] assert driver.executor_process.tasks == { task_info.task_id.value: task_info } def test_mesos_executor_kill_task(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) kill_task_event, kill_task_call, kill_task_side_effect = self.mock_method( ) executor = mock.create_autospec(Executor, spec_set=True) executor.killTask = mock.Mock(side_effect=kill_task_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # now launch task task_id = mesos_pb2.TaskID(value='task-id') self.slave.send_kill_task( driver.executor_process.pid, mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID), task_id, ) kill_task_event.wait(timeout=MAX_TIMEOUT) assert kill_task_event.is_set() assert kill_task_call.mock_calls == [mock.call(driver, task_id)] def test_mesos_executor_framework_message_delivery(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) framework_message_event, framework_message_call, framework_message_side_effect = ( self.mock_method()) executor = mock.create_autospec(Executor, spec_set=True) executor.frameworkMessage = mock.Mock( side_effect=framework_message_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() self.slave.send_framework_message( driver.executor_process.pid, mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID), mesos_pb2.ExecutorID(value=self.EXECUTOR_ID), data=b'beep boop beep', ) framework_message_event.wait(timeout=MAX_TIMEOUT) assert framework_message_event.is_set() assert framework_message_call.mock_calls == [ mock.call(driver, b'beep boop beep') ] def test_mesos_executor_shutdown(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) shutdown_event, shutdown_call, shutdown_side_effect = self.mock_method( ) executor = mock.create_autospec(Executor, spec_set=True) executor.shutdown = mock.Mock(side_effect=shutdown_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() self.slave.send_shutdown(driver.executor_process.pid) shutdown_event.wait(timeout=MAX_TIMEOUT) assert shutdown_event.is_set() assert shutdown_call.mock_calls == [mock.call(driver)] # -- Driver delivery tests def test_mesos_executor_driver_init(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING assert driver.stop() == mesos_pb2.DRIVER_STOPPED assert driver.join() == mesos_pb2.DRIVER_STOPPED def test_mesos_executor_driver_abort(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING assert driver.abort() == mesos_pb2.DRIVER_ABORTED driver.executor_process.aborted.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.aborted.is_set() assert driver.join() == mesos_pb2.DRIVER_ABORTED def test_mesos_executor_driver_run_and_abort(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) join_event = threading.Event() def runner(): assert driver.run() == mesos_pb2.DRIVER_ABORTED join_event.set() threading.Thread(target=runner).start() assert not join_event.is_set() driver.started.wait(timeout=MAX_TIMEOUT) assert driver.started.is_set() assert driver.abort() == mesos_pb2.DRIVER_ABORTED join_event.wait(timeout=MAX_TIMEOUT) assert join_event.is_set() def test_mesos_executor_driver_framework_message(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # send and wait for framework message assert driver.send_framework_message( b'beep boop beep') == mesos_pb2.DRIVER_RUNNING self.slave.framework_message_event.wait(timeout=MAX_TIMEOUT) assert self.slave.framework_message_event.is_set() framework_message = internal.ExecutorToFrameworkMessage( slave_id=self.slave.slave_id, framework_id=mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID), executor_id=mesos_pb2.ExecutorID(value=self.EXECUTOR_ID), data=b'beep boop beep', ) assert len(self.slave.framework_messages) == 1 assert self.slave.framework_messages[0][ 0] == driver.executor_process.pid assert self.slave.framework_messages[0][1] == framework_message, ( '%s != %s' % (self.slave.framework_messages[0][1], framework_message)) def test_mesos_executor_driver_status_update(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() task_status = mesos_pb2.TaskStatus( task_id=mesos_pb2.TaskID(value='task-id'), state=mesos_pb2.TASK_FAILED, ) assert driver.send_status_update( task_status) == mesos_pb2.DRIVER_RUNNING self.slave.status_update_event.wait(timeout=MAX_TIMEOUT) assert self.slave.status_update_event.is_set() assert len(self.slave.status_updates) == 1 assert self.slave.status_updates[0][0] == driver.executor_process.pid status_update_message = self.slave.status_updates[0][1] status_update = status_update_message.update assert status_update.slave_id == self.slave.slave_id assert status_update.framework_id == mesos_pb2.FrameworkID( value=self.FRAMEWORK_ID) assert status_update.executor_id == mesos_pb2.ExecutorID( value=self.EXECUTOR_ID) assert status_update.status.task_id == task_status.task_id assert status_update.status.state == task_status.state assert status_update.HasField('timestamp') assert status_update.HasField('uuid')
class TestExecutor(unittest.TestCase): FRAMEWORK_ID = 'fake_framework_id' EXECUTOR_ID = 'fake_executor_id' SLAVE_ID = 'fake_slave_id' @staticmethod def mock_method(): event = threading.Event() call = mock.Mock() def side_effect(*args, **kw): call(*args, **kw) event.set() return event, call, side_effect def setUp(self): command_info = mesos_pb2.CommandInfo(value='wat') framework_id = mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID) executor_id = mesos_pb2.ExecutorID(value=self.EXECUTOR_ID) self.executor_info = mesos_pb2.ExecutorInfo( executor_id=executor_id, framework_id=framework_id, command=command_info, ) self.framework_info = mesos_pb2.FrameworkInfo( user='******', name='fake_framework_name', ) self.context = Context() self.context.start() self.slave = MockSlave( mesos_pb2.SlaveID(value=self.SLAVE_ID), {self.EXECUTOR_ID: self.executor_info}, {self.FRAMEWORK_ID: self.framework_info}, ) self.context.spawn(self.slave) self.close_contexts = [] def tearDown(self): self.context.stop() for context in self.close_contexts: context.stop() # ---- Executor callback tests def test_mesos_executor_register(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) registered_event, registered_call, registered_side_effect = self.mock_method() executor = mock.create_autospec(Executor, spec_set=True) executor.registered = mock.Mock(side_effect=registered_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() registered_event.wait(timeout=MAX_TIMEOUT) assert registered_event.is_set() assert registered_call.mock_calls == [ mock.call(driver, self.executor_info, self.framework_info, self.slave.slave_info)] assert driver.stop() == mesos_pb2.DRIVER_STOPPED def test_mesos_executor_abort_on_disconnection(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) shutdown_event, shutdown_call, shutdown_side_effect = self.mock_method() executor = mock.create_autospec(Executor, spec_set=True) executor.shutdown = mock.Mock(side_effect=shutdown_side_effect) driver_context = Context() driver_context.start() self.close_contexts.append(driver_context) driver = PesosExecutorDriver(executor, context=driver_context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() self.slave.register_event.wait(timeout=MAX_TIMEOUT) assert self.slave.register_event.is_set() # kill connection conn = driver_context._connections[self.slave.pid] conn.close() # abort event shutdown_event.wait(timeout=MAX_TIMEOUT) assert shutdown_event.is_set() assert shutdown_call.mock_calls == [mock.call(driver)] def test_mesos_executor_reregister(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) os.environ['MESOS_CHECKPOINT'] = '1' os.environ['MESOS_RECOVERY_TIMEOUT'] = '15mins' reregistered_event, reregistered_call, reregistered_side_effect = self.mock_method() executor = mock.create_autospec(Executor, spec_set=True) executor.reregistered = mock.Mock(side_effect=reregistered_side_effect) driver_context = Context() driver_context.start() self.close_contexts.append(driver_context) driver = PesosExecutorDriver(executor, context=driver_context) assert driver.start() == mesos_pb2.DRIVER_RUNNING self.slave.register_event.wait(timeout=MAX_TIMEOUT) assert self.slave.register_event.is_set() driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # kill connection, but expect reconnect conn = driver_context._connections[self.slave.pid] conn.close() # simulate slave reconnecting self.slave.send_reconnect(driver.executor_process.pid) # wait for reregister event self.slave.reregister_event.wait(timeout=MAX_TIMEOUT) assert self.slave.reregister_event.is_set() driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # reregistered event reregistered_event.wait(timeout=MAX_TIMEOUT) assert reregistered_event.is_set() assert reregistered_call.mock_calls == [mock.call(driver, self.slave.slave_info)] def test_mesos_executor_run_task(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) launch_task_event, launch_task_call, launch_task_side_effect = self.mock_method() executor = mock.create_autospec(Executor, spec_set=True) executor.launchTask = mock.Mock(side_effect=launch_task_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # now launch task task_info = mesos_pb2.TaskInfo( name='task', task_id=mesos_pb2.TaskID(value='task-id'), slave_id=self.slave.slave_id, executor=self.executor_info, ) self.slave.send_run_task( driver.executor_process.pid, mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID), task_info, ) launch_task_event.wait(timeout=MAX_TIMEOUT) assert launch_task_event.is_set() assert launch_task_call.mock_calls == [mock.call(driver, task_info)] assert driver.executor_process.tasks == {task_info.task_id.value: task_info} def test_mesos_executor_kill_task(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) kill_task_event, kill_task_call, kill_task_side_effect = self.mock_method() executor = mock.create_autospec(Executor, spec_set=True) executor.killTask = mock.Mock(side_effect=kill_task_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # now launch task task_id = mesos_pb2.TaskID(value='task-id') self.slave.send_kill_task( driver.executor_process.pid, mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID), task_id, ) kill_task_event.wait(timeout=MAX_TIMEOUT) assert kill_task_event.is_set() assert kill_task_call.mock_calls == [mock.call(driver, task_id)] def test_mesos_executor_framework_message_delivery(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) framework_message_event, framework_message_call, framework_message_side_effect = ( self.mock_method()) executor = mock.create_autospec(Executor, spec_set=True) executor.frameworkMessage = mock.Mock(side_effect=framework_message_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() self.slave.send_framework_message( driver.executor_process.pid, mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID), mesos_pb2.ExecutorID(value=self.EXECUTOR_ID), data=b'beep boop beep', ) framework_message_event.wait(timeout=MAX_TIMEOUT) assert framework_message_event.is_set() assert framework_message_call.mock_calls == [mock.call(driver, b'beep boop beep')] def test_mesos_executor_shutdown(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) shutdown_event, shutdown_call, shutdown_side_effect = self.mock_method() executor = mock.create_autospec(Executor, spec_set=True) executor.shutdown = mock.Mock(side_effect=shutdown_side_effect) driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() self.slave.send_shutdown(driver.executor_process.pid) shutdown_event.wait(timeout=MAX_TIMEOUT) assert shutdown_event.is_set() assert shutdown_call.mock_calls == [mock.call(driver)] # -- Driver delivery tests def test_mesos_executor_driver_init(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING assert driver.stop() == mesos_pb2.DRIVER_STOPPED assert driver.join() == mesos_pb2.DRIVER_STOPPED def test_mesos_executor_driver_abort(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING assert driver.abort() == mesos_pb2.DRIVER_ABORTED driver.executor_process.aborted.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.aborted.is_set() assert driver.join() == mesos_pb2.DRIVER_ABORTED def test_mesos_executor_driver_run_and_abort(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) join_event = threading.Event() def runner(): assert driver.run() == mesos_pb2.DRIVER_ABORTED join_event.set() threading.Thread(target=runner).start() assert not join_event.is_set() driver.started.wait(timeout=MAX_TIMEOUT) assert driver.started.is_set() assert driver.abort() == mesos_pb2.DRIVER_ABORTED join_event.wait(timeout=MAX_TIMEOUT) assert join_event.is_set() def test_mesos_executor_driver_framework_message(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() # send and wait for framework message assert driver.send_framework_message(b'beep boop beep') == mesos_pb2.DRIVER_RUNNING self.slave.framework_message_event.wait(timeout=MAX_TIMEOUT) assert self.slave.framework_message_event.is_set() framework_message = internal.ExecutorToFrameworkMessage( slave_id=self.slave.slave_id, framework_id=mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID), executor_id=mesos_pb2.ExecutorID(value=self.EXECUTOR_ID), data=b'beep boop beep', ) assert len(self.slave.framework_messages) == 1 assert self.slave.framework_messages[0][0] == driver.executor_process.pid assert self.slave.framework_messages[0][1] == framework_message, ( '%s != %s' % (self.slave.framework_messages[0][1], framework_message)) def test_mesos_executor_driver_status_update(self): os.environ['MESOS_SLAVE_PID'] = str(self.slave.pid) executor = Executor() driver = PesosExecutorDriver(executor, context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING # wait until registered driver.executor_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.executor_process.connected.is_set() task_status = mesos_pb2.TaskStatus( task_id=mesos_pb2.TaskID(value='task-id'), state=mesos_pb2.TASK_FAILED, ) assert driver.send_status_update(task_status) == mesos_pb2.DRIVER_RUNNING self.slave.status_update_event.wait(timeout=MAX_TIMEOUT) assert self.slave.status_update_event.is_set() assert len(self.slave.status_updates) == 1 assert self.slave.status_updates[0][0] == driver.executor_process.pid status_update_message = self.slave.status_updates[0][1] status_update = status_update_message.update assert status_update.slave_id == self.slave.slave_id assert status_update.framework_id == mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID) assert status_update.executor_id == mesos_pb2.ExecutorID(value=self.EXECUTOR_ID) assert status_update.status.task_id == task_status.task_id assert status_update.status.state == task_status.state assert status_update.HasField('timestamp') assert status_update.HasField('uuid')
class TestScheduler(unittest.TestCase): FRAMEWORK_ID = 'fake_framework_id' @staticmethod def mock_method(): event = threading.Event() call = mock.Mock() def side_effect(*args, **kw): call(*args, **kw) event.set() return event, call, side_effect def setUp(self): self.framework_id = mesos_pb2.FrameworkID(value=self.FRAMEWORK_ID) self.framework_info = mesos_pb2.FrameworkInfo( user='******', name='fake_framework_name', ) self.context = Context() self.context.start() self.master = MockMaster() self.context.spawn(self.master) self.close_contexts = [] def tearDown(self): self.context.stop() for context in self.close_contexts: context.stop() def test_scheduler_registration(self): registered_event, registered_call, registered_side_effect = self.mock_method() scheduler = mock.create_autospec(Scheduler, spec_set=True) scheduler.registered = mock.Mock(side_effect=registered_side_effect) driver = PesosSchedulerDriver( scheduler, self.framework_info, str(self.master.pid), context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.scheduler_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.scheduler_process.connected.is_set() registered_event.wait(timeout=MAX_TIMEOUT) assert registered_event.is_set() assert len(self.master.frameworks) == 1 framework_id = next(iter(self.master.frameworks)) assert registered_call.mock_calls == [mock.call( driver, mesos_pb2.FrameworkID(value=framework_id), pid_to_master_info(self.master.master_id, self.master.pid))] assert driver.stop() == mesos_pb2.DRIVER_STOPPED def test_scheduler_scheduler_failover(self): reregistered_event, reregistered_call, reregistered_side_effect = self.mock_method() scheduler = mock.create_autospec(Scheduler, spec_set=True) scheduler.reregistered = mock.Mock(side_effect=reregistered_side_effect) self.framework_info.id.MergeFrom(self.framework_id) driver = PesosSchedulerDriver( scheduler, self.framework_info, str(self.master.pid), context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.scheduler_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.scheduler_process.connected.is_set() reregistered_event.wait(timeout=MAX_TIMEOUT) assert reregistered_event.is_set() assert len(self.master.frameworks) == 1 framework_id = next(iter(self.master.frameworks)) assert reregistered_call.mock_calls == [ mock.call(driver, pid_to_master_info(self.master.master_id, self.master.pid))] assert driver.stop() == mesos_pb2.DRIVER_STOPPED def test_scheduler_master_failover(self): disconnected_event, disconnected_call, disconnected_side_effect = self.mock_method() registered_event, registered_call, registered_side_effect = self.mock_method() reregistered_event, reregistered_call, reregistered_side_effect = self.mock_method() scheduler = mock.create_autospec(Scheduler, spec_set=True) scheduler.disconnected = mock.Mock(side_effect=disconnected_side_effect) scheduler.registered = mock.Mock(side_effect=registered_side_effect) scheduler.reregistered = mock.Mock(side_effect=reregistered_side_effect) standby_master = MockMaster() self.context.spawn(standby_master) driver = PesosSchedulerDriver( scheduler, self.framework_info, str(self.master.pid), context=self.context) assert driver.start() == mesos_pb2.DRIVER_RUNNING driver.scheduler_process.connected.wait(timeout=MAX_TIMEOUT) assert driver.scheduler_process.connected.is_set() registered_event.wait(timeout=MAX_TIMEOUT) assert registered_event.is_set() # now fail the current master driver.detector.appoint(None) disconnected_event.wait(timeout=MAX_TIMEOUT) assert disconnected_event.is_set() # now appoint the new master driver.detector.appoint(standby_master.pid) standby_master.reregister_event.wait(timeout=MAX_TIMEOUT) assert standby_master.reregister_event.is_set() assert standby_master.frameworks == self.master.frameworks reregistered_event.wait(timeout=MAX_TIMEOUT) assert reregistered_event.is_set() assert reregistered_call.mock_calls == [ mock.call(driver, pid_to_master_info(standby_master.master_id, standby_master.pid))] assert driver.stop() == mesos_pb2.DRIVER_STOPPED