def _search_by_name(word, cursor_str, limit): """Returns TaskResultSummary in -created_ts order containing the word.""" cursor = search.Cursor(web_safe_string=cursor_str, per_result=True) index = search.Index(name='requests') def item_to_id(item): for field in item.fields: if field.name == 'id': return field.value # The code is structured to handle incomplete entities but still return # 'limit' items. This is done by fetching a few more entities than necessary, # then keeping track of the cursor per item so the right cursor can be # returned. opts = search.QueryOptions(limit=limit + 5, cursor=cursor) results = index.search(search.Query('name:%s' % word, options=opts)) result_summary_keys = [] cursors = [] for item in results.results: value = item_to_id(item) if value: result_summary_keys.append( task_pack.unpack_result_summary_key(value)) cursors.append(item.cursor) # Handle None result value. See make_request() for details about how this can # happen. tasks = [] cursor = None for task, c in zip(ndb.get_multi(result_summary_keys), cursors): if task: cursor = c tasks.append(task) if len(tasks) == limit: # Drop the rest. break else: if len(cursors) == limit + 5: while len(tasks) < limit: # Go into the slow path, seems like we got a lot of corrupted items. opts = search.QueryOptions(limit=limit - len(tasks) + 5, cursor=cursor) results = index.search( search.Query('name:%s' % word, options=opts)) if not results.results: # Nothing else. cursor = None break for item in results.results: value = item_to_id(item) if value: cursor = item.cursor task = task_pack.unpack_result_summary_key(value).get() if task: tasks.append(task) if len(tasks) == limit: break cursor_str = cursor.web_safe_string if cursor else None return tasks, cursor_str
def search_by_name(word, cursor_str, limit): """Returns TaskResultSummary in -created_ts order containing the word.""" cursor = search.Cursor(web_safe_string=cursor_str, per_result=True) index = search.Index(name='requests') def item_to_id(item): for field in item.fields: if field.name == 'id': return field.value # The code is structured to handle incomplete entities but still return # 'limit' items. This is done by fetching a few more entities than necessary, # then keeping track of the cursor per item so the right cursor can be # returned. opts = search.QueryOptions(limit=limit + 5, cursor=cursor) results = index.search(search.Query('name:%s' % word, options=opts)) result_summary_keys = [] cursors = [] for item in results.results: value = item_to_id(item) if value: result_summary_keys.append(task_pack.unpack_result_summary_key(value)) cursors.append(item.cursor) # Handle None result value. See make_request() for details about how this can # happen. tasks = [] cursor = None for task, c in zip(ndb.get_multi(result_summary_keys), cursors): if task: cursor = c tasks.append(task) if len(tasks) == limit: # Drop the rest. break else: if len(cursors) == limit + 5: while len(tasks) < limit: # Go into the slow path, seems like we got a lot of corrupted items. opts = search.QueryOptions(limit=limit-len(tasks) + 5, cursor=cursor) results = index.search(search.Query('name:%s' % word, options=opts)) if not results.results: # Nothing else. cursor = None break for item in results.results: value = item_to_id(item) if value: cursor = item.cursor task = task_pack.unpack_result_summary_key(value).get() if task: tasks.append(task) if len(tasks) == limit: break cursor_str = cursor.web_safe_string if cursor else None return tasks, cursor_str
def get_request_and_result(self, task_id): """Retrieves the TaskRequest for 'task_id' and enforces the ACL. Supports both TaskResultSummary (ends with 0) or TaskRunResult (ends with 1 or 2). Returns: tuple(TaskRequest, result): result can be either for a TaskRunResult or a TaskResultSummay. """ try: key = task_pack.unpack_result_summary_key(task_id) request_key = task_pack.result_summary_key_to_request_key(key) except ValueError: try: key = task_pack.unpack_run_result_key(task_id) request_key = task_pack.result_summary_key_to_request_key( task_pack.run_result_key_to_result_summary_key(key)) except ValueError: self.abort(404, 'Invalid key format.') request, result = ndb.get_multi((request_key, key)) if not request or not result: self.abort(404, '%s not found.' % key.id()) if not request.has_access: self.abort(403, '%s is not accessible.' % key.id()) return request, result
def cancel(self, request): """Cancels a task. If a bot was running the task, the bot will forcibly cancel the task. """ logging.info('%s', request) summary_key = task_pack.unpack_result_summary_key(request.task_id) ok, was_running = task_scheduler.cancel_task(summary_key) return swarming_rpcs.CancelResponse(ok=ok, was_running=was_running)
def post(self): request = self.parse_body() task_id = request.get('task_id') summary_key = task_pack.unpack_result_summary_key(task_id) ok, was_running = task_scheduler.cancel_task(summary_key) out = { 'ok': ok, 'was_running': was_running, } self.send_response(out)
def post(self): key_id = self.request.get('task_id', '') try: key = task_pack.unpack_result_summary_key(key_id) except ValueError: self.abort_with_error(400, error='Invalid key') redirect_to = self.request.get('redirect_to', '') task_scheduler.cancel_task(key) if redirect_to == 'listing': self.redirect('/user/tasks') else: self.redirect('/user/task/%s' % key_id)
def post(self): key_id = self.request.get("task_id", "") try: key = task_pack.unpack_result_summary_key(key_id) except ValueError: self.abort_with_error(400, error="Invalid key") redirect_to = self.request.get("redirect_to", "") task_scheduler.cancel_task(key) if redirect_to == "listing": self.redirect("/user/tasks") else: self.redirect("/user/task/%s" % key_id)
def test_unpack_result_summary_key(self): actual = task_pack.unpack_result_summary_key('bb80210') expected = ndb.Key('TaskRequest', 0x7fffffffff447fde, 'TaskResultSummary', 1) self.assertEqual(expected, actual) with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('0') with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('g') with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('bb80201')
def get_result_key(task_id): """Provides the key corresponding to a task ID.""" key = None summary_key = None try: key = task_pack.unpack_result_summary_key(task_id) summary_key = key except ValueError: try: key = task_pack.unpack_run_result_key(task_id) summary_key = task_pack.run_result_key_to_result_summary_key(key) except ValueError: raise endpoints.BadRequestException( 'Task ID %s produces an invalid key.' % task_id) return key, summary_key
def get_result_key(self, task_id): # TODO(maruel): Users can only request their own task. Privileged users can # request any task. key = None summary_key = None try: key = task_pack.unpack_result_summary_key(task_id) summary_key = key except ValueError: try: key = task_pack.unpack_run_result_key(task_id) summary_key = task_pack.run_result_key_to_result_summary_key(key) except ValueError: self.abort_with_error(400, error='Invalid key') return key, summary_key
def test_unpack_result_summary_key(self): # New style key. actual = task_pack.unpack_result_summary_key('bb80210') expected = ndb.Key('TaskRequest', 0x7fffffffff447fde, 'TaskResultSummary', 1) self.assertEqual(expected, actual) # Old style key. actual = task_pack.unpack_result_summary_key('bb80200') expected = ndb.Key('TaskRequestShard', '6f4236', 'TaskRequest', 196608512, 'TaskResultSummary', 1) self.assertEqual(expected, actual) with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('0') with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('g') with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('bb80201')
def test_unpack_result_summary_key(self): # New style key. actual = task_pack.unpack_result_summary_key('bb80210') expected = ndb.Key( 'TaskRequest', 0x7fffffffff447fde, 'TaskResultSummary', 1) self.assertEqual(expected, actual) # Old style key. actual = task_pack.unpack_result_summary_key('bb80200') expected = ndb.Key( 'TaskRequestShard', '6f4236', 'TaskRequest', 196608512, 'TaskResultSummary', 1) self.assertEqual(expected, actual) with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('0') with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('g') with self.assertRaises(ValueError): task_pack.unpack_result_summary_key('bb80201')
def handle_termination_task(machine_lease): """Checks the state of the termination task, releasing the lease if completed. Args: machine_lease: MachineLease instance. """ assert machine_lease.termination_task task_result_summary = task_pack.unpack_result_summary_key( machine_lease.termination_task).get() if task_result_summary.state == task_result.State.COMPLETED: # There is a race condition where the bot reports the termination task as # completed but hasn't exited yet. The last thing it does before exiting # is post a bot_shutdown event. Check for the presence of a bot_shutdown # event which occurred after the termination task was completed. shutdown_ts = last_shutdown_ts(machine_lease.hostname) if not shutdown_ts or shutdown_ts < task_result_summary.completed_ts: logging.info( 'Machine terminated but not yet shut down:\nKey: %s', machine_lease.key, ) return response = machine_provider.release_machine( machine_lease.client_request_id) if response.get('error'): error = machine_provider.LeaseReleaseRequestError.lookup_by_name( response['error']) if error not in ( machine_provider.LeaseReleaseRequestError. ALREADY_RECLAIMED, machine_provider.LeaseReleaseRequestError.NOT_FOUND, ): logging.error( 'Lease release failed\nKey: %s\nRequest ID: %s\nError: %s', machine_lease.key, response['client_request_id'], response['error'], ) return logging.info('MachineLease released: %s', machine_lease.key) clear_lease_request(machine_lease.key, machine_lease.client_request_id) bot_management.get_info_key(machine_lease.hostname).delete()
def post(self, task_id): try: key = task_pack.unpack_result_summary_key(task_id) request_key = task_pack.result_summary_key_to_request_key(key) except ValueError: try: key = task_pack.unpack_run_result_key(task_id) request_key = task_pack.result_summary_key_to_request_key( task_pack.run_result_key_to_result_summary_key(key)) except (NotImplementedError, ValueError): self.abort(404, 'Invalid key format.') # Retrying a task is essentially reusing the same task request as the # original one, but with new parameters. original_request = request_key.get() if not original_request: self.abort(404, 'Invalid request key.') new_request = task_request.make_request_clone(original_request) result_summary = task_scheduler.schedule_request(new_request) self.redirect('/user/task/%s' % result_summary.task_id)
def handle_termination_task(machine_lease): """Checks the state of the termination task, releasing the lease if completed. Args: machine_lease: MachineLease instance. """ assert machine_lease.termination_task task_result_summary = task_pack.unpack_result_summary_key( machine_lease.termination_task).get() if task_result_summary.state in task_result.State.STATES_EXCEPTIONAL: logging.info( 'Termination failed:\nKey: %s\nHostname: %s\nTask ID: %s\nState: %s', machine_lease.key, machine_lease.hostname, machine_lease.termination_task, task_result.State.to_string(task_result_summary.state), ) clear_termination_task(machine_lease.key, machine_lease.termination_task) return if task_result_summary.state == task_result.State.COMPLETED: # There is a race condition where the bot reports the termination task as # completed but hasn't exited yet. The last thing it does before exiting # is post a bot_shutdown event. Check for the presence of a bot_shutdown # event which occurred after the termination task was completed. shutdown_ts = last_shutdown_ts(machine_lease.bot_id) if not shutdown_ts or shutdown_ts < task_result_summary.completed_ts: logging.info( 'Machine terminated but not yet shut down:\nKey: %s\nHostname: %s', machine_lease.key, machine_lease.hostname, ) return if release(machine_lease): cleanup_bot(machine_lease)
def get(self, task_id): try: key = task_pack.unpack_result_summary_key(task_id) request_key = task_pack.result_summary_key_to_request_key(key) except ValueError: try: key = task_pack.unpack_run_result_key(task_id) request_key = task_pack.result_summary_key_to_request_key( task_pack.run_result_key_to_result_summary_key(key)) except (NotImplementedError, ValueError): self.abort(404, 'Invalid key format.') # 'result' can be either a TaskRunResult or TaskResultSummary. result_future = key.get_async() request_future = request_key.get_async() result = result_future.get_result() if not result: self.abort(404, 'Invalid key.') if not acl.is_privileged_user(): self.abort(403, 'Implement access control based on the user') request = request_future.get_result() parent_task_future = None if request.parent_task_id: parent_key = task_pack.unpack_run_result_key(request.parent_task_id) parent_task_future = parent_key.get_async() children_tasks_futures = [ task_pack.unpack_result_summary_key(c).get_async() for c in result.children_task_ids ] bot_id = result.bot_id following_task_future = None previous_task_future = None if result.started_ts: # Use a shortcut name because it becomes unwieldy otherwise. cls = task_result.TaskRunResult # Note that the links will be to the TaskRunResult, not to # TaskResultSummary. following_task_future = cls.query( cls.bot_id == bot_id, cls.started_ts > result.started_ts, ).order(cls.started_ts).get_async() previous_task_future = cls.query( cls.bot_id == bot_id, cls.started_ts < result.started_ts, ).order(-cls.started_ts).get_async() bot_future = ( bot_management.get_info_key(bot_id).get_async() if bot_id else None) following_task = None if following_task_future: following_task = following_task_future.get_result() previous_task = None if previous_task_future: previous_task = previous_task_future.get_result() parent_task = None if parent_task_future: parent_task = parent_task_future.get_result() children_tasks = [c.get_result() for c in children_tasks_futures] params = { 'bot': bot_future.get_result() if bot_future else None, 'children_tasks': children_tasks, 'is_admin': acl.is_admin(), 'is_gae_admin': users.is_current_user_admin(), 'is_privileged_user': acl.is_privileged_user(), 'following_task': following_task, 'full_appid': os.environ['APPLICATION_ID'], 'host_url': self.request.host_url, 'is_running': result.state == task_result.State.RUNNING, 'now': utils.utcnow(), 'parent_task': parent_task, 'previous_task': previous_task, 'request': request, 'task': result, 'xsrf_token': self.generate_xsrf_token(), } self.response.write(template.render('swarming/user_task.html', params))
def cancel(self, request): """Cancels a task and indicate success.""" summary_key = task_pack.unpack_result_summary_key(request.task_id) ok, was_running = task_scheduler.cancel_task(summary_key) return swarming_rpcs.CancelResponse(ok=ok, was_running=was_running)
def get(self, task_id): try: key = task_pack.unpack_result_summary_key(task_id) request_key = task_pack.result_summary_key_to_request_key(key) except ValueError: try: key = task_pack.unpack_run_result_key(task_id) request_key = task_pack.result_summary_key_to_request_key( task_pack.run_result_key_to_result_summary_key(key) ) except (NotImplementedError, ValueError): self.abort(404, "Invalid key format.") # 'result' can be either a TaskRunResult or TaskResultSummary. result_future = key.get_async() request_future = request_key.get_async() result = result_future.get_result() if not result: self.abort(404, "Invalid key.") if not acl.is_privileged_user(): self.abort(403, "Implement access control based on the user") request = request_future.get_result() parent_task_future = None if request.parent_task_id: parent_key = task_pack.unpack_run_result_key(request.parent_task_id) parent_task_future = parent_key.get_async() children_tasks_futures = [task_pack.unpack_result_summary_key(c).get_async() for c in result.children_task_ids] bot_id = result.bot_id following_task_future = None previous_task_future = None if result.started_ts: # Use a shortcut name because it becomes unwieldy otherwise. cls = task_result.TaskRunResult # Note that the links will be to the TaskRunResult, not to # TaskResultSummary. following_task_future = ( cls.query(cls.bot_id == bot_id, cls.started_ts > result.started_ts).order(cls.started_ts).get_async() ) previous_task_future = ( cls.query(cls.bot_id == bot_id, cls.started_ts < result.started_ts).order(-cls.started_ts).get_async() ) bot_future = bot_management.get_info_key(bot_id).get_async() if bot_id else None following_task = None if following_task_future: following_task = following_task_future.get_result() previous_task = None if previous_task_future: previous_task = previous_task_future.get_result() parent_task = None if parent_task_future: parent_task = parent_task_future.get_result() children_tasks = [c.get_result() for c in children_tasks_futures] params = { "bot": bot_future.get_result() if bot_future else None, "children_tasks": children_tasks, "is_admin": acl.is_admin(), "is_gae_admin": users.is_current_user_admin(), "is_privileged_user": acl.is_privileged_user(), "following_task": following_task, "full_appid": os.environ["APPLICATION_ID"], "host_url": self.request.host_url, "is_running": result.state == task_result.State.RUNNING, "now": utils.utcnow(), "parent_task": parent_task, "previous_task": previous_task, "request": request, "task": result, "xsrf_token": self.generate_xsrf_token(), } self.response.write(template.render("swarming/user_task.html", params))
def _validate_task_summary_id(_prop, value): """Validates a task_id looks valid without fetching the entity.""" if not value: return None task_pack.unpack_result_summary_key(value) return value
def _gen_two_tasks(self): # first request now = datetime.datetime(2010, 1, 2, 3, 4, 5) str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) self.mock_now(now) self.mock(random, 'getrandbits', lambda _: 0x66) _, first_id = self.client_create_task_raw( name='first', tags=['project:yay', 'commit:post', 'os:Win'], properties=dict(idempotent=True)) self.set_as_bot() self.bot_run_task() # second request self.set_as_user() self.mock(random, 'getrandbits', lambda _: 0x88) now_60 = self.mock_now(now, 60) str_now_60 = unicode(now_60.strftime(self.DATETIME_NO_MICRO)) self.client_create_task_raw( name='second', user='******', tags=['project:yay', 'commit:pre', 'os:Win'], properties=dict(idempotent=True)) # Hack the datastore so MODIFIED_TS returns in backward order compared to # CREATED_TS. now_120 = self.mock_now(now, 120) str_now_120 = unicode(now_120.strftime(self.DATETIME_NO_MICRO)) entity = task_pack.unpack_result_summary_key(first_id).get() entity.modified_ts = now_120 entity.put() second = { u'bot_dimensions': [ {u'key': u'id', u'value': [u'bot1']}, {u'key': u'os', u'value': [u'Amiga']}, ], u'bot_id': u'bot1', u'bot_version': self.bot_version, u'cost_saved_usd': 0.1, u'created_ts': str_now_60, u'completed_ts': str_now, u'deduped_from': u'5cee488006611', u'duration': 0.1, u'exit_code': u'0', u'failure': False, u'internal_failure': False, u'modified_ts': str_now_60, u'name': u'second', u'server_versions': [u'v1a'], u'started_ts': str_now, u'state': u'COMPLETED', u'tags': [ u'commit:pre', u'os:Amiga', u'os:Win', u'priority:10', u'project:yay', u'user:jack@localhost', ], u'task_id': u'5cfcee8008810', u'try_number': u'0', u'user': u'jack@localhost', } first = { u'bot_dimensions': [ {u'key': u'id', u'value': [u'bot1']}, {u'key': u'os', u'value': [u'Amiga']}, ], u'bot_id': u'bot1', u'bot_version': self.bot_version, u'costs_usd': [0.1], u'created_ts': str_now, u'completed_ts': str_now, u'duration': 0.1, u'exit_code': u'0', u'failure': False, u'internal_failure': False, u'modified_ts': str_now_120, u'name': u'first', u'properties_hash': u'8771754ee465a689f19c87f2d21ea0d9b8dd4f64', u'server_versions': [u'v1a'], u'started_ts': str_now, u'state': u'COMPLETED', u'tags': [ u'commit:post', u'os:Amiga', u'os:Win', u'priority:10', u'project:yay', u'user:joe@localhost', ], u'task_id': u'5cee488006610', u'try_number': u'1', u'user': u'joe@localhost' } start = ( utils.datetime_to_timestamp(now - datetime.timedelta(days=1)) / 1000000.) end = ( utils.datetime_to_timestamp(now + datetime.timedelta(days=1)) / 1000000.) self.set_as_privileged_user() return first, second, str_now_120, start, end
def get(self, task_id): request, result = self.get_request_and_result(task_id) parent_task_future = None if request.parent_task_id: parent_key = task_pack.unpack_run_result_key(request.parent_task_id) parent_task_future = parent_key.get_async() children_tasks_futures = [ task_pack.unpack_result_summary_key(c).get_async() for c in result.children_task_ids ] bot_id = result.bot_id following_task_future = None previous_task_future = None if result.started_ts: # Use a shortcut name because it becomes unwieldy otherwise. cls = task_result.TaskRunResult # Note that the links will be to the TaskRunResult, not to # TaskResultSummary. following_task_future = cls.query( cls.bot_id == bot_id, cls.started_ts > result.started_ts, ).order(cls.started_ts).get_async() previous_task_future = cls.query( cls.bot_id == bot_id, cls.started_ts < result.started_ts, ).order(-cls.started_ts).get_async() bot_future = ( bot_management.get_info_key(bot_id).get_async() if bot_id else None) following_task = None if following_task_future: following_task = following_task_future.get_result() previous_task = None if previous_task_future: previous_task = previous_task_future.get_result() parent_task = None if parent_task_future: parent_task = parent_task_future.get_result() children_tasks = [c.get_result() for c in children_tasks_futures] cipd = None if request.properties.cipd_input: cipd = { 'server': request.properties.cipd_input.server, 'client_package': request.properties.cipd_input.client_package, 'packages': self.packages_grouped_by_path( request.properties.cipd_input.packages), } cipd_pins = None if result.cipd_pins: cipd_pins = { 'client_package': result.cipd_pins.client_package, 'packages': self.packages_grouped_by_path(result.cipd_pins.packages), } params = { 'bot': bot_future.get_result() if bot_future else None, 'children_tasks': children_tasks, 'cipd': cipd, 'cipd_pins': cipd_pins, 'is_admin': acl.is_admin(), 'is_gae_admin': users.is_current_user_admin(), 'is_privileged_user': acl.is_privileged_user(), 'following_task': following_task, 'full_appid': os.environ['APPLICATION_ID'], 'host_url': self.request.host_url, 'is_running': result.state == task_result.State.RUNNING, 'parent_task': parent_task, 'previous_task': previous_task, 'request': request, 'task': result, 'try_link': '/task?id=%s' % task_id, 'xsrf_token': self.generate_xsrf_token(), } self.response.write(template.render('swarming/user_task.html', params))
def _gen_two_tasks(self): # first request now = datetime.datetime(2010, 1, 2, 3, 4, 5) str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) self.mock_now(now) self.mock(random, 'getrandbits', lambda _: 0x66) _, first_id = self.client_create_task_raw( name='first', tags=['project:yay', 'commit:post', 'os:Win'], properties=dict(idempotent=True)) self.set_as_bot() self.bot_run_task() # second request self.set_as_user() self.mock(random, 'getrandbits', lambda _: 0x88) now_60 = self.mock_now(now, 60) str_now_60 = unicode(now_60.strftime(self.DATETIME_NO_MICRO)) self.client_create_task_raw( name='second', user='******', tags=['project:yay', 'commit:pre', 'os:Win'], properties=dict(idempotent=True)) # Hack the datastore so MODIFIED_TS returns in backward order compared to # CREATED_TS. now_120 = self.mock_now(now, 120) str_now_120 = unicode(now_120.strftime(self.DATETIME_NO_MICRO)) entity = task_pack.unpack_result_summary_key(first_id).get() entity.modified_ts = now_120 entity.put() properties_hash = entity.properties_hash.encode('hex') second = { u'bot_dimensions': [ {u'key': u'id', u'value': [u'bot1']}, {u'key': u'os', u'value': [u'Amiga']}, {u'key': u'pool', u'value': [u'default']}, ], u'bot_id': u'bot1', u'bot_version': self.bot_version, u'cost_saved_usd': 0.1, u'created_ts': str_now_60, u'completed_ts': str_now, u'deduped_from': u'5cee488006611', u'duration': 0.1, u'exit_code': u'0', u'failure': False, u'internal_failure': False, u'modified_ts': str_now_60, u'name': u'second', u'server_versions': [u'v1a'], u'started_ts': str_now, u'state': u'COMPLETED', u'tags': [ u'commit:pre', u'os:Amiga', u'os:Win', u'pool:default', u'priority:10', u'project:yay', u'user:jack@localhost', ], u'task_id': u'5cfcee8008810', u'try_number': u'0', u'user': u'jack@localhost', } first = { u'bot_dimensions': [ {u'key': u'id', u'value': [u'bot1']}, {u'key': u'os', u'value': [u'Amiga']}, {u'key': u'pool', u'value': [u'default']}, ], u'bot_id': u'bot1', u'bot_version': self.bot_version, u'costs_usd': [0.1], u'created_ts': str_now, u'completed_ts': str_now, u'duration': 0.1, u'exit_code': u'0', u'failure': False, u'internal_failure': False, u'performance_stats': { u'bot_overhead': 0.1, u'isolated_download': { u'duration': 1.0, u'initial_number_items': u'10', u'initial_size': u'100000', u'items_cold': [20], u'items_hot': [30], }, u'isolated_upload': { u'duration': 2.0, u'items_cold': [40], u'items_hot': [50], }, }, u'modified_ts': str_now_120, u'name': u'first', u'properties_hash': unicode(properties_hash), u'server_versions': [u'v1a'], u'started_ts': str_now, u'state': u'COMPLETED', u'tags': [ u'commit:post', u'os:Amiga', u'os:Win', u'pool:default', u'priority:10', u'project:yay', u'user:joe@localhost', ], u'task_id': u'5cee488006610', u'try_number': u'1', u'user': u'joe@localhost' } start = ( utils.datetime_to_timestamp(now - datetime.timedelta(days=1)) / 1000000.) end = ( utils.datetime_to_timestamp(now + datetime.timedelta(days=1)) / 1000000.) self.set_as_privileged_user() return first, second, str_now_120, start, end