diff --git a/neutron/db/models_v2.py b/neutron/db/models_v2.py index 6863cc3b267..d37e2f9ad62 100644 --- a/neutron/db/models_v2.py +++ b/neutron/db/models_v2.py @@ -56,7 +56,12 @@ class IPAllocation(model_base.BASEV2): network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id", ondelete="CASCADE"), nullable=False, primary_key=True) - revises_on_change = ('port', ) + network_standard_attr = orm.relationship( + 'StandardAttribute', lazy='subquery', viewonly=True, + secondary='networks', uselist=False, + load_on_pending=True) + + revises_on_change = ('port', 'network_standard_attr',) class Route(object): diff --git a/neutron/services/revisions/revision_plugin.py b/neutron/services/revisions/revision_plugin.py index 4a63e9fc36c..619d83ade1b 100644 --- a/neutron/services/revisions/revision_plugin.py +++ b/neutron/services/revisions/revision_plugin.py @@ -47,7 +47,8 @@ class RevisionPlugin(service_base.ServicePluginBase): self._enforce_if_match_constraints(session) # bump revision number for any updated objects in the session for obj in session.dirty: - if isinstance(obj, standard_attr.HasStandardAttributes): + if (session.is_modified(obj) and + isinstance(obj, standard_attr.HasStandardAttributes)): self._bump_obj_revision(session, obj) # see if any created/updated/deleted objects bump the revision diff --git a/neutron/tests/unit/services/revisions/test_revision_plugin.py b/neutron/tests/unit/services/revisions/test_revision_plugin.py index 8ae6315785c..9048d184a2e 100644 --- a/neutron/tests/unit/services/revisions/test_revision_plugin.py +++ b/neutron/tests/unit/services/revisions/test_revision_plugin.py @@ -86,10 +86,17 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): def test_port_name_update_revises(self): with self.port() as port: rev = port['port']['revision_number'] + network = directory.get_plugin().get_network( + self.ctx, port['port']['network_id']) + net_rev = network['revision_number'] new = {'port': {'name': 'seaweed'}} response = self._update('ports', port['port']['id'], new) new_rev = response['port']['revision_number'] self.assertGreater(new_rev, rev) + network = directory.get_plugin().get_network( + self.ctx, port['port']['network_id']) + net_ew_rev = network['revision_number'] + self.assertEqual(net_ew_rev, net_rev) def test_constrained_port_update(self): with self.port() as port: @@ -145,6 +152,9 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): def test_port_ip_update_revises(self): with self.port() as port: rev = port['port']['revision_number'] + network = directory.get_plugin().get_network( + self.ctx, port['port']['network_id']) + net_rev = network['revision_number'] new = {'port': {'fixed_ips': port['port']['fixed_ips']}} # ensure adding an IP allocation updates the port next_ip = str(netaddr.IPAddress( @@ -154,13 +164,23 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): self.assertEqual(2, len(response['port']['fixed_ips'])) new_rev = response['port']['revision_number'] self.assertGreater(new_rev, rev) + network = directory.get_plugin().get_network( + self.ctx, port['port']['network_id']) + new_net_rev = network['revision_number'] + self.assertGreater(new_net_rev, net_rev) + # ensure deleting an IP allocation updates the port rev = new_rev + net_rev = new_net_rev new['port']['fixed_ips'].pop() response = self._update('ports', port['port']['id'], new) self.assertEqual(1, len(response['port']['fixed_ips'])) new_rev = response['port']['revision_number'] self.assertGreater(new_rev, rev) + network = directory.get_plugin().get_network( + self.ctx, port['port']['network_id']) + new_net_rev = network['revision_number'] + self.assertGreater(new_net_rev, net_rev) def test_security_group_rule_ops_bump_security_group(self): s = {'security_group': {'tenant_id': 'some_tenant', 'name': '',