def test_get_schedules(self): timeutils.set_time_override() start_time = timeutils.isotime() timeutils.advance_time_seconds(30) end_time = timeutils.isotime() filter_args = {'next_run_after': start_time, 'next_run_before': end_time} self.client.list_schedules(filter_args=filter_args).AndReturn([]) self.mox.ReplayAll() self.scheduler.get_schedules(start_time, end_time) self.mox.VerifyAll()
def test_get_schedules(self): timeutils.set_time_override() start_time = timeutils.isotime() timeutils.advance_time_seconds(30) end_time = timeutils.isotime() filter_args = { 'next_run_after': start_time, 'next_run_before': end_time } self.client.list_schedules(filter_args=filter_args).AndReturn([]) self.mox.ReplayAll() self.scheduler.get_schedules(start_time, end_time) self.mox.VerifyAll()
def test_create_zero_hour(self): hour = 0 fixture = { "schedule": { "id": unit_utils.SCHEDULE_UUID5, "tenant": unit_utils.TENANT1, "action": "snapshot", "minute": 30, "hour": hour, } } expected = fixture["schedule"] request = unit_utils.get_fake_request(method="POST") actual = self.controller.create(request, fixture)["schedule"] self.assertNotEqual(actual.get("id"), None) self.assertNotEqual(actual.get("created_at"), None) self.assertNotEqual(actual.get("updated_at"), None) now = timeutils.utcnow() if not (now.hour == hour and now.minute < 30): now = now + datetime.timedelta(days=1) expected_next_run = timeutils.isotime(now.replace(hour=hour, minute=30, second=0, microsecond=0)) self.assertEqual(expected_next_run, actual["next_run"]) self.assertEqual(expected["tenant"], actual["tenant"]) self.assertEqual(expected["action"], actual["action"]) self.assertEqual(expected["minute"], actual["minute"]) self.assertEqual(expected["hour"], actual["hour"])
def test_create_with_next_run(self): expected_next_run = timeutils.parse_isotime('1989-01-19T12:00:00Z').\ replace(tzinfo=None) def fake_schedule_to_next_run(_schedule, start_time=None): self.assertEqual(timeutils.utcnow(), start_time) return expected_next_run self.stubs.Set(api_utils, 'schedule_to_next_run', fake_schedule_to_next_run) self._stub_notifications(None, 'qonos.job.create', 'fake-payload', 'INFO') request = unit_utils.get_fake_request(method='POST') fixture = {'job': {'schedule_id': self.schedule_1['id'], 'next_run': timeutils.isotime(self.schedule_1['next_run'])}} job = self.controller.create(request, fixture).get('job') self.assertNotEqual(job, None) self.assertNotEqual(job.get('id'), None) self.assertEqual(job['schedule_id'], self.schedule_1['id']) self.assertEqual(job['tenant'], self.schedule_1['tenant']) self.assertEqual(job['action'], self.schedule_1['action']) self.assertEqual(job['status'], 'QUEUED') self.assertEqual(len(job['metadata']), 0) schedule = db_api.schedule_get_by_id(self.schedule_1['id']) self.assertNotEqual(schedule['next_run'], self.schedule_1['next_run']) self.assertEqual(schedule['next_run'], expected_next_run) self.assertNotEqual(schedule['last_scheduled'], self.schedule_1.get('last_scheduled')) self.assertTrue(schedule.get('last_scheduled'))
def test_create_with_next_run(self): expected_next_run = timeutils.parse_isotime('1989-01-19T12:00:00Z') def fake_schedule_to_next_run(_schedule, start_time=None): self.assertEqual(timeutils.utcnow(), start_time) return expected_next_run self.stubs.Set(api_utils, 'schedule_to_next_run', fake_schedule_to_next_run) self._stub_notifications(None, 'qonos.job.create', 'fake-payload', 'INFO') request = unit_utils.get_fake_request(method='POST') fixture = {'job': {'schedule_id': self.schedule_1['id'], 'next_run': timeutils.isotime(self.schedule_1['next_run'])}} job = self.controller.create(request, fixture).get('job') self.assertNotEqual(job, None) self.assertNotEqual(job.get('id'), None) self.assertEqual(job['schedule_id'], self.schedule_1['id']) self.assertEqual(job['tenant'], self.schedule_1['tenant']) self.assertEqual(job['action'], self.schedule_1['action']) self.assertEqual(job['status'], 'QUEUED') self.assertEqual(len(job['metadata']), 0) schedule = db_api.schedule_get_by_id(self.schedule_1['id']) self.assertNotEqual(schedule['next_run'], self.schedule_1['next_run']) self.assertEqual(schedule['next_run'], expected_next_run) self.assertNotEqual(schedule['last_scheduled'], self.schedule_1.get('last_scheduled')) self.assertTrue(schedule.get('last_scheduled'))
def _run_loop(self, run_once=False): next_run = None current_run = None while self.running: current_run = timeutils.isotime() next_run = time.time() + CONF.scheduler.job_schedule_interval # do work with utils.log_warning_and_dismiss_exception(LOG): self.enqueue_jobs(end_time=current_run) # if shutdown hasn't been requested, do nothing until next run if self.running: seconds = next_run - time.time() if seconds > 0: time.sleep(seconds) else: msg = _('Scheduling of jobs took longer than expected.') LOG.warn(msg) if run_once: break LOG.info(_('Scheduler is shutting down'))
def test_create_zero_hour(self): hour = 0 fixture = {'schedule': { 'id': unit_utils.SCHEDULE_UUID5, 'tenant': unit_utils.TENANT1, 'action': 'snapshot', 'minute': 30, 'hour': hour, }} expected = fixture['schedule'] request = unit_utils.get_fake_request(method='POST') actual = self.controller.create(request, fixture)['schedule'] self.assertNotEqual(actual.get('id'), None) self.assertNotEqual(actual.get('created_at'), None) self.assertNotEqual(actual.get('updated_at'), None) now = timeutils.utcnow() if not (now.hour == hour and now.minute < 30): now = now + datetime.timedelta(days=1) expected_next_run = timeutils.isotime( now.replace(hour=hour, minute=30, second=0, microsecond=0)) self.assertEqual(expected_next_run, actual['next_run']) self.assertEqual(expected['tenant'], actual['tenant']) self.assertEqual(expected['action'], actual['action']) self.assertEqual(expected['minute'], actual['minute']) self.assertEqual(expected['hour'], actual['hour'])
def test_list_with_hard_timeout_filter(self): hard_timeout = timeutils.isotime(self.job_1['hard_timeout']) path = '?hard_timeout=%s' % hard_timeout request = unit_utils.get_fake_request(path=path, method='GET') jobs = self.controller.list(request).get('jobs') self.assertEqual(len(jobs), 1) self.assertEqual(jobs[0]['id'], self.job_1['id'])
def test_get_schedules_no_previous_run(self): end_time = timeutils.isotime() filter_args = {'next_run_before': end_time} self.client.list_schedules(filter_args=filter_args).AndReturn([]) self.mox.ReplayAll() self.scheduler.get_schedules(end_time=end_time) self.mox.VerifyAll()
def test_list_next_run_filtered_before_less_than_after(self): after = self.schedule_3["next_run"] before = timeutils.isotime(after - datetime.timedelta(seconds=1)) path = "?next_run_after=%s&next_run_before=%s" path = path % (after, before) request = unit_utils.get_fake_request(path=path, method="GET") schedules = self.controller.list(request).get("schedules") self.assertEqual(len(schedules), 0)
def test_list_next_run_filtered_before_less_than_after(self): after = self.schedule_3['next_run'] before = timeutils.isotime(after - datetime.timedelta(seconds=1)) path = '?next_run_after=%s&next_run_before=%s' path = path % (after, before) request = unit_utils.get_fake_request(path=path, method='GET') schedules = self.controller.list(request).get('schedules') self.assertEqual(len(schedules), 0)
def serialize_datetimes(data): """Serializes datetimes to strings in the top level values of a dict.""" for (k, v) in data.iteritems(): if isinstance(v, datetime.datetime): data[k] = timeutils.isotime(v) elif isinstance(v, list): for item in v: serialize_datetimes(item) elif isinstance(v, dict): serialize_datetimes(v)
def test_run_loop(self): self.config(job_schedule_interval=5, group='scheduler') timeutils.set_time_override() current_time = timeutils.isotime() called = {'enqueue_jobs': False} def fake(end_time=None): # assert only end_time kwarg is passed self.assertEqual(end_time, current_time) called['enqueue_jobs'] = True self.stubs.Set(self.scheduler, 'enqueue_jobs', fake) fake_sleep = lambda x: None self.stubs.Set(time, 'sleep', fake_sleep) self.scheduler.run(run_once=True) self.assertTrue(called['enqueue_jobs'])
def test_update_tenant(self): new_tenant = "new-tenant-name" def fake_schedule_to_next_run(*args, **kwargs): self.fail("next_run should not be updated") self.stubs.Set(api_utils, "schedule_to_next_run", fake_schedule_to_next_run) request = unit_utils.get_fake_request(method="PUT") update_fixture = {"schedule": {"tenant": new_tenant}} updated = self.controller.update(request, self.schedule_1["id"], update_fixture)["schedule"] self.assertNotEqual(updated.get("created_at"), None) self.assertNotEqual(updated.get("updated_at"), None) self.assertEqual(new_tenant, updated["tenant"]) self.assertEqual(self.schedule_1["action"], updated["action"]) self.assertEqual(self.schedule_1["minute"], updated["minute"]) self.assertEqual(updated["next_run"], timeutils.isotime(self.schedule_1["next_run"]))
def test_update_tenant(self): new_tenant = 'new-tenant-name' def fake_schedule_to_next_run(*args, **kwargs): self.fail('next_run should not be updated') self.stubs.Set(api_utils, 'schedule_to_next_run', fake_schedule_to_next_run) request = unit_utils.get_fake_request(method='PUT') update_fixture = {'schedule': {'tenant': new_tenant}} updated = self.controller.update(request, self.schedule_1['id'], update_fixture)['schedule'] self.assertNotEqual(updated.get('created_at'), None) self.assertNotEqual(updated.get('updated_at'), None) self.assertEqual(new_tenant, updated['tenant']) self.assertEqual(self.schedule_1['action'], updated['action']) self.assertEqual(self.schedule_1['minute'], updated['minute']) self.assertEqual(updated['next_run'], timeutils.isotime(self.schedule_1['next_run']))
def test_schedule_workflow(self): schedules = self.client.list_schedules() self.assertEqual(len(schedules), 0) # create invalid schedule request = {'not a schedule': 'yes'} self.assertRaises(client_exc.BadRequest, self.client.create_schedule, request) # create malformed schedule request = 'not a schedule' self.assertRaises(client_exc.BadRequest, self.client.create_schedule, request) # create schedule with no body self.assertRaises(client_exc.BadRequest, self.client.create_schedule, None) # create schedule request = { 'schedule': { 'tenant': TENANT1, 'action': 'snapshot', 'minute': 30, 'hour': 12, 'metadata': {'instance_id': 'my_instance_1'}, } } schedule = self.client.create_schedule(request) self.assertTrue(schedule['id']) self.assertEqual(schedule['tenant'], TENANT1) self.assertEqual(schedule['action'], 'snapshot') self.assertEqual(schedule['minute'], 30) self.assertEqual(schedule['hour'], 12) self.assertTrue('metadata' in schedule) metadata = schedule['metadata'] self.assertEqual(1, len(metadata)) self.assertEqual(metadata['instance_id'], 'my_instance_1') # Get schedule schedule = self.client.get_schedule(schedule['id']) self.assertTrue(schedule['id']) self.assertEqual(schedule['tenant'], TENANT1) self.assertEqual(schedule['action'], 'snapshot') self.assertEqual(schedule['minute'], 30) self.assertEqual(schedule['hour'], 12) # list schedules schedules = self.client.list_schedules() self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) # list schedules, next_run filters filters = {} filters['next_run_after'] = schedule['next_run'] filters['next_run_before'] = schedule['next_run'] schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) filters['next_run_after'] = schedule['next_run'] after_datetime = timeutils.parse_isotime(schedule['next_run']) before_datetime = (after_datetime - datetime.timedelta(seconds=1)) filters['next_run_before'] = timeutils.isotime(before_datetime) schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 0) # list schedules, next_run_before filters filters = {} filters['next_run_before'] = schedule['next_run'] schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) # list schedules, next_run_after filters filters = {} filters['next_run_after'] = schedule['next_run'] schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) # list schedules, tenant filters filters = {} filters['tenant'] = TENANT1 schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) filters['tenant'] = 'aaaa-bbbb-cccc-dddd' schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 0) # list schedules, metadata filter filter = {} filter['instance_id'] = 'my_instance_1' schedules = self.client.list_schedules(filter_args=filter) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) filters['instance_id'] = 'aaaa-bbbb-cccc-dddd' schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 0) filter = {} filter['instance_name'] = 'aaaa-bbbb-cccc-dddd' schedules = self.client.list_schedules(filter_args=filter) self.assertEqual(len(schedules), 0) # test filter by action filter = {} filter['action'] = 'snapshot' schedules = self.client.list_schedules(filter_args=filter) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) filter['action'] = 'test_action' schedules = self.client.list_schedules(filter_args=filter) self.assertEqual(len(schedules), 0) # update schedule request = {'schedule': {'hour': 14}} updated_schedule = self.client.update_schedule(schedule['id'], request) self.assertEqual(updated_schedule['id'], schedule['id']) self.assertEqual(updated_schedule['tenant'], schedule['tenant']) self.assertEqual(updated_schedule['action'], schedule['action']) self.assertEqual(updated_schedule['minute'], None) self.assertEqual(updated_schedule['month'], None) self.assertEqual(updated_schedule['day_of_week'], None) self.assertEqual(updated_schedule['day_of_month'], None) self.assertEqual(updated_schedule['hour'], request['schedule']['hour']) self.assertNotEqual(updated_schedule['hour'], schedule['hour']) self.assertNotEqual(updated_schedule['next_run'], schedule['next_run']) # update schedule metadata request = {'schedule': {'metadata': {'instance_id': 'my_instance_2', 'retention': '3', }}} schedule = self.client.get_schedule(schedule['id']) updated_schedule = self.client.update_schedule(schedule['id'], request) self.assertEqual(updated_schedule['id'], schedule['id']) self.assertEqual(updated_schedule['tenant'], schedule['tenant']) self.assertEqual(updated_schedule['action'], schedule['action']) self.assertEqual(updated_schedule['hour'], schedule['hour']) self.assertEqual(updated_schedule['minute'], schedule['minute']) self.assertEqual(updated_schedule['month'], schedule['month']) self.assertEqual(updated_schedule['day_of_week'], schedule['day_of_week']) self.assertEqual(updated_schedule['day_of_month'], schedule['day_of_month']) self.assertTrue('metadata' in updated_schedule) metadata = updated_schedule['metadata'] self.assertEqual(2, len(metadata)) self.assertEqual(metadata['instance_id'], 'my_instance_2') self.assertEqual(metadata['retention'], '3') # delete schedule self.client.delete_schedule(schedule['id']) # make sure schedule no longer exists self.assertRaises(client_exc.NotFound, self.client.get_schedule, schedule['id'])
def test_schedule_workflow(self): schedules = self.client.list_schedules() self.assertEqual(len(schedules), 0) # create invalid schedule request = {'not a schedule': 'yes'} self.assertRaises(client_exc.BadRequest, self.client.create_schedule, request) # create malformed schedule request = 'not a schedule' self.assertRaises(client_exc.BadRequest, self.client.create_schedule, request) # create schedule with no body self.assertRaises(client_exc.BadRequest, self.client.create_schedule, None) # create schedule request = { 'schedule': { 'tenant': TENANT1, 'action': 'snapshot', 'minute': 30, 'hour': 12, 'metadata': { 'instance_id': 'my_instance_1' }, } } schedule = self.client.create_schedule(request) self.assertTrue(schedule['id']) self.assertEqual(schedule['tenant'], TENANT1) self.assertEqual(schedule['action'], 'snapshot') self.assertEqual(schedule['minute'], 30) self.assertEqual(schedule['hour'], 12) self.assertTrue('metadata' in schedule) metadata = schedule['metadata'] self.assertEqual(1, len(metadata)) self.assertEqual(metadata['instance_id'], 'my_instance_1') # Get schedule schedule = self.client.get_schedule(schedule['id']) self.assertTrue(schedule['id']) self.assertEqual(schedule['tenant'], TENANT1) self.assertEqual(schedule['action'], 'snapshot') self.assertEqual(schedule['minute'], 30) self.assertEqual(schedule['hour'], 12) # list schedules schedules = self.client.list_schedules() self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) # list schedules, next_run filters filters = {} filters['next_run_after'] = schedule['next_run'] filters['next_run_before'] = schedule['next_run'] schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) filters['next_run_after'] = schedule['next_run'] after_datetime = timeutils.parse_isotime(schedule['next_run']) before_datetime = (after_datetime - datetime.timedelta(seconds=1)) filters['next_run_before'] = timeutils.isotime(before_datetime) schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 0) # list schedules, next_run_before filters filters = {} filters['next_run_before'] = schedule['next_run'] schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) # list schedules, next_run_after filters filters = {} filters['next_run_after'] = schedule['next_run'] schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) # list schedules, tenant filters filters = {} filters['tenant'] = TENANT1 schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) filters['tenant'] = 'aaaa-bbbb-cccc-dddd' schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 0) # list schedules, metadata filter filter = {} filter['instance_id'] = 'my_instance_1' schedules = self.client.list_schedules(filter_args=filter) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) filters['instance_id'] = 'aaaa-bbbb-cccc-dddd' schedules = self.client.list_schedules(filter_args=filters) self.assertEqual(len(schedules), 0) filter = {} filter['instance_name'] = 'aaaa-bbbb-cccc-dddd' schedules = self.client.list_schedules(filter_args=filter) self.assertEqual(len(schedules), 0) # test filter by action filter = {} filter['action'] = 'snapshot' schedules = self.client.list_schedules(filter_args=filter) self.assertEqual(len(schedules), 1) self.assertEqual(schedules[0], schedule) filter['action'] = 'test_action' schedules = self.client.list_schedules(filter_args=filter) self.assertEqual(len(schedules), 0) # update schedule request = {'schedule': {'hour': 14}} updated_schedule = self.client.update_schedule(schedule['id'], request) self.assertEqual(updated_schedule['id'], schedule['id']) self.assertEqual(updated_schedule['tenant'], schedule['tenant']) self.assertEqual(updated_schedule['action'], schedule['action']) self.assertEqual(updated_schedule['minute'], None) self.assertEqual(updated_schedule['month'], None) self.assertEqual(updated_schedule['day_of_week'], None) self.assertEqual(updated_schedule['day_of_month'], None) self.assertEqual(updated_schedule['hour'], request['schedule']['hour']) self.assertNotEqual(updated_schedule['hour'], schedule['hour']) self.assertNotEqual(updated_schedule['next_run'], schedule['next_run']) # update schedule metadata request = { 'schedule': { 'metadata': { 'instance_id': 'my_instance_2', 'retention': '3', } } } schedule = self.client.get_schedule(schedule['id']) updated_schedule = self.client.update_schedule(schedule['id'], request) self.assertEqual(updated_schedule['id'], schedule['id']) self.assertEqual(updated_schedule['tenant'], schedule['tenant']) self.assertEqual(updated_schedule['action'], schedule['action']) self.assertEqual(updated_schedule['hour'], schedule['hour']) self.assertEqual(updated_schedule['minute'], schedule['minute']) self.assertEqual(updated_schedule['month'], schedule['month']) self.assertEqual(updated_schedule['day_of_week'], schedule['day_of_week']) self.assertEqual(updated_schedule['day_of_month'], schedule['day_of_month']) self.assertTrue('metadata' in updated_schedule) metadata = updated_schedule['metadata'] self.assertEqual(2, len(metadata)) self.assertEqual(metadata['instance_id'], 'my_instance_2') self.assertEqual(metadata['retention'], '3') # delete schedule self.client.delete_schedule(schedule['id']) # make sure schedule no longer exists self.assertRaises(client_exc.NotFound, self.client.get_schedule, schedule['id'])