From 9cac6bd92cf35d739491b38778aceeb90a5a598f Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Thu, 22 Sep 2016 17:52:25 -0700 Subject: [PATCH] Add missing revision number altercations This adds revises_on_change for the following models and API tests to ensure the correct behavior: * port security (network and port) * DNS domain (network and port) * extra dhcp opts (port) * extra routes (router) * subnet service type (subnet) Additionally, it configures the DNS extension to be loaded in the gate since the extension is enabled for tempest. Closes-Bug: #1627649 Change-Id: Ifa969c8c2582f8f41d42df07652f259781a36bb5 (cherry picked from commit 971cf85034a1f94efec27742ff43edb7e664dc98) --- devstack/lib/dns | 6 + devstack/plugin.sh | 7 ++ neutron/db/dns_db.py | 3 + neutron/db/extra_dhcp_opt/models.py | 1 + neutron/db/extraroute_db.py | 1 + neutron/db/models/allowed_address_pair.py | 1 + neutron/db/models/subnet_service_type.py | 1 + neutron/db/port_security/models.py | 2 + neutron/tests/contrib/gate_hook.sh | 1 + neutron/tests/contrib/hooks/dns | 1 + neutron/tests/tempest/api/test_revisions.py | 115 ++++++++++++++++++++ 11 files changed, 139 insertions(+) create mode 100644 devstack/lib/dns create mode 100644 neutron/tests/contrib/hooks/dns diff --git a/devstack/lib/dns b/devstack/lib/dns new file mode 100644 index 00000000000..ff79085f7f7 --- /dev/null +++ b/devstack/lib/dns @@ -0,0 +1,6 @@ +function configure_dns_extension { + enable_ml2_extension_driver "dns" +} +function post_config_dns_extension { + iniset $NEUTRON_CONF DEFAULT dns_domain openstackgate.local +} diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 1943d9f0ff5..7791c624149 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -1,5 +1,6 @@ LIBDIR=$DEST/neutron/devstack/lib +source $LIBDIR/dns source $LIBDIR/flavors source $LIBDIR/l2_agent source $LIBDIR/l2_agent_sriovnicswitch @@ -26,6 +27,9 @@ if [[ "$1" == "stack" ]]; then if is_service_enabled q-trunk; then configure_trunk_extension fi + if is_service_enabled q-dns; then + configure_dns_extension + fi if [[ "$Q_AGENT" == "openvswitch" ]] && \ [[ "$Q_BUILD_OVS_FROM_GIT" == "True" ]]; then remove_ovs_packages @@ -34,6 +38,9 @@ if [[ "$1" == "stack" ]]; then fi ;; post-config) + if is_service_enabled q-dns; then + post_config_dns_extension + fi if is_service_enabled q-agt; then configure_l2_agent fi diff --git a/neutron/db/dns_db.py b/neutron/db/dns_db.py index 09fe11bcabc..ddca77f3877 100644 --- a/neutron/db/dns_db.py +++ b/neutron/db/dns_db.py @@ -48,6 +48,7 @@ class NetworkDNSDomain(model_base.BASEV2): lazy='joined', uselist=False, cascade='delete')) + revises_on_change = ('network', ) class FloatingIPDNS(model_base.BASEV2): @@ -75,6 +76,7 @@ class FloatingIPDNS(model_base.BASEV2): lazy='joined', uselist=False, cascade='delete')) + revises_on_change = ('floatingip', ) class PortDNS(model_base.BASEV2): @@ -102,6 +104,7 @@ class PortDNS(model_base.BASEV2): lazy='joined', uselist=False, cascade='delete')) + revises_on_change = ('port', ) class DNSActionsData(object): diff --git a/neutron/db/extra_dhcp_opt/models.py b/neutron/db/extra_dhcp_opt/models.py index 1e5b96a1733..86ce0387db7 100644 --- a/neutron/db/extra_dhcp_opt/models.py +++ b/neutron/db/extra_dhcp_opt/models.py @@ -43,3 +43,4 @@ class ExtraDhcpOpt(model_base.BASEV2, model_base.HasId): ports = orm.relationship( models_v2.Port, backref=orm.backref("dhcp_opts", lazy='joined', cascade='delete')) + revises_on_change = ('ports', ) diff --git a/neutron/db/extraroute_db.py b/neutron/db/extraroute_db.py index 019ebddbf71..8f9b29f5fc4 100644 --- a/neutron/db/extraroute_db.py +++ b/neutron/db/extraroute_db.py @@ -50,6 +50,7 @@ class RouterRoute(model_base.BASEV2, models_v2.Route): backref=orm.backref("route_list", lazy='joined', cascade='delete')) + revises_on_change = ('router', ) class ExtraRoute_dbonly_mixin(l3_db.L3_NAT_dbonly_mixin): diff --git a/neutron/db/models/allowed_address_pair.py b/neutron/db/models/allowed_address_pair.py index 37d170361cd..832fb8904fa 100644 --- a/neutron/db/models/allowed_address_pair.py +++ b/neutron/db/models/allowed_address_pair.py @@ -28,3 +28,4 @@ class AllowedAddressPair(model_base.BASEV2): models_v2.Port, backref=orm.backref("allowed_address_pairs", lazy="joined", cascade="delete")) + revises_on_change = ('port', ) diff --git a/neutron/db/models/subnet_service_type.py b/neutron/db/models/subnet_service_type.py index 947f4312c7a..9ff0c5cec41 100644 --- a/neutron/db/models/subnet_service_type.py +++ b/neutron/db/models/subnet_service_type.py @@ -40,3 +40,4 @@ class SubnetServiceType(model_base.BASEV2): sa.PrimaryKeyConstraint('subnet_id', 'service_type'), model_base.BASEV2.__table_args__ ) + revises_on_change = ('subnet', ) diff --git a/neutron/db/port_security/models.py b/neutron/db/port_security/models.py index 0d2144389ca..99b1a749bdd 100644 --- a/neutron/db/port_security/models.py +++ b/neutron/db/port_security/models.py @@ -29,6 +29,7 @@ class PortSecurityBinding(model_base.BASEV2): models_v2.Port, backref=orm.backref("port_security", uselist=False, cascade='delete', lazy='joined')) + revises_on_change = ('port',) class NetworkSecurityBinding(model_base.BASEV2): @@ -44,3 +45,4 @@ class NetworkSecurityBinding(model_base.BASEV2): models_v2.Network, backref=orm.backref("port_security", uselist=False, cascade='delete', lazy='joined')) + revises_on_change = ('network',) diff --git a/neutron/tests/contrib/gate_hook.sh b/neutron/tests/contrib/gate_hook.sh index 52e51ecb711..455a98a6e07 100644 --- a/neutron/tests/contrib/gate_hook.sh +++ b/neutron/tests/contrib/gate_hook.sh @@ -65,6 +65,7 @@ case $VENV in # NOTE(ihrachys): note the order of hook post-* sections is significant: [quotas] hook should # go before other hooks modifying [DEFAULT]. See LP#1583214 for details. load_conf_hook quotas + load_rc_hook dns load_rc_hook qos load_rc_hook trunk load_conf_hook osprofiler diff --git a/neutron/tests/contrib/hooks/dns b/neutron/tests/contrib/hooks/dns new file mode 100644 index 00000000000..6597790ccd6 --- /dev/null +++ b/neutron/tests/contrib/hooks/dns @@ -0,0 +1 @@ +enable_service q-dns diff --git a/neutron/tests/tempest/api/test_revisions.py b/neutron/tests/tempest/api/test_revisions.py index 2d5b965d147..78fcea4093a 100644 --- a/neutron/tests/tempest/api/test_revisions.py +++ b/neutron/tests/tempest/api/test_revisions.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import netaddr + from tempest import test from neutron.tests.tempest.api import base @@ -113,6 +115,119 @@ class TestRevisions(base.BaseAdminNetworkTest, bsg.BaseSecGroupTest): self.assertGreater(updated2['security_group']['revision_number'], updated['security_group']['revision_number']) + @test.idempotent_id('db70c285-0365-4fac-9f55-2a0ad8cf55a8') + @test.requires_ext(extension="allowed-address-pairs", service="network") + def test_update_allowed_address_pairs_bumps_revision(self): + net = self.create_network() + port = self.create_port(net) + updated = self.client.update_port( + port['id'], allowed_address_pairs=[{'ip_address': '1.1.1.1/32'}]) + self.assertGreater(updated['port']['revision_number'], + port['revision_number']) + updated2 = self.client.update_port( + port['id'], allowed_address_pairs=[]) + self.assertGreater(updated2['port']['revision_number'], + updated['port']['revision_number']) + + @test.idempotent_id('a21ec3b4-3569-4b77-bf29-4177edaa2df5') + @test.requires_ext(extension="extra_dhcp_opt", service="network") + def test_update_extra_dhcp_opt_bumps_revision(self): + net = self.create_network() + port = self.create_port(net) + opts = [{'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'}] + updated = self.client.update_port(port['id'], extra_dhcp_opts=opts) + self.assertGreater(updated['port']['revision_number'], + port['revision_number']) + opts[0]['opt_value'] = 'pxelinux.77' + updated2 = self.client.update_port( + port['id'], extra_dhcp_opts=opts) + self.assertGreater(updated2['port']['revision_number'], + updated['port']['revision_number']) + + @test.idempotent_id('40ba648f-f374-4c29-a5b7-489dd5a38a4e') + @test.requires_ext(extension="dns-integration", service="network") + def test_update_dns_domain_bumps_revision(self): + net = self.create_network(dns_domain='example.test.') + self.client.update_network(net['id'], dns_domain='exa.test.') + # TODO(kevinbenton): use update result after bug/1627628 is fixed + updated = self.client.show_network(net['id']) + self.assertGreater(updated['network']['revision_number'], + net['revision_number']) + port = self.create_port(net) + updated = self.client.update_port(port['id'], dns_name='port1') + if not updated['port']['dns_name']: + self.skipTest("Server does not have DNS domain configured.") + self.assertGreater(updated['port']['revision_number'], + port['revision_number']) + updated2 = self.client.update_port(port['id'], dns_name='') + self.assertGreater(updated2['port']['revision_number'], + updated['port']['revision_number']) + + @test.idempotent_id('8482324f-cf59-4d73-b98e-d37119255300') + @test.requires_ext(extension="router", service="network") + @test.requires_ext(extension="extraroute", service="network") + def test_update_router_extra_routes_bumps_revision(self): + subnet = self.create_subnet(self.create_network()) + subgateway = netaddr.IPAddress(subnet['gateway_ip']) + router = self.create_router(router_name='test') + self.create_router_interface(router['id'], subnet['id']) + router = self.client.show_router(router['id'])['router'] + updated = self.client.update_router( + router['id'], routes=[{'destination': '2.0.0.0/24', + 'nexthop': str(subgateway + 1)}]) + self.assertGreater(updated['router']['revision_number'], + router['revision_number']) + updated2 = self.client.update_router(router['id'], routes=[]) + self.assertGreater(updated2['router']['revision_number'], + updated['router']['revision_number']) + + @test.idempotent_id('6bd18702-e25a-4b4b-8c0c-680113533511') + @test.requires_ext(extension="subnet-service-types", service="network") + def test_update_subnet_service_types_bumps_revisions(self): + subnet = self.create_subnet(self.create_network()) + updated = self.client.update_subnet( + subnet['id'], service_types=['compute:']) + self.assertGreater(updated['subnet']['revision_number'], + subnet['revision_number']) + updated2 = self.client.update_subnet( + subnet['id'], service_types=[]) + self.assertGreater(updated2['subnet']['revision_number'], + updated['subnet']['revision_number']) + + @test.idempotent_id('9c83105c-9973-45ff-9ca2-e66d64700abe') + @test.requires_ext(extension="port-security", service="network") + def test_update_port_security_bumps_revisions(self): + net = self.create_network(port_security_enabled=False) + self.client.update_network(net['id'], port_security_enabled=True) + # TODO(kevinbenton): use update result after bug/1627628 is fixed + updated = self.client.show_network(net['id']) + self.assertGreater(updated['network']['revision_number'], + net['revision_number']) + self.client.update_network(net['id'], port_security_enabled=False) + updated2 = self.client.show_network(net['id']) + self.assertGreater(updated2['network']['revision_number'], + updated['network']['revision_number']) + port = self.create_port(net, port_security_enabled=False) + updated = self.client.update_port(port['id'], + port_security_enabled=True) + self.assertGreater(updated['port']['revision_number'], + port['revision_number']) + updated2 = self.client.update_port(port['id'], + port_security_enabled=False) + self.assertGreater(updated2['port']['revision_number'], + updated['port']['revision_number']) + + @test.idempotent_id('68d5ac3a-11a1-4847-8e2e-5843c043d89b') + @test.requires_ext(extension="binding", service="network") + def test_portbinding_bumps_revision(self): + port = self.create_port(self.create_network()) + port = self.admin_client.update_port( + port['id'], **{'binding:host_id': 'badhost1'})['port'] + updated = self.admin_client.update_port( + port['id'], **{'binding:host_id': 'badhost2'})['port'] + self.assertGreater(updated['revision_number'], + port['revision_number']) + @test.idempotent_id('4a37bde9-1975-47e0-9b8c-2c9ca36415b0') @test.requires_ext(extension="router", service="network") def test_update_router_bumps_revision(self):