Merge "Make the non ha router usage explicit in a dvr test"
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index ee003b0..3470602 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -29,7 +29,7 @@
     def test_get_availability_zone_list(self):
         # List of availability zone
         availability_zone = self.client.list_availability_zones()
-        self.assertTrue(len(availability_zone['availabilityZoneInfo']) > 0)
+        self.assertGreater(len(availability_zone['availabilityZoneInfo']), 0)
 
     @test.idempotent_id('ef726c58-530f-44c2-968c-c7bed22d5b8c')
     def test_get_availability_zone_list_detail(self):
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 3754637..154d717 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -42,11 +42,9 @@
 
     @test.idempotent_id('aa06b52b-2db5-4807-b218-9441f75d74e3')
     def test_delete_saving_image(self):
-        snapshot_name = data_utils.rand_name('test-snap')
         server = self.create_test_server(wait_until='ACTIVE')
         self.addCleanup(self.servers_client.delete_server, server['id'])
         image = self.create_image_from_server(server['id'],
-                                              name=snapshot_name,
                                               wait_until='SAVING')
         self.client.delete_image(image['id'])
         msg = ('The image with ID {image_id} failed to be deleted'
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index e91944f..8db094d 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -64,8 +64,6 @@
         # Create a new image with invalid server id
         name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
-        resp = {}
-        resp['status'] = None
         self.assertRaises(lib_exc.NotFound, self.create_image_from_server,
                           '!@$^&*()', name=name, meta=meta)
 
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index d4c2648..a48c17b 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -264,37 +264,23 @@
         flavor_base = self.flavors_client.show_flavor(
             self.flavor_ref)['flavor']
 
-        def create_flavor_with_extra_specs():
-            flavor_with_eph_disk_name = data_utils.rand_name('eph_flavor')
+        def create_flavor_with_ephemeral(ephem_disk):
+            if ephem_disk > 0:
+                flavor_name = data_utils.rand_name('eph_flavor')
+            else:
+                flavor_name = data_utils.rand_name('no_eph_flavor')
             flavor_with_eph_disk_id = data_utils.rand_int_id(start=1000)
 
             ram = flavor_base['ram']
             vcpus = flavor_base['vcpus']
             disk = flavor_base['disk']
 
-            # Create a flavor with extra specs
+            # Create a flavor with ephemeral disk
             flavor = (self.flavor_client.
-                      create_flavor(name=flavor_with_eph_disk_name,
+                      create_flavor(name=flavor_name,
                                     ram=ram, vcpus=vcpus, disk=disk,
                                     id=flavor_with_eph_disk_id,
-                                    ephemeral=1))['flavor']
-            self.addCleanup(flavor_clean_up, flavor['id'])
-
-            return flavor['id']
-
-        def create_flavor_without_extra_specs():
-            flavor_no_eph_disk_name = data_utils.rand_name('no_eph_flavor')
-            flavor_no_eph_disk_id = data_utils.rand_int_id(start=1000)
-
-            ram = flavor_base['ram']
-            vcpus = flavor_base['vcpus']
-            disk = flavor_base['disk']
-
-            # Create a flavor without extra specs
-            flavor = (self.flavor_client.
-                      create_flavor(name=flavor_no_eph_disk_name,
-                                    ram=ram, vcpus=vcpus, disk=disk,
-                                    id=flavor_no_eph_disk_id))['flavor']
+                                    ephemeral=ephem_disk))['flavor']
             self.addCleanup(flavor_clean_up, flavor['id'])
 
             return flavor['id']
@@ -303,8 +289,8 @@
             self.flavor_client.delete_flavor(flavor_id)
             self.flavor_client.wait_for_resource_deletion(flavor_id)
 
-        flavor_with_eph_disk_id = create_flavor_with_extra_specs()
-        flavor_no_eph_disk_id = create_flavor_without_extra_specs()
+        flavor_with_eph_disk_id = create_flavor_with_ephemeral(ephem_disk=1)
+        flavor_no_eph_disk_id = create_flavor_with_ephemeral(ephem_disk=0)
 
         admin_pass = self.image_ssh_password
 
@@ -314,7 +300,7 @@
             adminPass=admin_pass,
             flavor=flavor_no_eph_disk_id)
 
