Adds scenario for IPv6 addresses
* Checks the way how IPv6 addresses assigned to vNIC
* Eliminates hardcoded IPv4 subnet creation.
* Fixes problem with creating FIP for port with few addresses.
* Adds ping6 to remote_client
Partially implements: blueprint ipv6-api-testing-parity
Change-Id: I728edf0165ba47b6f8930f2fb3d08bd29cfbb317
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
new file mode 100644
index 0000000..c9f1fe1
--- /dev/null
+++ b/tempest/scenario/test_network_v6.py
@@ -0,0 +1,146 @@
+# Copyright 2014 Cisco Systems, Inc.
+# All Rights Reserved.
+#
+# 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 netaddr
+from tempest import config
+from tempest.openstack.common import log as logging
+from tempest.scenario import manager
+from tempest import test
+
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+class TestGettingAddress(manager.NetworkScenarioTest):
+ """Create network with 2 subnets: IPv4 and IPv6 in a given address mode
+ Boot 2 VMs on this network
+ Allocate and assign 2 FIP4
+ Check that vNIC of server matches port data from OpenStack DB
+ Ping4 tenant IPv4 of one VM from another one
+ Will do the same with ping6 when available in VM
+ """
+
+ @classmethod
+ def resource_setup(cls):
+ # Create no network resources for these tests.
+ cls.set_network_resources()
+ super(TestGettingAddress, cls).resource_setup()
+
+ @classmethod
+ def check_preconditions(cls):
+ if not (CONF.network_feature_enabled.ipv6
+ and CONF.network_feature_enabled.ipv6_subnet_attributes):
+ cls.enabled = False
+ raise cls.skipException('IPv6 or its attributes not supported')
+ if not (CONF.network.tenant_networks_reachable
+ or CONF.network.public_network_id):
+ msg = ('Either tenant_networks_reachable must be "true", or '
+ 'public_network_id must be defined.')
+ cls.enabled = False
+ raise cls.skipException(msg)
+ super(TestGettingAddress, cls).check_preconditions()
+
+ def setUp(self):
+ super(TestGettingAddress, self).setUp()
+ self.keypair = self.create_keypair()
+ self.sec_grp = self._create_security_group(tenant_id=self.tenant_id)
+ self.srv_kwargs = {
+ 'key_name': self.keypair['name'],
+ 'security_groups': [self.sec_grp]}
+
+ def prepare_network(self, address6_mode):
+ """Creates network with
+ one IPv6 subnet in the given mode and
+ one IPv4 subnet
+ Creates router with ports on both subnets
+ """
+ net = self._create_network(tenant_id=self.tenant_id)
+ sub4 = self._create_subnet(network=net,
+ namestart='sub4',
+ ip_version=4,)
+ # since https://bugs.launchpad.net/neutron/+bug/1394112 we need
+ # to specify gateway_ip manually
+ net_range = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
+ gateway_ip = (netaddr.IPAddress(net_range) + 1).format()
+ sub6 = self._create_subnet(network=net,
+ namestart='sub6',
+ ip_version=6,
+ gateway_ip=gateway_ip,
+ ipv6_ra_mode=address6_mode,
+ ipv6_address_mode=address6_mode)
+
+ router = self._get_router(tenant_id=self.tenant_id)
+ sub4.add_to_router(router_id=router['id'])
+ sub6.add_to_router(router_id=router['id'])
+ self.addCleanup(sub4.delete)
+ self.addCleanup(sub6.delete)
+
+ @staticmethod
+ def define_server_ips(srv):
+ for net_name, nics in srv['addresses'].iteritems():
+ for nic in nics:
+ if nic['version'] == 6:
+ srv['accessIPv6'] = nic['addr']
+ else:
+ srv['accessIPv4'] = nic['addr']
+
+ def prepare_server(self):
+ username = CONF.compute.image_ssh_user
+
+ srv = self.create_server(create_kwargs=self.srv_kwargs)
+ fip = self.create_floating_ip(thing=srv)
+ self.define_server_ips(srv=srv)
+ ssh = self.get_remote_client(
+ server_or_ip=fip.floating_ip_address,
+ username=username)
+ return ssh, srv
+
+ def _prepare_and_test(self, address6_mode):
+ self.prepare_network(address6_mode=address6_mode)
+
+ ssh1, srv1 = self.prepare_server()
+ ssh2, srv2 = self.prepare_server()
+
+ result = ssh1.get_ip_list()
+ self.assertIn(srv1['accessIPv4'], result)
+ # v6 should be configured since the image supports it
+ self.assertIn(srv1['accessIPv6'], result)
+ result = ssh2.get_ip_list()
+ self.assertIn(srv2['accessIPv4'], result)
+ # v6 should be configured since the image supports it
+ self.assertIn(srv2['accessIPv6'], result)
+ result = ssh1.ping_host(srv2['accessIPv4'])
+ self.assertIn('0% packet loss', result)
+ result = ssh2.ping_host(srv1['accessIPv4'])
+ self.assertIn('0% packet loss', result)
+
+ # Some VM (like cirros) may not have ping6 utility
+ result = ssh1.exec_command('whereis ping6')
+ is_ping6 = False if result == 'ping6:\n' else True
+ if is_ping6:
+ result = ssh1.ping_host(srv2['accessIPv6'])
+ self.assertIn('0% packet loss', result)
+ result = ssh2.ping_host(srv1['accessIPv6'])
+ self.assertIn('0% packet loss', result)
+ else:
+ LOG.warning('Ping6 is not available, skipping')
+
+ @test.services('compute', 'network')
+ def test_slaac_from_os(self):
+ self._prepare_and_test(address6_mode='slaac')
+
+ @test.services('compute', 'network')
+ def test_dhcp6_stateless_from_os(self):
+ self._prepare_and_test(address6_mode='dhcpv6-stateless')