diff --git a/HACKING.rst b/HACKING.rst index dcf71e453774..82a7a08f0c6f 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -11,6 +11,8 @@ Nova Specific Commandments - ``nova.db`` imports are not allowed in ``nova/virt/*`` - [N309] no db session in public API methods (disabled) This enforces a guideline defined in ``nova.openstack.common.db.sqlalchemy.session`` +- [N310] timeutils.utcnow() wrapper must be used instead of direct calls to + datetime.datetime.utcnow() to make it easy to override its return value in tests Creating Unit Tests ------------------- diff --git a/nova/hacking/checks.py b/nova/hacking/checks.py index aee63dde3683..88dcd0a7e664 100644 --- a/nova/hacking/checks.py +++ b/nova/hacking/checks.py @@ -60,7 +60,18 @@ def no_db_session_in_public_api(logical_line, filename): yield (0, "N309: public db api methods may not accept session") +def use_timeutils_utcnow(logical_line): + msg = "N310: timeutils.%s() must be used instead of datetime.%s()" + + datetime_funcs = ['now', 'utcnow'] + for f in datetime_funcs: + pos = logical_line.find('datetime.%s' % f) + if pos != -1: + yield (pos, msg % (f, f)) + + def factory(register): register(import_no_db_in_virt) register(except_python3x_compatible) register(no_db_session_in_public_api) + register(use_timeutils_utcnow) diff --git a/nova/tests/api/openstack/compute/contrib/test_server_usage.py b/nova/tests/api/openstack/compute/contrib/test_server_usage.py index 74758c649ec5..c303b1297d0a 100644 --- a/nova/tests/api/openstack/compute/contrib/test_server_usage.py +++ b/nova/tests/api/openstack/compute/contrib/test_server_usage.py @@ -94,7 +94,7 @@ class ServerUsageTest(test.TestCase): res = self._make_request(url) self.assertEqual(res.status_int, 200) - now = datetime.datetime.utcnow() + now = timeutils.utcnow() timeutils.set_time_override(now) self.assertServerUsage(self._get_server(res.body), launched_at=DATE1, diff --git a/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py b/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py index 8c8242505427..7ab612ebc35c 100644 --- a/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py +++ b/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py @@ -422,7 +422,7 @@ class SimpleTenantUsageControllerTest(test.TestCase): self.compute_api = FakeComputeAPI() self.context = None - now = datetime.datetime.now() + now = timeutils.utcnow() self.baseinst = dict(display_name='foo', launched_at=now - datetime.timedelta(1), terminated_at=now, diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_simple_tenant_usage.py b/nova/tests/api/openstack/compute/plugins/v3/test_simple_tenant_usage.py index badda82d8291..476860754355 100644 --- a/nova/tests/api/openstack/compute/plugins/v3/test_simple_tenant_usage.py +++ b/nova/tests/api/openstack/compute/plugins/v3/test_simple_tenant_usage.py @@ -427,7 +427,7 @@ class SimpleTenantUsageControllerTest(test.TestCase): self.compute_api = FakeComputeAPI() self.context = None - now = datetime.datetime.now() + now = timeutils.utcnow() self.baseinst = dict(display_name='foo', launched_at=now - datetime.timedelta(1), terminated_at=now, diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 571bd78d210b..8db2887f1bf0 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -469,8 +469,8 @@ def stub_instance(id, user_id=None, project_id=None, host=None, power_state=None, nw_cache=None, metadata=None, security_groups=None, root_device_name=None, limit=None, marker=None, - launched_at=datetime.datetime.utcnow(), - terminated_at=datetime.datetime.utcnow(), + launched_at=timeutils.utcnow(), + terminated_at=timeutils.utcnow(), availability_zone=''): if user_id is None: diff --git a/nova/tests/db/test_db_api.py b/nova/tests/db/test_db_api.py index bac3aff4e586..0926d0cb3b1a 100644 --- a/nova/tests/db/test_db_api.py +++ b/nova/tests/db/test_db_api.py @@ -88,7 +88,7 @@ def _quota_reserve(context, project_id): sqlalchemy_api.QUOTA_SYNC_FUNCTIONS[sync_name] = getattr( sqlalchemy_api, sync_name) return db.quota_reserve(context, resources, quotas, deltas, - datetime.datetime.utcnow(), datetime.datetime.utcnow(), + timeutils.utcnow(), timeutils.utcnow(), datetime.timedelta(days=1), project_id) @@ -835,8 +835,7 @@ class ReservationTestCase(test.TestCase, ModelsObjectComparatorMixin): 'project_id': 'project1', 'resource': 'resource', 'delta': 42, - 'expire': datetime.datetime.utcnow() + - datetime.timedelta(days=1), + 'expire': timeutils.utcnow() + datetime.timedelta(days=1), 'usage': {'id': 1}} def test_reservation_create(self): @@ -896,8 +895,8 @@ class ReservationTestCase(test.TestCase, ModelsObjectComparatorMixin): self.ctxt, 'project1')) def test_reservation_expire(self): - self.values['expire'] = datetime.datetime.utcnow() + datetime.\ - timedelta(days=1) + self.values['expire'] = timeutils.utcnow() + datetime.timedelta(days=1) + _quota_reserve(self.ctxt, 'project1') db.reservation_expire(self.ctxt) diff --git a/nova/tests/db/test_migrations.py b/nova/tests/db/test_migrations.py index 425584b3c35f..a6e06a332d5b 100644 --- a/nova/tests/db/test_migrations.py +++ b/nova/tests/db/test_migrations.py @@ -1145,7 +1145,7 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn): # migration 173, add unique constraint to keypairs def _pre_upgrade_173(self, engine): - created_at = [datetime.datetime.now() for x in range(0, 7)] + created_at = [timeutils.utcnow() for x in range(0, 7)] fake_keypairs = [dict(name='key1', user_id='1a', created_at=created_at[0], deleted=0), @@ -1167,7 +1167,7 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn): # is applied to the key_pairs table or not. insert = keypairs.insert() duplicate_keypair = dict(name='key4', user_id='4a', - created_at=datetime.datetime.now(), + created_at=timeutils.utcnow(), deleted=0) insert.execute(duplicate_keypair) # Insert again @@ -1228,12 +1228,12 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn): volume_usage_cache = db_utils.get_table(engine, 'volume_usage_cache') fake_usage = {'volume_id': 'fake_volume_id', 'instance_id': 10, - 'tot_last_refreshed': datetime.datetime.now(), + 'tot_last_refreshed': timeutils.utcnow(), 'tot_reads': 2, 'tot_read_bytes': 3, 'tot_writes': 4, 'tot_write_bytes': 5, - 'curr_last_refreshed': datetime.datetime.now(), + 'curr_last_refreshed': timeutils.utcnow(), 'curr_reads': 6, 'curr_read_bytes': 7, 'curr_writes': 8, diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index 12e80f788738..ff20eccc1c72 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -146,7 +146,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): def _force_reclaim(self): # Make sure that compute manager thinks the instance is # old enough to be expired - the_past = datetime.datetime.utcnow() + datetime.timedelta(hours=1) + the_past = timeutils.utcnow() + datetime.timedelta(hours=1) timeutils.set_time_override(override_time=the_past) ctxt = context.get_admin_context() self.compute._reclaim_queued_deletes(ctxt) diff --git a/nova/tests/objects/test_objects.py b/nova/tests/objects/test_objects.py index 03a27038620b..0e49d4f7753e 100644 --- a/nova/tests/objects/test_objects.py +++ b/nova/tests/objects/test_objects.py @@ -119,7 +119,7 @@ class TestMetaclass(test.TestCase): class TestUtils(test.TestCase): def test_datetime_or_none(self): - naive_dt = datetime.datetime.now() + naive_dt = timeutils.utcnow() dt = timeutils.parse_isotime(timeutils.isotime(naive_dt)) self.assertEqual(utils.datetime_or_none(dt), dt) self.assertEqual(utils.datetime_or_none(dt),