-        # Get partition number of server without extra specs.
+        # Get partition number of server without ephemeral disk.
         server_no_eph_disk = self.client.show_server(
             server_no_eph_disk['id'])['server']
         linux_client = remote_client.RemoteClient(
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 4dd26af..9fc30f9 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -14,26 +14,16 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest import test
 
 
 class MultipleCreateTestJSON(base.BaseV2ComputeTest):
-    _name = 'multiple-create-test'
-
-    def _create_multiple_servers(self, **kwargs):
-        # This is the right way to create_multiple servers and manage to get
-        # the created servers into the servers list to be cleaned up after all.
-        kwargs['name'] = kwargs.get('name', data_utils.rand_name(self._name))
-        body = self.create_test_server(**kwargs)
-
-        return body
 
     @test.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
     def test_multiple_create(self):
-        body = self._create_multiple_servers(wait_until='ACTIVE',
-                                             min_count=1,
-                                             max_count=2)
+        body = self.create_test_server(wait_until='ACTIVE',
+                                       min_count=1,
+                                       max_count=2)
         # NOTE(maurosr): do status response check and also make sure that
         # reservation_id is not in the response body when the request send
         # contains return_reservation_id=False
@@ -41,8 +31,8 @@
 
     @test.idempotent_id('864777fb-2f1e-44e3-b5b9-3eb6fa84f2f7')
     def test_multiple_create_with_reservation_return(self):
-        body = self._create_multiple_servers(wait_until='ACTIVE',
-                                             min_count=1,
-                                             max_count=2,
-                                             return_reservation_id=True)
+        body = self.create_test_server(wait_until='ACTIVE',
+                                       min_count=1,
+                                       max_count=2,
+                                       return_reservation_id=True)
         self.assertIn('reservation_id', body)
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
index c4dbe23..d9fb4ca 100644
--- a/tempest/api/compute/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -14,48 +14,38 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
 
 class MultipleCreateNegativeTestJSON(base.BaseV2ComputeTest):
-    _name = 'multiple-create-test'
-
-    def _create_multiple_servers(self, **kwargs):
-        # This is the right way to create_multiple servers and manage to get
-        # the created servers into the servers list to be cleaned up after all.
-        kwargs['name'] = kwargs.get('name', data_utils.rand_name(self._name))
-        body = self.create_test_server(**kwargs)
-
-        return body
 
     @test.attr(type=['negative'])
     @test.idempotent_id('daf29d8d-e928-4a01-9a8c-b129603f3fc0')
     def test_min_count_less_than_one(self):
         invalid_min_count = 0
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           min_count=invalid_min_count)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('999aa722-d624-4423-b813-0d1ac9884d7a')
     def test_min_count_non_integer(self):
         invalid_min_count = 2.5
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           min_count=invalid_min_count)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('a6f9c2ab-e060-4b82-b23c-4532cb9390ff')
     def test_max_count_less_than_one(self):
         invalid_max_count = 0
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           max_count=invalid_max_count)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('9c5698d1-d7af-4c80-b971-9d403135eea2')
     def test_max_count_non_integer(self):
         invalid_max_count = 2.5
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           max_count=invalid_max_count)
 
     @test.attr(type=['negative'])
@@ -63,6 +53,6 @@
     def test_max_count_less_than_min_count(self):
         min_count = 3
         max_count = 2
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           min_count=min_count,
                           max_count=max_count)
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 89be3f3..1b1b339 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -490,6 +490,36 @@
                           self.client.unshelve_server,
                           self.server_id)
 
+    @test.attr(type=['negative'])
+    @test.idempotent_id('74085be3-a370-4ca2-bc51-2d0e10e0f573')
+    @test.services('volume', 'image')
+    def test_create_server_from_non_bootable_volume(self):
+        # Create a volume
+        volume = self.create_volume()
+
+        # Update volume bootable status to false
+        self.volumes_client.set_bootable_volume(volume['id'],
+                                                bootable=False)
+
+        # Verify bootable flag was updated
+        nonbootable_vol = self.volumes_client.show_volume(
+            volume['id'])['volume']
+        self.assertEqual('false', nonbootable_vol['bootable'])
+
+        # Block device mapping
+        bd_map = [{'boot_index': '0',
+                   'uuid': volume['id'],
+                   'source_type': 'volume',
+                   'destination_type': 'volume',
+                   'delete_on_termination': False}]
+
+        # Try creating a server from non-bootable volume
+        self.assertRaises(lib_exc.BadRequest,
+                          self.create_test_server,
+                          image_id='',
+                          wait_until='ACTIVE',
+                          block_device_mapping_v2=bd_map)
+
 
 class ServersNegativeTestMultiTenantJSON(base.BaseV2ComputeTest):
 
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 4bc4262..84c48ec 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -348,9 +348,7 @@
 
     def _create_subnet_router(self, kwargs):
         subnet = self.create_subnet(self.network, **kwargs)
