blob: 02e28463893dd202b2a487efc9ef8bf7ca09f3af [file] [log] [blame]
Slawek Kaplonskia1e88c42020-03-03 03:00:48 +01001# Copyright 2020 Red Hat, Inc.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from neutron_lib import constants as lib_constants
17from oslo_log import log
18from tempest.common import utils as tempest_utils
Slawek Kaplonskia1e88c42020-03-03 03:00:48 +010019from tempest.lib.common.utils import data_utils
20from tempest.lib import decorators
21from tempest.lib import exceptions as lib_exc
22
23from neutron_tempest_plugin.common import ip
24from neutron_tempest_plugin.common import ssh
25from neutron_tempest_plugin.common import utils
26from neutron_tempest_plugin import config
27from neutron_tempest_plugin.scenario import base
28
29CONF = config.CONF
30
31LOG = log.getLogger(__name__)
32
33
34def turn_nic6_on(ssh, ipv6_port):
35 """Turns the IPv6 vNIC on
36
37 Required because guest images usually set only the first vNIC on boot.
38 Searches for the IPv6 vNIC's MAC and brings it up.
39
40 @param ssh: RemoteClient ssh instance to server
41 @param ipv6_port: port from IPv6 network attached to the server
42 """
43 ip_command = ip.IPCommand(ssh)
44 nic = ip_command.get_nic_name_by_mac(ipv6_port['mac_address'])
45
46 # NOTE(slaweq): on RHEL based OS ifcfg file for new interface is
47 # needed to make IPv6 working on it, so if
48 # /etc/sysconfig/network-scripts directory exists ifcfg-%(nic)s file
49 # should be added in it
50 if sysconfig_network_scripts_dir_exists(ssh):
51 try:
52 ssh.execute_script(
53 'echo -e "DEVICE=%(nic)s\\nNAME=%(nic)s\\nIPV6INIT=yes" | '
54 'tee /etc/sysconfig/network-scripts/ifcfg-%(nic)s; '
55 'nmcli connection reload' % {'nic': nic},
56 become_root=True)
57 ssh.execute_script('nmcli connection up %s' % nic,
58 become_root=True)
59 except lib_exc.SSHExecCommandFailed as e:
60 # NOTE(slaweq): Sometimes it can happen that this SSH command
61 # will fail because of some error from network manager in
62 # guest os.
63 # But even then doing ip link set up below is fine and
64 # IP address should be configured properly.
65 LOG.debug("Error during restarting %(nic)s interface on "
66 "instance. Error message: %(error)s",
67 {'nic': nic, 'error': e})
68 ip_command.set_link(nic, "up")
69
70
71def sysconfig_network_scripts_dir_exists(ssh):
72 return "False" not in ssh.execute_script(
73 'test -d /etc/sysconfig/network-scripts/ || echo "False"')
74
75
76class IPv6Test(base.BaseTempestTestCase):
77 credentials = ['primary', 'admin']
78
79 ipv6_ra_mode = 'slaac'
80 ipv6_address_mode = 'slaac'
81
82 @classmethod
83 @tempest_utils.requires_ext(extension="router", service="network")
84 def resource_setup(cls):
85 super(IPv6Test, cls).resource_setup()
86 cls._setup_basic_resources()
87
88 @classmethod
89 def _setup_basic_resources(cls):
90 cls.network = cls.create_network()
91 cls.subnet = cls.create_subnet(cls.network)
92 cls.router = cls.create_router_by_client()
93 cls.create_router_interface(cls.router['id'], cls.subnet['id'])
94 cls.keypair = cls.create_keypair()
95 cls.secgroup = cls.create_security_group(
96 name=data_utils.rand_name('secgroup'))
97 cls.create_loginable_secgroup_rule(secgroup_id=cls.secgroup['id'])
98 cls.create_pingable_secgroup_rule(secgroup_id=cls.secgroup['id'])
99
100 def _test_ipv6_address_configured(self, ssh_client, vm, ipv6_port):
101 ipv6_address = ipv6_port['fixed_ips'][0]['ip_address']
102 ip_command = ip.IPCommand(ssh_client)
103
104 def guest_has_address(expected_address):
105 ip_addresses = [a.address for a in ip_command.list_addresses()]
106 for ip_address in ip_addresses:
107 if expected_address in ip_address:
108 return True
109 return False
110
111 # Set NIC with IPv6 to be UP and wait until IPv6 address will be
112 # configured on this NIC
113 turn_nic6_on(ssh_client, ipv6_port)
114 # And check if IPv6 address will be properly configured on this NIC
115 utils.wait_until_true(
116 lambda: guest_has_address(ipv6_address),
117 timeout=120,
118 exception=RuntimeError(
119 "Timed out waiting for IP address {!r} to be configured in "
120 "the VM {!r}.".format(ipv6_address, vm['id'])))
121
122 def _test_ipv6_hotplug(self, ra_mode, address_mode):
123 ipv6_networks = [self.create_network() for _ in range(2)]
124 for net in ipv6_networks:
125 subnet = self.create_subnet(
126 network=net, ip_version=6,
127 ipv6_ra_mode=ra_mode, ipv6_address_mode=address_mode)
128 self.create_router_interface(self.router['id'], subnet['id'])
129
130 server_kwargs = {
131 'flavor_ref': CONF.compute.flavor_ref,
132 'image_ref': CONF.compute.image_ref,
133 'key_name': self.keypair['name'],
134 'networks': [
135 {'uuid': self.network['id']},
136 {'uuid': ipv6_networks[0]['id']}],
137 'security_groups': [{'name': self.secgroup['name']}],
138 }
139 vm = self.create_server(**server_kwargs)['server']
140 self.wait_for_server_active(vm)
141 ipv4_port = self.client.list_ports(
142 network_id=self.network['id'],
143 device_id=vm['id'])['ports'][0]
144 fip = self.create_floatingip(port=ipv4_port)
145 ssh_client = ssh.Client(
146 fip['floating_ip_address'], CONF.validation.image_ssh_user,
147 pkey=self.keypair['private_key'])
148
149 ipv6_port = self.client.list_ports(
150 network_id=ipv6_networks[0]['id'],
151 device_id=vm['id'])['ports'][0]
152 self._test_ipv6_address_configured(ssh_client, vm, ipv6_port)
153
154 # Now remove this port IPv6 port from the VM and attach new one
155 self.delete_interface(vm['id'], ipv6_port['id'])
156
157 # And plug VM to the second IPv6 network
158 ipv6_port = self.create_port(ipv6_networks[1])
159 self.create_interface(vm['id'], ipv6_port['id'])
Rodolfo Alonso Hernandez0adf8a22020-06-11 11:28:25 +0000160 ip.wait_for_interface_status(
Slawek Kaplonskia1e88c42020-03-03 03:00:48 +0100161 self.os_primary.interfaces_client, vm['id'],
Rodolfo Alonso Hernandez0adf8a22020-06-11 11:28:25 +0000162 ipv6_port['id'], lib_constants.PORT_STATUS_ACTIVE,
163 ssh_client=ssh_client, mac_address=ipv6_port['mac_address'])
Slawek Kaplonskia1e88c42020-03-03 03:00:48 +0100164 self._test_ipv6_address_configured(ssh_client, vm, ipv6_port)
165
166 @decorators.idempotent_id('b13e5408-5250-4a42-8e46-6996ce613e91')
167 def test_ipv6_hotplug_slaac(self):
168 self._test_ipv6_hotplug("slaac", "slaac")
169
170 @decorators.idempotent_id('9aaedbc4-986d-42d5-9177-3e721728e7e0')
171 def test_ipv6_hotplug_dhcpv6stateless(self):
172 self._test_ipv6_hotplug("dhcpv6-stateless", "dhcpv6-stateless")