def succeeded(self, reply): """ Notification (reply) indicating an RMI succeeded. This information is relayed to the task coordinator. :param reply: A successful reply object. :type reply: gofer.rmi.async.Succeeded """ log.info('Task RMI (succeeded)\n%s', reply) call_context = dict(reply.any) action = call_context.get('action') task_id = call_context['task_id'] result = dict(reply.retval) TaskStatusManager.set_task_succeeded(task_id, result) if action == 'bind': if result['succeeded']: ReplyHandler._bind_succeeded(task_id, call_context) else: ReplyHandler._bind_failed(task_id, call_context) return if action == 'unbind': if result['succeeded']: ReplyHandler._unbind_succeeded(call_context) else: ReplyHandler._unbind_failed(task_id, call_context) return
def test_GET_celery_tasks(self): """ Test the GET() method to get all current tasks. """ # Populate a couple of task statuses task_id1 = str(uuid.uuid4()) queue_1 = 'queue_1' state1 = 'waiting' task_id2 = str(uuid.uuid4()) queue_2 = 'queue_2' state2 = 'running' tags = ['random', 'tags'] TaskStatusManager.create_task_status(task_id1, queue_1, tags, state1) TaskStatusManager.create_task_status(task_id2, queue_2, tags, state2) status, body = self.get('/v2/tasks/') # Validate self.assertEqual(200, status) self.assertTrue(len(body) == 2) for task in body: if task['task_id'] == task_id1: self.assertEqual( task['_href'], serialization.dispatch.task_result_href(task)['_href']) self.assertEquals(task['state'], state1) self.assertEqual(task['queue'], queue_1) else: self.assertEqual( task['_href'], serialization.dispatch.task_result_href(task)['_href']) self.assertEquals(task['state'], state2) self.assertEqual(task['queue'], queue_2) self.assertEquals(task['tags'], tags)
def test_update_task_status(self): """ Tests the successful operation of update_task_status(). """ task_id = self.get_random_uuid() queue = 'special_queue' tags = ['test-tag1', 'test-tag2'] state = 'waiting' TaskStatusManager.create_task_status(task_id, queue, tags, state) now = datetime.now(dateutils.utc_tz()) start_time = dateutils.format_iso8601_datetime(now) delta = {'start_time': start_time, 'state': 'running', 'disregard': 'ignored', 'progress_report': {'report-id': 'my-progress'}} updated = TaskStatusManager.update_task_status(task_id, delta) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['start_time'], delta['start_time']) # Make sure that parse_iso8601_datetime is able to parse the start_time without errors dateutils.parse_iso8601_datetime(task_status['start_time']) self.assertEqual(task_status['state'], delta['state']) self.assertEqual(task_status['progress_report'], delta['progress_report']) self.assertEqual(task_status['queue'], queue) self.assertEqual(updated['start_time'], delta['start_time']) self.assertEqual(updated['state'], delta['state']) self.assertEqual(updated['progress_report'], delta['progress_report']) self.assertTrue('disregard' not in updated) self.assertTrue('disregard' not in task_status)
def test_on_success_handler_async_result(self, mock_request): """ Make sure that overridden on_success handler updates task status correctly """ retval = AsyncResult('foo-id') task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = { '1': 'for the money', 'tags': ['test_tags'], 'queue': WORKER_2_QUEUE } mock_request.called_directly = False task_status = TaskStatusManager.create_task_status( task_id, 'some_queue') self.assertEqual(task_status['state'], 'waiting') self.assertEqual(task_status['finish_time'], None) task = tasks.Task() task.on_success(retval, task_id, args, kwargs) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'finished') self.assertEqual(new_task_status['result'], None) self.assertFalse(new_task_status['finish_time'] is None) # Make sure that parse_iso8601_datetime is able to parse the finish_time without errors dateutils.parse_iso8601_datetime(new_task_status['finish_time']) self.assertEqual(new_task_status['spawned_tasks'], ['foo-id'])
def on_success(self, retval, task_id, args, kwargs): """ This overrides the success handler run by the worker when the task executes successfully. It updates state, finish_time and traceback of the relevant task status for asynchronous tasks. Skip updating status for synchronous tasks. :param retval: The return value of the task. :param task_id: Unique id of the executed task. :param args: Original arguments for the executed task. :param kwargs: Original keyword arguments for the executed task. """ logger.debug("Task successful : [%s]" % task_id) if not self.request.called_directly: delta = {'state': dispatch_constants.CALL_FINISHED_STATE, 'finish_time': dateutils.now_utc_timestamp(), 'result': retval} if isinstance(retval, TaskResult): delta['result'] = retval.return_value if retval.error: delta['error'] = retval.error.to_dict() if retval.spawned_tasks: task_list = [] for spawned_task in retval.spawned_tasks: if isinstance(spawned_task, AsyncResult): task_list.append(spawned_task.task_id) elif isinstance(spawned_task, dict): task_list.append(spawned_task['task_id']) delta['spawned_tasks'] = task_list if isinstance(retval, AsyncResult): delta['spawned_tasks'] = [retval.task_id, ] delta['result'] = None TaskStatusManager.update_task_status(task_id=task_id, delta=delta)
def test_on_success_handler_spawned_task_dict(self, mock_request): """ Make sure that overridden on_success handler updates task status correctly """ retval = tasks.TaskResult(spawned_tasks=[{ 'task_id': 'foo-id' }], result='bar') task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = { '1': 'for the money', 'tags': ['test_tags'], 'queue': WORKER_2_QUEUE } mock_request.called_directly = False task_status = TaskStatusManager.create_task_status( task_id, 'some_queue') self.assertEqual(task_status['state'], 'waiting') self.assertEqual(task_status['finish_time'], None) task = tasks.Task() task.on_success(retval, task_id, args, kwargs) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'finished') self.assertEqual(new_task_status['result'], 'bar') self.assertFalse(new_task_status['finish_time'] is None) self.assertEqual(new_task_status['spawned_tasks'], ['foo-id'])
def on_failure(self, exc, task_id, args, kwargs, einfo): """ This overrides the error handler run by the worker when the task fails. It updates state, finish_time and traceback of the relevant task status for asynchronous tasks. Skip updating status for synchronous tasks. :param exc: The exception raised by the task. :param task_id: Unique id of the failed task. :param args: Original arguments for the executed task. :param kwargs: Original keyword arguments for the executed task. :param einfo: celery's ExceptionInfo instance, containing serialized traceback. """ logger.debug("Task failed : [%s]" % task_id) if not self.request.called_directly: now = datetime.now(dateutils.utc_tz()) finish_time = dateutils.format_iso8601_datetime(now) delta = { 'state': constants.CALL_ERROR_STATE, 'finish_time': finish_time, 'traceback': einfo.traceback } if not isinstance(exc, PulpException): exc = PulpException(str(exc)) delta['error'] = exc.to_dict() TaskStatusManager.update_task_status(task_id=task_id, delta=delta)
def test_spawned_task_status(self, mock_request): async_result = AsyncResult('foo-id') retval = tasks.TaskResult(error=PulpException('error-foo'), result='bar') retval.spawned_tasks = [async_result] task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = { '1': 'for the money', 'tags': ['test_tags'], 'routing_key': WORKER_2 } mock_request.called_directly = False task_status = TaskStatusManager.create_task_status(task_id) self.assertEqual(task_status['state'], 'waiting') self.assertEqual(task_status['finish_time'], None) task = tasks.Task() task.on_success(retval, task_id, args, kwargs) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'finished') self.assertEqual(new_task_status['result'], 'bar') self.assertEqual(new_task_status['error']['description'], 'error-foo') self.assertFalse(new_task_status['finish_time'] is None) # Make sure that parse_iso8601_datetime is able to parse the finish_time without errors dateutils.parse_iso8601_datetime(new_task_status['finish_time']) self.assertEqual(new_task_status['spawned_tasks'], ['foo-id'])
def test_spawned_task_dict(self, mock_request): retval = tasks.TaskResult(spawned_tasks=[{ 'task_id': 'foo-id' }], result='bar') task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = { '1': 'for the money', 'tags': ['test_tags'], 'routing_key': WORKER_2 } mock_request.called_directly = False task_status = TaskStatusManager.create_task_status(task_id) self.assertEqual(task_status['state'], 'waiting') self.assertEqual(task_status['finish_time'], None) task = tasks.Task() task.on_success(retval, task_id, args, kwargs) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'finished') self.assertEqual(new_task_status['result'], 'bar') self.assertFalse(new_task_status['finish_time'] is None) self.assertEqual(new_task_status['spawned_tasks'], ['foo-id'])
def succeeded(self, reply): """ Notification (reply) indicating an RMI succeeded. This information is relayed to the task coordinator. :param reply: A successful reply object. :type reply: gofer.rmi.async.Succeeded """ log.info(_('Task RMI (succeeded): %(r)s'), {'r': reply}) call_context = dict(reply.any) action = call_context.get('action') task_id = call_context['task_id'] result = dict(reply.retval) TaskStatusManager.set_task_succeeded(task_id, result=result, timestamp=reply.timestamp) if action == 'bind': if result['succeeded']: ReplyHandler._bind_succeeded(task_id, call_context) else: ReplyHandler._bind_failed(task_id, call_context) return if action == 'unbind': if result['succeeded']: ReplyHandler._unbind_succeeded(call_context) else: ReplyHandler._unbind_failed(task_id, call_context) return
def test_update_task_status(self): """ Tests the successful operation of update_task_status(). """ task_id = self.get_random_uuid() queue = 'special_queue' tags = ['test-tag1', 'test-tag2'] state = 'waiting' TaskStatusManager.create_task_status(task_id, queue, tags, state) delta = {'start_time': dateutils.now_utc_timestamp(), 'state': 'running', 'disregard': 'ignored', 'progress_report': {'report-id': 'my-progress'}} updated = TaskStatusManager.update_task_status(task_id, delta) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['start_time'], delta['start_time']) self.assertEqual(task_status['state'], delta['state']) self.assertEqual(task_status['progress_report'], delta['progress_report']) self.assertEqual(task_status['queue'], queue) self.assertEqual(updated['start_time'], delta['start_time']) self.assertEqual(updated['state'], delta['state']) self.assertEqual(updated['progress_report'], delta['progress_report']) self.assertTrue('disregard' not in updated) self.assertTrue('disregard' not in task_status)
def set_progress(self, status): """ Informs the server of the current state of the publish operation. The contents of the status is dependent on how the distributor implementation chooses to divide up the publish process. @param status: contains arbitrary data to describe the state of the publish; the contents may contain whatever information is relevant to the distributor implementation so long as it is serializable """ if self.task_id is None: # not running within a task return try: self.progress_report[self.report_id] = status delta = {'progress_report': self.progress_report} TaskStatusManager.update_task_status(self.task_id, delta) except Exception, e: logger.exception( 'Exception from server setting progress for report [%s]' % self.report_id) try: logger.error('Progress value: %s' % str(status)) except Exception: # Best effort to print this, but if its that grossly unserializable # the log will tank and we don't want that exception to bubble up pass raise self.exception_class(e), None, sys.exc_info()[2]
def test_update_task_status(self): """ Tests the successful operation of update_task_status(). """ task_id = self.get_random_uuid() queue = 'special_queue' tags = ['test-tag1', 'test-tag2'] state = 'waiting' TaskStatusManager.create_task_status(task_id, queue, tags, state) now = datetime.now(dateutils.utc_tz()) start_time = dateutils.format_iso8601_datetime(now) delta = { 'start_time': start_time, 'state': 'running', 'disregard': 'ignored', 'progress_report': { 'report-id': 'my-progress' } } updated = TaskStatusManager.update_task_status(task_id, delta) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['start_time'], delta['start_time']) # Make sure that parse_iso8601_datetime is able to parse the start_time without errors dateutils.parse_iso8601_datetime(task_status['start_time']) self.assertEqual(task_status['state'], delta['state']) self.assertEqual(task_status['progress_report'], delta['progress_report']) self.assertEqual(task_status['queue'], queue) self.assertEqual(updated['start_time'], delta['start_time']) self.assertEqual(updated['state'], delta['state']) self.assertEqual(updated['progress_report'], delta['progress_report']) self.assertTrue('disregard' not in updated) self.assertTrue('disregard' not in task_status)
def test_on_success_handler_spawned_task_status(self, mock_request): """ Make sure that overridden on_success handler updates task status correctly """ async_result = AsyncResult('foo-id') retval = tasks.TaskResult(error=PulpException('error-foo'), result='bar') retval.spawned_tasks = [async_result] task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = {'1': 'for the money', 'tags': ['test_tags'], 'queue': RESERVED_WORKER_2} mock_request.called_directly = False task_status = TaskStatusManager.create_task_status(task_id, 'some_queue') self.assertEqual(task_status['state'], None) self.assertEqual(task_status['finish_time'], None) task = tasks.Task() task.on_success(retval, task_id, args, kwargs) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'finished') self.assertEqual(new_task_status['result'], 'bar') self.assertEqual(new_task_status['error']['description'], 'error-foo') self.assertFalse(new_task_status['finish_time'] == None) self.assertEqual(new_task_status['spawned_tasks'], ['foo-id'])
def test_on_success_with_canceled_task(self, mock_request): """ Make sure on_success() does not move a canceled Task to 'finished' state. """ retval = 'random_return_value' task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = { '1': 'for the money', 'tags': ['test_tags'], 'queue': WORKER_2_QUEUE } mock_request.called_directly = False task_status = TaskStatusManager.create_task_status( task_id, 'some_queue', state=CALL_CANCELED_STATE) task = tasks.Task() # This should not update the task status to finished, since this task was canceled. task.on_success(retval, task_id, args, kwargs) updated_task_status = TaskStatusManager.find_by_task_id(task_id) # Make sure the task is still canceled. self.assertEqual(updated_task_status['state'], CALL_CANCELED_STATE) self.assertEqual(updated_task_status['result'], retval) self.assertFalse(updated_task_status['finish_time'] is None) # Make sure that parse_iso8601_datetime is able to parse the finish_time without errors dateutils.parse_iso8601_datetime(updated_task_status['finish_time'])
def set_progress(self, status): """ Informs the server of the current state of the publish operation. The contents of the status is dependent on how the distributor implementation chooses to divide up the publish process. @param status: contains arbitrary data to describe the state of the publish; the contents may contain whatever information is relevant to the distributor implementation so long as it is serializable """ try: self.progress_report[self.report_id] = status context = dispatch_factory.context() delta = {'progress_report': self.progress_report} TaskStatusManager.update_task_status(context.call_request_id, delta) context.report_progress(self.progress_report) except Exception, e: _LOG.exception('Exception from server setting progress for report [%s]' % self.report_id) try: _LOG.error('Progress value: %s' % str(status)) except Exception: # Best effort to print this, but if its that grossly unserializable # the log will tank and we don't want that exception to bubble up pass raise self.exception_class(e), None, sys.exc_info()[2]
def test_GET_celery_tasks(self): """ Test the GET() method to get all current tasks. """ # Populate a couple of task statuses task_id1 = str(uuid.uuid4()) worker_1 = 'worker_1' state1 = 'waiting' task_id2 = str(uuid.uuid4()) worker_2 = 'worker_2' state2 = 'running' tags = ['random', 'tags'] TaskStatusManager.create_task_status(task_id1, worker_1, tags, state1) TaskStatusManager.create_task_status(task_id2, worker_2, tags, state2) status, body = self.get('/v2/tasks/') # Validate self.assertEqual(200, status) self.assertTrue(len(body) == 2) for task in body: if task['task_id'] == task_id1: self.assertEqual(task['_href'], serialization.dispatch.task_result_href(task)['_href']) self.assertEquals(task['state'], state1) self.assertEqual(task['worker_name'], worker_1) else: self.assertEqual(task['_href'], serialization.dispatch.task_result_href(task)['_href']) self.assertEquals(task['state'], state2) self.assertEqual(task['worker_name'], worker_2) self.assertEquals(task['tags'], tags)
def test_on_success_handler_async_result(self, mock_request): """ Make sure that overridden on_success handler updates task status correctly """ retval = AsyncResult('foo-id') task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = {'1': 'for the money', 'tags': ['test_tags'], 'queue': RESERVED_WORKER_2} mock_request.called_directly = False task_status = TaskStatusManager.create_task_status(task_id, 'some_queue') self.assertEqual(task_status['state'], 'waiting') self.assertEqual(task_status['finish_time'], None) task = tasks.Task() task.on_success(retval, task_id, args, kwargs) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'finished') self.assertEqual(new_task_status['result'], None) self.assertFalse(new_task_status['finish_time'] is None) # Make sure that parse_iso8601_datetime is able to parse the finish_time without errors dateutils.parse_iso8601_datetime(new_task_status['finish_time']) self.assertEqual(new_task_status['spawned_tasks'], ['foo-id'])
def test_on_failure_handler(self, mock_request): """ Make sure that overridden on_failure handler updates task status correctly """ exc = Exception() task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = {'1': 'for the money', 'tags': ['test_tags']} class EInfo(object): """ on_failure handler expects an instance of celery's ExceptionInfo class as one of the attributes. It stores string representation of traceback in it's traceback instance variable. This is a stub to imitate that behavior. """ def __init__(self): self.traceback = "string_repr_of_traceback" einfo = EInfo() mock_request.called_directly = False task_status = TaskStatusManager.create_task_status(task_id, 'some_queue') self.assertEqual(task_status['state'], 'waiting') self.assertEqual(task_status['finish_time'], None) self.assertEqual(task_status['traceback'], None) task = tasks.Task() task.on_failure(exc, task_id, args, kwargs, einfo) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'error') self.assertFalse(new_task_status['finish_time'] is None) # Make sure that parse_iso8601_datetime is able to parse the finish_time without errors dateutils.parse_iso8601_datetime(new_task_status['finish_time']) self.assertEqual(new_task_status['traceback'], einfo.traceback)
def test_spawned_task_status(self, mock_request): async_result = AsyncResult('foo-id') retval = tasks.TaskResult(error=PulpException('error-foo'), result='bar') retval.spawned_tasks = [async_result] task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = {'1': 'for the money', 'tags': ['test_tags'], 'routing_key': WORKER_2} mock_request.called_directly = False task_status = TaskStatusManager.create_task_status(task_id) self.assertEqual(task_status['state'], 'waiting') self.assertEqual(task_status['finish_time'], None) task = tasks.Task() task.on_success(retval, task_id, args, kwargs) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'finished') self.assertEqual(new_task_status['result'], 'bar') self.assertEqual(new_task_status['error']['description'], 'error-foo') self.assertFalse(new_task_status['finish_time'] is None) # Make sure that parse_iso8601_datetime is able to parse the finish_time without errors dateutils.parse_iso8601_datetime(new_task_status['finish_time']) self.assertEqual(new_task_status['spawned_tasks'], ['foo-id'])
def test_updates_task_status_correctly(self, mock_request): exc = Exception() task_id = str(uuid.uuid4()) args = [1, 'b', 'iii'] kwargs = {'1': 'for the money', 'tags': ['test_tags']} class EInfo(object): """ on_failure handler expects an instance of celery's ExceptionInfo class as one of the attributes. It stores string representation of traceback in it's traceback instance variable. This is a stub to imitate that behavior. """ def __init__(self): self.traceback = "string_repr_of_traceback" einfo = EInfo() mock_request.called_directly = False task_status = TaskStatusManager.create_task_status(task_id) self.assertEqual(task_status['state'], 'waiting') self.assertEqual(task_status['finish_time'], None) self.assertEqual(task_status['traceback'], None) task = tasks.Task() task.on_failure(exc, task_id, args, kwargs, einfo) new_task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(new_task_status['state'], 'error') self.assertFalse(new_task_status['finish_time'] is None) # Make sure that parse_iso8601_datetime is able to parse the finish_time without errors dateutils.parse_iso8601_datetime(new_task_status['finish_time']) self.assertEqual(new_task_status['traceback'], einfo.traceback)
def test_set_started_with_timestamp(self, get_collection): task_id = 'test' timestamp = '1234' collection = mock.Mock() get_collection.return_value = collection # test TaskStatusManager.set_task_started(task_id, timestamp=timestamp) # validation select_1 = { 'task_id': task_id } update_1 = { '$set': {'start_time': timestamp} } select_2 = { 'task_id': task_id, 'state': {'$in': [constants.CALL_WAITING_STATE, constants.CALL_ACCEPTED_STATE]} } update_2 = { '$set': {'state': constants.CALL_RUNNING_STATE} } self.assertEqual( collection.update.call_args_list, [ ((select_1, update_1), {'safe': True}), ((select_2, update_2), {'safe': True}), ])
def test_GET_celery_tasks(self): """ Test the GET() method to get all current tasks. """ # Populate a couple of task statuses task_id1 = str(uuid.uuid4()) queue_1 = 'queue_1' state1 = 'waiting' task_id2 = str(uuid.uuid4()) queue_2 = 'queue_2' state2 = 'running' tags = ['random', 'tags'] TaskStatusManager.create_task_status(task_id1, queue_1, tags, state1) TaskStatusManager.create_task_status(task_id2, queue_2, tags, state2) status, body = self.get('/v2/tasks/') # Validate self.assertEqual(200, status) self.assertTrue(len(body) == 2) for task in body: if task['task_id'] == task_id1: self.assertEquals(task['state'], state1) self.assertEqual(task['queue'], queue_1) else: self.assertEquals(task['state'], state2) self.assertEqual(task['queue'], queue_2) self.assertEquals(task['tags'], tags)
def test_create_task_status_invalid_task_id(self): """ Test that calling create_task_status() with an invalid task id raises the correct error. """ try: TaskStatusManager.create_task_status(None) except exceptions.InvalidValue, e: self.assertTrue(e.property_names[0], 'task_id')
def test_cancel_after_task_finished(self, logger, revoke): task_id = '1234abcd' test_queue = AvailableQueue('test_queue') TaskStatusManager.create_task_status(task_id, test_queue.name, state=CALL_FINISHED_STATE) self.assertRaises(PulpCodedException, tasks.cancel, task_id) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['state'], CALL_FINISHED_STATE)
def test_update_missing_task_status(self): """ Tests updating a task status that doesn't exist raises the appropriate exception. """ task_id = self.get_random_uuid() try: TaskStatusManager.update_task_status(task_id, {}) except exceptions.MissingResource, e: self.assertTrue(task_id == e.resources['resource_id'])
def test_GET_has_correct_worker_name_attribute(self): task_id = '1234abcd' TaskStatusManager.create_task_status(task_id, worker_name='worker1') result = self.task_resource.GET(task_id) result_json = json.loads(result) self.assertTrue('worker_name' in result_json) self.assertTrue(result_json['worker_name'] == 'worker1')
def test_DELETE_completed_celery_task(self): """ Test the DELETE() method raises a TaskComplete exception if the task is already complete. """ task_id = '1234abcd' test_queue = AvailableQueue('test_queue') TaskStatusManager.create_task_status(task_id, test_queue.name, state=dispatch_constants.CALL_FINISHED_STATE) self.assertRaises(PulpCodedException, self.task_resource.DELETE, task_id)
def test_cancel_after_task_finished(self, logger, revoke): task_id = '1234abcd' now = datetime.utcnow() test_worker = Worker('test_worker', now) TaskStatusManager.create_task_status(task_id, test_worker.name, state=CALL_FINISHED_STATE) self.assertRaises(PulpCodedException, tasks.cancel, task_id) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['state'], CALL_FINISHED_STATE)
def test_delete_not_existing_task_status(self): """ Tests that deleting a task status that doesn't exist raises the appropriate error. """ task_id = self.get_random_uuid() try: TaskStatusManager.delete_task_status(task_id) except exceptions.MissingResource, e: self.assertTrue(task_id == e.resources['resource_id'])
def test_DELETE_completed_celery_task(self): """ Test the DELETE() method does not change the state of a task that is already complete """ task_id = '1234abcd' TaskStatusManager.create_task_status(task_id, state=constants.CALL_FINISHED_STATE) self.task_resource.DELETE(task_id) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['state'], constants.CALL_FINISHED_STATE)
def test_DELETE_completed_celery_task(self): """ Test the DELETE() method raises a TaskComplete exception if the task is already complete. """ task_id = '1234abcd' now = datetime.utcnow() test_worker = Worker('test_worker', now) TaskStatusManager.create_task_status(task_id, test_worker.name, state=constants.CALL_FINISHED_STATE) self.assertRaises(PulpCodedException, self.task_resource.DELETE, task_id)
def started(self, reply): """ Notification that an RMI has started executing in the agent. The task status is updated in the pulp DB. :param reply: A status reply object. :type reply: gofer.rmi.async.Started """ call_context = reply.any task_id = call_context['task_id'] TaskStatusManager.set_task_started(task_id)
def test_DELETE_completed_celery_task(self): """ Test the DELETE() method does not change the state of a task that is already complete """ task_id = '1234abcd' TaskStatusManager.create_task_status( task_id, state=constants.CALL_FINISHED_STATE) self.task_resource.DELETE(task_id) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['state'], constants.CALL_FINISHED_STATE)
def test_create_task_status_duplicate_task_id(self): """ Tests create_task_status() with a duplicate task id. """ task_id = self.get_random_uuid() TaskStatusManager.create_task_status(task_id) try: TaskStatusManager.create_task_status(task_id) except exceptions.DuplicateResource, e: self.assertTrue(task_id in e)
def test_DELETE_celery_task(self, revoke): """ Test the DELETE() method with a UUID that does not correspond to a UUID that the coordinator is aware of. This should cause a revoke call to Celery's Controller. """ task_id = '1234abcd' TaskStatusManager.create_task_status(task_id) self.task_resource.DELETE(task_id) revoke.assert_called_once_with(task_id, terminate=True)
def test_DELETE_completed_celery_task(self): """ Test the DELETE() method raises a TaskComplete exception if the task is already complete. """ task_id = '1234abcd' now = datetime.utcnow() test_worker = Worker('test_worker', now) TaskStatusManager.create_task_status( task_id, test_worker.name, state=constants.CALL_FINISHED_STATE) self.assertRaises(PulpCodedException, self.task_resource.DELETE, task_id)
def progress(self, reply): """ Notification (reply) indicating an RMI has reported status. This information is relayed to the task coordinator. :param reply: A progress reply object. :type reply: gofer.rmi.async.Progress """ call_context = dict(reply.any) task_id = call_context['task_id'] delta = {'progress_report': reply.details} TaskStatusManager.update_task_status(task_id, delta)
def test_delete_task_status(self): """ Test delete_task_status() under normal circumstances. """ task_id = self.get_random_uuid() TaskStatusManager.create_task_status(task_id, 'a_queue') TaskStatusManager.delete_task_status(task_id) task_statuses = list(TaskStatusManager.find_all()) self.assertEqual(0, len(task_statuses))
def test_cancel_after_task_canceled(self, *unused_mocks): """ Test that canceling a task that was already canceled results in no change to the task state. """ task_id = '1234abcd' TaskStatusManager.create_task_status(task_id, 'test_worker', state=CALL_CANCELED_STATE) tasks.cancel(task_id) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['state'], CALL_CANCELED_STATE)
def test_cancel_after_task_finished(self, logger, revoke): """ Test that canceling a task that is already finished results in no change to the task state. """ task_id = '1234abcd' TaskStatusManager.create_task_status(task_id, 'test_worker', state=CALL_FINISHED_STATE) tasks.cancel(task_id) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['state'], CALL_FINISHED_STATE)
def started(self, reply): """ Notification that an RMI has started executing in the agent. The task status is updated in the pulp DB. :param reply: A status reply object. :type reply: gofer.rmi.async.Started """ log.debug(_('Task RMI (started): %(r)s'), {'r': reply}) call_context = dict(reply.any) task_id = call_context['task_id'] TaskStatusManager.set_task_started(task_id, timestamp=reply.timestamp)
def test_cancel_successful(self, logger, revoke): task_id = '1234abcd' TaskStatusManager.create_task_status(task_id) tasks.cancel(task_id) revoke.assert_called_once_with(task_id, terminate=True) self.assertEqual(logger.info.call_count, 1) log_msg = logger.info.mock_calls[0][1][0] self.assertTrue(task_id in log_msg) self.assertTrue('Task canceled' in log_msg) task_status = TaskStatusManager.find_by_task_id(task_id) self.assertEqual(task_status['state'], CALL_CANCELED_STATE)
def test_set_accepted(self, mock_update): task_id = 'test' # test TaskStatusManager.set_task_accepted(task_id) # validation delta = {'state': constants.CALL_ACCEPTED_STATE} mock_update.assert_called_with(task_id=task_id, delta=delta)
def test_set_started(self, mock_update, mock_date): task_id = 'test' now = '1234' mock_date.return_value = now # test TaskStatusManager.set_task_started(task_id) # validation delta = {'state': constants.CALL_RUNNING_STATE, 'start_time': now} mock_update.assert_called_with(task_id=task_id, delta=delta)
def test_create_task_status_defaults(self): """ Tests create_task_status() with minimal information, to ensure that defaults are handled properly. """ task_id = self.get_random_uuid() TaskStatusManager.create_task_status(task_id) task_statuses = list(TaskStatus.get_collection().find()) self.assertEqual(1, len(task_statuses)) self.assertEqual(task_id, task_statuses[0]['task_id']) self.assertEqual(None, task_statuses[0]['worker_name']) self.assertEqual([], task_statuses[0]['tags']) self.assertEqual('waiting', task_statuses[0]['state'])
def test_create_task_status_duplicate_task_id(self): """ Tests create_task_status() with a duplicate task id. """ task_id = self.get_random_uuid() queue = 'a_queue' TaskStatusManager.create_task_status(task_id, queue) try: TaskStatusManager.create_task_status(task_id, queue) self.fail( 'Task status with a duplicate task id did not raise an exception' ) except exceptions.DuplicateResource, e: self.assertTrue(task_id in e)