-        router = self.create_router(
-            router_name=data_utils.rand_name("routerv6-"),
-            admin_state_up=True)
+        router = self.create_router(admin_state_up=True)
         port = self.create_router_interface(router['id'],
                                             subnet['id'])
         body = self.ports_client.show_port(port['port_id'])
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index 963d99d..7ffc30f 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -15,7 +15,6 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
 from tempest import config
 from tempest.lib import exceptions as lib_exc
 from tempest import test
@@ -45,7 +44,7 @@
         # Create a network with a subnet connected to a router.
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
-        cls.router = cls.create_router(data_utils.rand_name('router'))
+        cls.router = cls.create_router()
         cls.create_router_interface(cls.router['id'], cls.subnet['id'])
         cls.port = cls.create_port(cls.network)
 
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 2979f7d..15d289d 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -199,7 +199,7 @@
         self.addCleanup(self.networks_client.delete_network, network['id'])
         subnet = self.create_subnet(network)
         self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
-        router = self.create_router(data_utils.rand_name('router-'))
+        router = self.create_router()
         self.addCleanup(self.routers_client.delete_router, router['id'])
         port = self.ports_client.create_port(network_id=network['id'])
         # Add router interface to port created above
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 354e6d1..b3983de 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -134,7 +134,5 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('4990b055-8fc7-48ab-bba7-aa28beaad0b9')
     def test_router_create_tenant_distributed_returns_forbidden(self):
-        self.assertRaises(lib_exc.Forbidden,
-                          self.create_router,
-                          data_utils.rand_name('router'),
+        self.assertRaises(lib_exc.Forbidden, self.create_router,
                           distributed=True)
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 1468e90..5af83b3 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest import config
 from tempest import test
 
@@ -38,16 +37,10 @@
         super(SnapshotsActionsV2Test, cls).resource_setup()
 
         # Create a test shared volume for tests
-        vol_name = data_utils.rand_name(cls.__name__ + '-Volume')
-        cls.name_field = cls.special_fields['name_field']
-        params = {cls.name_field: vol_name}
-        cls.volume = cls.create_volume(**params)
+        cls.volume = cls.create_volume()
 
         # Create a test shared snapshot for tests
-        snap_name = data_utils.rand_name(cls.__name__ + '-Snapshot')
-        params = {cls.name_field: snap_name}
-        cls.snapshot = cls.create_snapshot(
-            volume_id=cls.volume['id'], **params)
+        cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id'])
 
     def tearDown(self):
         # Set snapshot's status to available after test
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index b788d54..b9aeb99 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -113,13 +113,12 @@
         if 'size' not in kwargs:
             kwargs['size'] = CONF.volume.volume_size
 
-        name = data_utils.rand_name(cls.__name__ + '-Volume')
-
         name_field = cls.special_fields['name_field']
+        if name_field not in kwargs:
+            name = data_utils.rand_name(cls.__name__ + '-Volume')
+            kwargs[name_field] = name
 
-        kwargs[name_field] = name
         volume = cls.volumes_client.create_volume(**kwargs)['volume']
-
         cls.volumes.append(volume)
         waiters.wait_for_volume_status(cls.volumes_client,
                                        volume['id'], 'available')
@@ -128,6 +127,11 @@
     @classmethod
     def create_snapshot(cls, volume_id=1, **kwargs):
         """Wrapper utility that returns a test snapshot."""
+        name_field = cls.special_fields['name_field']
+        if name_field not in kwargs:
+            name = data_utils.rand_name(cls.__name__ + '-Snapshot')
+            kwargs[name_field] = name
+
         snapshot = cls.snapshots_client.create_snapshot(
             volume_id=volume_id, **kwargs)['snapshot']
         cls.snapshots.append(snapshot)
@@ -173,7 +177,7 @@
                 pass
 
     def create_server(self, **kwargs):
-        name = kwargs.get(
+        name = kwargs.pop(
             'name',
             data_utils.rand_name(self.__class__.__name__ + '-instance'))
 
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 7be31d1..3c05d3e 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -64,9 +64,7 @@
     @test.idempotent_id('2a8abbe4-d871-46db-b049-c41f5af8216e')
     def test_snapshot_create_get_list_update_delete(self):
         # Create a snapshot
-        s_name = data_utils.rand_name(self.__class__.__name__ + '-snap')
-        params = {self.name_field: s_name}
-        snapshot = self.create_snapshot(self.volume_origin['id'], **params)
+        snapshot = self.create_snapshot(self.volume_origin['id'])
 
         # Get the snap and check for some of its details
         snap_get = self.snapshots_client.show_snapshot(
diff --git a/tempest/common/utils/net_utils.py b/tempest/common/utils/net_utils.py
index f0d3da3..867b3dd 100644
--- a/tempest/common/utils/net_utils.py
+++ b/tempest/common/utils/net_utils.py
@@ -51,3 +51,23 @@
                 return addrs
     msg = "Insufficient IP addresses available"
     raise lib_exc.BadRequest(message=msg)
+
+
+def get_ping_payload_size(mtu, ip_version):
+    """Return the maximum size of ping payload that will fit into MTU."""
+    if not mtu:
+        return None
+    if ip_version == 4:
+        ip_header = 20
+        icmp_header = 8
+    else:
+        ip_header = 40
+        icmp_header = 4
+    res = mtu - ip_header - icmp_header
+    if res < 0:
+        raise lib_exc.BadRequest(
+            message='MTU = %(mtu)d is too low for IPv%(ip_version)d' % {
+                'mtu': mtu,
+                'ip_version': ip_version,
+            })
+    return res
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index ab388c2..831be99 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -26,6 +26,7 @@
 from tempest.common import image as common_image
 from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
+from tempest.common.utils import net_utils
 from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
@@ -495,9 +496,18 @@
                                            server_id, 'ACTIVE')
 
     def ping_ip_address(self, ip_address, should_succeed=True,
-                        ping_timeout=None):
+                        ping_timeout=None, mtu=None):
         timeout = ping_timeout or CONF.validation.ping_timeout
-        cmd = ['ping', '-c1', '-w1', ip_address]
+        cmd = ['ping', '-c1', '-w1']
+
+        if mtu:
+            cmd += [
+                # don't fragment
+                '-M', 'do',
+                # ping receives just the size of ICMP payload
+                '-s', str(net_utils.get_ping_payload_size(mtu, 4))
+            ]
+        cmd.append(ip_address)
 
         def ping():
             proc = subprocess.Popen(cmd,
@@ -525,7 +535,8 @@
     def check_vm_connectivity(self, ip_address,
                               username=None,
                               private_key=None,
-                              should_connect=True):
+                              should_connect=True,
+                              mtu=None):
         """Check server connectivity
 
         :param ip_address: server to test against
@@ -534,6 +545,7 @@
         :param should_connect: True/False indicates positive/negative test
             positive - attempt ping and ssh
             negative - attempt ping and fail if succeed
+        :param mtu: network MTU to use for connectivity validation
 
         :raises: AssertError if the result of the connectivity check does
             not match the value of the should_connect param
@@ -543,7 +555,8 @@
         else:
             msg = "ip address %s is reachable" % ip_address
         self.assertTrue(self.ping_ip_address(ip_address,
-                                             should_succeed=should_connect),
+                                             should_succeed=should_connect,
+                                             mtu=mtu),
                         msg=msg)
         if should_connect:
             # no need to check ssh for negative connectivity
@@ -551,7 +564,7 @@
 
     def check_public_network_connectivity(self, ip_address, username,
                                           private_key, should_connect=True,
-                                          msg=None, servers=None):
+                                          msg=None, servers=None, mtu=None):
         # The target login is assumed to have been configured for
         # key-based authentication by cloud-init.
         LOG.debug('checking network connections to IP %s with user: %s' %
@@ -560,7 +573,8 @@
             self.check_vm_connectivity(ip_address,
                                        username,
                                        private_key,
-                                       should_connect=should_connect)
+                                       should_connect=should_connect,
+                                       mtu=mtu)
         except Exception:
             ex_msg = 'Public network connectivity check failed'
             if msg:
@@ -789,7 +803,7 @@
 
     def _get_server_port_id_and_ip4(self, server, ip_addr=None):
         ports = self._list_ports(device_id=server['id'], fixed_ip=ip_addr)
-        # A port can have more then one IP address in some cases.
+        # A port can have more than one IP address in some cases.
         # If the network is dual-stack (IPv4 + IPv6), this port is associated
         # with 2 subnets
         p_status = ['ACTIVE']
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 43adfb1..8de3561 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -52,7 +52,7 @@
 
     def _get_host_name(self):
         hosts = self.hosts_client.list_hosts()['hosts']
-        self.assertTrue(len(hosts) >= 1)
+        self.assertGreaterEqual(len(hosts), 1)
         computes = [x for x in hosts if x['service'] == 'compute']
         return computes[0]['host_name']
 
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index a295b6a..b527c3d 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -183,7 +183,7 @@
 
     def check_public_network_connectivity(
             self, should_connect=True, msg=None,
-            should_check_floating_ip_status=True):
+            should_check_floating_ip_status=True, mtu=None):
         """Verifies connectivty to a VM via public network and floating IP
 
         and verifies floating IP has resource status is correct.
@@ -195,6 +195,7 @@
         to indicate the context of the failure
         :param should_check_floating_ip_status: bool. should status of
         floating_ip be checked or not
+        :param mtu: int. MTU network to use for connectivity validation
         """
         ssh_login = CONF.validation.image_ssh_user
         floating_ip, server = self.floating_ip_tuple
@@ -210,7 +211,7 @@
         # call the common method in the parent class
         super(TestNetworkBasicOps, self).check_public_network_connectivity(
             ip_address, ssh_login, private_key, should_connect, msg,
-            self.servers)
+            self.servers, mtu=mtu)
 
     def _disassociate_floating_ips(self):
         floating_ip, server = self.floating_ip_tuple
@@ -410,6 +411,16 @@
                                                msg="after re-associate "
                                                    "floating ip")
 
+    @test.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
+    @testtools.skipUnless(test.is_extension_enabled('net-mtu', 'network'),
+                          'No way to calculate MTU for networks')
+    @test.services('compute', 'network')
+    def test_mtu_sized_frames(self):
+        """Validate that network MTU sized frames fit through."""
+        self._setup_network_and_servers()
+        self.check_public_network_connectivity(
+            should_connect=True, mtu=self.network['mtu'])
+
     @test.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
     @testtools.skipIf(CONF.baremetal.driver_enabled,
                       'Baremetal relies on a shared physical network.')
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index dd86d90..496f07e 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -18,7 +18,6 @@
 
 from tempest import config
 from tempest.lib.common.utils import test_utils
-from tempest.lib import decorators
 from tempest.scenario import manager
 from tempest import test
 
@@ -255,7 +254,6 @@
         self._prepare_and_test(address6_mode='dhcpv6-stateless', n_subnets6=2,
                                dualnet=True)
 
-    @decorators.skip_because(bug="1540983")
     @test.idempotent_id('9178ad42-10e4-47e9-8987-e02b170cc5cd')
     @test.services('compute', 'network')
     def test_dualnet_multi_prefix_slaac(self):
diff --git a/tempest/tests/common/utils/test_net_utils.py b/tempest/tests/common/utils/test_net_utils.py
new file mode 100644
index 0000000..83c6bcc
--- /dev/null
+++ b/tempest/tests/common/utils/test_net_utils.py
@@ -0,0 +1,33 @@
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import mock
+
+from tempest.common.utils import net_utils
+from tempest.lib import exceptions as lib_exc
+from tempest.tests import base
+
+
+class TestGetPingPayloadSize(base.TestCase):
+
+    def test_ipv4(self):
+        self.assertEqual(1422, net_utils.get_ping_payload_size(1450, 4))
+
+    def test_ipv6(self):
+        self.assertEqual(1406, net_utils.get_ping_payload_size(1450, 6))
+
+    def test_too_low_mtu(self):
+        self.assertRaises(
+            lib_exc.BadRequest, net_utils.get_ping_payload_size, 10, 4)
+
+    def test_None(self):
+        self.assertIsNone(net_utils.get_ping_payload_size(None, mock.Mock()))