blob: 253d779eee68247f4011bffc777b1f2316b6e863 [file] [log] [blame]
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +04001# Copyright 2014 OpenStack Foundation
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
16import netaddr
17import random
18
Matthew Treinish01472ff2015-02-20 17:26:52 -050019from tempest_lib.common.utils import data_utils
Masayuki Igawad9388762015-01-20 14:56:42 +090020from tempest_lib import exceptions as lib_exc
21
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040022from tempest.api.network import base
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040023from tempest import config
Chris Hoge7579c1a2015-02-26 14:12:15 -080024from tempest import test
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040025
26CONF = config.CONF
27
28
29class NetworksTestDHCPv6(base.BaseNetworkTest):
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040030 _ip_version = 6
31
32 """ Test DHCPv6 specific features using SLAAC, stateless and
33 stateful settings for subnets. Also it shall check dual-stack
34 functionality (IPv4 + IPv6 together).
35 The tests include:
36 generating of SLAAC EUI-64 address in subnets with various settings
37 receiving SLAAC addresses in combinations of various subnets
38 receiving stateful IPv6 addresses
39 addressing in subnets with router
40 """
41
42 @classmethod
Sergey Shnaidman64303102014-12-23 13:09:09 +030043 def skip_checks(cls):
Rohan Kanadea565e452015-01-27 14:00:13 +053044 super(NetworksTestDHCPv6, cls).skip_checks()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040045 msg = None
46 if not CONF.network_feature_enabled.ipv6:
47 msg = "IPv6 is not enabled"
48 elif not CONF.network_feature_enabled.ipv6_subnet_attributes:
49 msg = "DHCPv6 attributes are not enabled."
50 if msg:
51 raise cls.skipException(msg)
Sergey Shnaidman64303102014-12-23 13:09:09 +030052
53 @classmethod
54 def resource_setup(cls):
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040055 super(NetworksTestDHCPv6, cls).resource_setup()
56 cls.network = cls.create_network()
57
58 def _remove_from_list_by_index(self, things_list, elem):
59 for index, i in enumerate(things_list):
60 if i['id'] == elem['id']:
61 break
62 del things_list[index]
63
64 def _clean_network(self):
David Kranz34e88122014-12-11 15:24:05 -050065 body = self.client.list_ports()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040066 ports = body['ports']
67 for port in ports:
Michael Smithc0514d52014-12-18 10:37:49 -080068 if (port['device_owner'].startswith('network:router_interface')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040069 and port['device_id'] in [r['id'] for r in self.routers]):
70 self.client.remove_router_interface_with_port_id(
71 port['device_id'], port['id']
72 )
73 else:
74 if port['id'] in [p['id'] for p in self.ports]:
75 self.client.delete_port(port['id'])
76 self._remove_from_list_by_index(self.ports, port)
David Kranz34e88122014-12-11 15:24:05 -050077 body = self.client.list_subnets()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040078 subnets = body['subnets']
79 for subnet in subnets:
80 if subnet['id'] in [s['id'] for s in self.subnets]:
81 self.client.delete_subnet(subnet['id'])
82 self._remove_from_list_by_index(self.subnets, subnet)
David Kranz34e88122014-12-11 15:24:05 -050083 body = self.client.list_routers()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040084 routers = body['routers']
85 for router in routers:
86 if router['id'] in [r['id'] for r in self.routers]:
87 self.client.delete_router(router['id'])
88 self._remove_from_list_by_index(self.routers, router)
89
90 def _get_ips_from_subnet(self, **kwargs):
91 subnet = self.create_subnet(self.network, **kwargs)
92 port_mac = data_utils.rand_mac_address()
93 port = self.create_port(self.network, mac_address=port_mac)
94 real_ip = next(iter(port['fixed_ips']), None)['ip_address']
95 eui_ip = data_utils.get_ipv6_addr_by_EUI64(subnet['cidr'],
96 port_mac).format()
97 return real_ip, eui_ip
98
Chris Hoge7579c1a2015-02-26 14:12:15 -080099 @test.idempotent_id('e5517e62-6f16-430d-a672-f80875493d4c')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400100 def test_dhcpv6_stateless_eui64(self):
101 """When subnets configured with RAs SLAAC (AOM=100) and DHCP stateless
102 (AOM=110) both for radvd and dnsmasq, port shall receive IP address
103 calculated from its MAC.
104 """
105 for ra_mode, add_mode in (
106 ('slaac', 'slaac'),
107 ('dhcpv6-stateless', 'dhcpv6-stateless'),
108 ):
109 kwargs = {'ipv6_ra_mode': ra_mode,
110 'ipv6_address_mode': add_mode}
111 real_ip, eui_ip = self._get_ips_from_subnet(**kwargs)
112 self._clean_network()
113 self.assertEqual(eui_ip, real_ip,
114 ('Real port IP is %s, but shall be %s when '
115 'ipv6_ra_mode=%s and ipv6_address_mode=%s') % (
116 real_ip, eui_ip, ra_mode, add_mode))
117
Chris Hoge7579c1a2015-02-26 14:12:15 -0800118 @test.idempotent_id('ae2f4a5d-03ff-4c42-a3b0-ce2fcb7ea832')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400119 def test_dhcpv6_stateless_no_ra(self):
120 """When subnets configured with dnsmasq SLAAC and DHCP stateless
121 and there is no radvd, port shall receive IP address calculated
122 from its MAC and mask of subnet.
123 """
124 for ra_mode, add_mode in (
125 (None, 'slaac'),
126 (None, 'dhcpv6-stateless'),
127 ):
128 kwargs = {'ipv6_ra_mode': ra_mode,
129 'ipv6_address_mode': add_mode}
130 kwargs = {k: v for k, v in kwargs.iteritems() if v}
131 real_ip, eui_ip = self._get_ips_from_subnet(**kwargs)
132 self._clean_network()
133 self.assertEqual(eui_ip, real_ip,
134 ('Real port IP %s shall be equal to EUI-64 %s'
135 'when ipv6_ra_mode=%s,ipv6_address_mode=%s') % (
136 real_ip, eui_ip,
137 ra_mode if ra_mode else "Off",
138 add_mode if add_mode else "Off"))
139
Chris Hoge7579c1a2015-02-26 14:12:15 -0800140 @test.idempotent_id('81f18ef6-95b5-4584-9966-10d480b7496a')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400141 def test_dhcpv6_invalid_options(self):
142 """Different configurations for radvd and dnsmasq are not allowed"""
143 for ra_mode, add_mode in (
144 ('dhcpv6-stateless', 'dhcpv6-stateful'),
145 ('dhcpv6-stateless', 'slaac'),
146 ('slaac', 'dhcpv6-stateful'),
147 ('dhcpv6-stateful', 'dhcpv6-stateless'),
148 ('dhcpv6-stateful', 'slaac'),
149 ('slaac', 'dhcpv6-stateless'),
150 ):
151 kwargs = {'ipv6_ra_mode': ra_mode,
152 'ipv6_address_mode': add_mode}
Masayuki Igawa4b29e472015-02-16 10:41:54 +0900153 self.assertRaises(lib_exc.BadRequest,
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400154 self.create_subnet,
155 self.network,
156 **kwargs)
157
Chris Hoge7579c1a2015-02-26 14:12:15 -0800158 @test.idempotent_id('21635b6f-165a-4d42-bf49-7d195e47342f')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400159 def test_dhcpv6_stateless_no_ra_no_dhcp(self):
160 """If no radvd option and no dnsmasq option is configured
161 port shall receive IP from fixed IPs list of subnet.
162 """
163 real_ip, eui_ip = self._get_ips_from_subnet()
164 self._clean_network()
165 self.assertNotEqual(eui_ip, real_ip,
166 ('Real port IP %s equal to EUI-64 %s when '
167 'ipv6_ra_mode=Off and ipv6_address_mode=Off,'
168 'but shall be taken from fixed IPs') % (
169 real_ip, eui_ip))
170
Chris Hoge7579c1a2015-02-26 14:12:15 -0800171 @test.idempotent_id('4544adf7-bb5f-4bdc-b769-b3e77026cef2')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400172 def test_dhcpv6_two_subnets(self):
173 """When one IPv6 subnet configured with dnsmasq SLAAC or DHCP stateless
174 and other IPv6 is with DHCP stateful, port shall receive EUI-64 IP
175 addresses from first subnet and DHCP address from second one.
176 Order of subnet creating should be unimportant.
177 """
178 for order in ("slaac_first", "dhcp_first"):
179 for ra_mode, add_mode in (
180 ('slaac', 'slaac'),
181 ('dhcpv6-stateless', 'dhcpv6-stateless'),
182 ):
183 kwargs = {'ipv6_ra_mode': ra_mode,
184 'ipv6_address_mode': add_mode}
185 kwargs_dhcp = {'ipv6_address_mode': 'dhcpv6-stateful'}
186 if order == "slaac_first":
187 subnet_slaac = self.create_subnet(self.network, **kwargs)
188 subnet_dhcp = self.create_subnet(
189 self.network, **kwargs_dhcp)
190 else:
191 subnet_dhcp = self.create_subnet(
192 self.network, **kwargs_dhcp)
193 subnet_slaac = self.create_subnet(self.network, **kwargs)
194 port_mac = data_utils.rand_mac_address()
195 dhcp_ip = subnet_dhcp["allocation_pools"][0]["start"]
196 eui_ip = data_utils.get_ipv6_addr_by_EUI64(
197 subnet_slaac['cidr'],
198 port_mac
199 ).format()
200 # TODO(sergsh): remove this when 1219795 is fixed
201 dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
202 port = self.create_port(self.network, mac_address=port_mac)
203 real_ips = dict([(k['subnet_id'], k['ip_address'])
204 for k in port['fixed_ips']])
205 real_dhcp_ip, real_eui_ip = [real_ips[sub['id']]
206 for sub in subnet_dhcp,
207 subnet_slaac]
208 self.client.delete_port(port['id'])
209 self.ports.pop()
David Kranz34e88122014-12-11 15:24:05 -0500210 body = self.client.list_ports()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400211 ports_id_list = [i['id'] for i in body['ports']]
212 self.assertNotIn(port['id'], ports_id_list)
213 self._clean_network()
214 self.assertEqual(real_eui_ip,
215 eui_ip,
216 'Real IP is {0}, but shall be {1}'.format(
217 real_eui_ip,
218 eui_ip))
219 self.assertIn(
220 real_dhcp_ip, dhcp_ip,
221 'Real IP is {0}, but shall be one from {1}'.format(
222 real_dhcp_ip,
223 str(dhcp_ip)))
224
Chris Hoge7579c1a2015-02-26 14:12:15 -0800225 @test.idempotent_id('4256c61d-c538-41ea-9147-3c450c36669e')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400226 def test_dhcpv6_64_subnets(self):
227 """When one IPv6 subnet configured with dnsmasq SLAAC or DHCP stateless
228 and other IPv4 is with DHCP of IPv4, port shall receive EUI-64 IP
229 addresses from first subnet and IPv4 DHCP address from second one.
230 Order of subnet creating should be unimportant.
231 """
232 for order in ("slaac_first", "dhcp_first"):
233 for ra_mode, add_mode in (
234 ('slaac', 'slaac'),
235 ('dhcpv6-stateless', 'dhcpv6-stateless'),
236 ):
237 kwargs = {'ipv6_ra_mode': ra_mode,
238 'ipv6_address_mode': add_mode}
239 if order == "slaac_first":
240 subnet_slaac = self.create_subnet(self.network, **kwargs)
241 subnet_dhcp = self.create_subnet(
242 self.network, ip_version=4)
243 else:
244 subnet_dhcp = self.create_subnet(
245 self.network, ip_version=4)
246 subnet_slaac = self.create_subnet(self.network, **kwargs)
247 port_mac = data_utils.rand_mac_address()
248 dhcp_ip = subnet_dhcp["allocation_pools"][0]["start"]
249 eui_ip = data_utils.get_ipv6_addr_by_EUI64(
250 subnet_slaac['cidr'],
251 port_mac
252 ).format()
253 # TODO(sergsh): remove this when 1219795 is fixed
254 dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
255 port = self.create_port(self.network, mac_address=port_mac)
256 real_ips = dict([(k['subnet_id'], k['ip_address'])
257 for k in port['fixed_ips']])
258 real_dhcp_ip, real_eui_ip = [real_ips[sub['id']]
259 for sub in subnet_dhcp,
260 subnet_slaac]
261 self._clean_network()
262 self.assertTrue({real_eui_ip,
263 real_dhcp_ip}.issubset([eui_ip] + dhcp_ip))
264 self.assertEqual(real_eui_ip,
265 eui_ip,
266 'Real IP is {0}, but shall be {1}'.format(
267 real_eui_ip,
268 eui_ip))
269 self.assertIn(
270 real_dhcp_ip, dhcp_ip,
271 'Real IP is {0}, but shall be one from {1}'.format(
272 real_dhcp_ip,
273 str(dhcp_ip)))
274
Chris Hoge7579c1a2015-02-26 14:12:15 -0800275 @test.idempotent_id('4ab211a0-276f-4552-9070-51e27f58fecf')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400276 def test_dhcp_stateful(self):
277 """With all options below, DHCPv6 shall allocate first
278 address from subnet pool to port.
279 """
280 for ra_mode, add_mode in (
281 ('dhcpv6-stateful', 'dhcpv6-stateful'),
282 ('dhcpv6-stateful', None),
283 (None, 'dhcpv6-stateful'),
284 ):
285 kwargs = {'ipv6_ra_mode': ra_mode,
286 'ipv6_address_mode': add_mode}
287 kwargs = {k: v for k, v in kwargs.iteritems() if v}
288 subnet = self.create_subnet(self.network, **kwargs)
289 port = self.create_port(self.network)
290 port_ip = next(iter(port['fixed_ips']), None)['ip_address']
291 dhcp_ip = subnet["allocation_pools"][0]["start"]
292 # TODO(sergsh): remove this when 1219795 is fixed
293 dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
294 self._clean_network()
295 self.assertIn(
296 port_ip, dhcp_ip,
297 'Real IP is {0}, but shall be one from {1}'.format(
298 port_ip,
299 str(dhcp_ip)))
300
Chris Hoge7579c1a2015-02-26 14:12:15 -0800301 @test.idempotent_id('51a5e97f-f02e-4e4e-9a17-a69811d300e3')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400302 def test_dhcp_stateful_fixedips(self):
303 """With all options below, port shall be able to get
304 requested IP from fixed IP range not depending on
305 DHCP stateful (not SLAAC!) settings configured.
306 """
307 for ra_mode, add_mode in (
308 ('dhcpv6-stateful', 'dhcpv6-stateful'),
309 ('dhcpv6-stateful', None),
310 (None, 'dhcpv6-stateful'),
311 ):
312 kwargs = {'ipv6_ra_mode': ra_mode,
313 'ipv6_address_mode': add_mode}
314 kwargs = {k: v for k, v in kwargs.iteritems() if v}
315 subnet = self.create_subnet(self.network, **kwargs)
316 ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
317 subnet["allocation_pools"][0]["end"])
318 ip = netaddr.IPAddress(random.randrange(ip_range.first,
319 ip_range.last)).format()
320 port = self.create_port(self.network,
321 fixed_ips=[{'subnet_id': subnet['id'],
322 'ip_address': ip}])
323 port_ip = next(iter(port['fixed_ips']), None)['ip_address']
324 self._clean_network()
325 self.assertEqual(port_ip, ip,
326 ("Port IP %s is not as fixed IP from "
327 "port create request: %s") % (
328 port_ip, ip))
329
Chris Hoge7579c1a2015-02-26 14:12:15 -0800330 @test.idempotent_id('98244d88-d990-4570-91d4-6b25d70d08af')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400331 def test_dhcp_stateful_fixedips_outrange(self):
332 """When port gets IP address from fixed IP range it
333 shall be checked if it's from subnets range.
334 """
335 kwargs = {'ipv6_ra_mode': 'dhcpv6-stateful',
336 'ipv6_address_mode': 'dhcpv6-stateful'}
337 subnet = self.create_subnet(self.network, **kwargs)
338 ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
339 subnet["allocation_pools"][0]["end"])
340 ip = netaddr.IPAddress(random.randrange(
341 ip_range.last + 1, ip_range.last + 10)).format()
Masayuki Igawa4b29e472015-02-16 10:41:54 +0900342 self.assertRaises(lib_exc.BadRequest,
Qin Zhaoa4cae612015-01-28 16:27:00 +0800343 self.create_port,
344 self.network,
345 fixed_ips=[{'subnet_id': subnet['id'],
346 'ip_address': ip}])
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400347
Chris Hoge7579c1a2015-02-26 14:12:15 -0800348 @test.idempotent_id('57b8302b-cba9-4fbb-8835-9168df029051')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400349 def test_dhcp_stateful_fixedips_duplicate(self):
350 """When port gets IP address from fixed IP range it
351 shall be checked if it's not duplicate.
352 """
353 kwargs = {'ipv6_ra_mode': 'dhcpv6-stateful',
354 'ipv6_address_mode': 'dhcpv6-stateful'}
355 subnet = self.create_subnet(self.network, **kwargs)
356 ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
357 subnet["allocation_pools"][0]["end"])
358 ip = netaddr.IPAddress(random.randrange(
359 ip_range.first, ip_range.last)).format()
360 self.create_port(self.network,
361 fixed_ips=[
362 {'subnet_id': subnet['id'],
363 'ip_address': ip}])
Masayuki Igawad9388762015-01-20 14:56:42 +0900364 self.assertRaisesRegexp(lib_exc.Conflict,
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400365 "object with that identifier already exists",
366 self.create_port,
367 self.network,
368 fixed_ips=[{'subnet_id': subnet['id'],
369 'ip_address': ip}])
370
371 def _create_subnet_router(self, kwargs):
372 subnet = self.create_subnet(self.network, **kwargs)
373 router = self.create_router(
374 router_name=data_utils.rand_name("routerv6-"),
375 admin_state_up=True)
376 port = self.create_router_interface(router['id'],
377 subnet['id'])
David Kranz34e88122014-12-11 15:24:05 -0500378 body = self.client.show_port(port['port_id'])
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400379 return subnet, body['port']
380
Chris Hoge7579c1a2015-02-26 14:12:15 -0800381 @test.idempotent_id('e98f65db-68f4-4330-9fea-abd8c5192d4d')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400382 def test_dhcp_stateful_router(self):
383 """With all options below the router interface shall
384 receive DHCPv6 IP address from allocation pool.
385 """
386 for ra_mode, add_mode in (
387 ('dhcpv6-stateful', 'dhcpv6-stateful'),
388 ('dhcpv6-stateful', None),
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400389 ):
390 kwargs = {'ipv6_ra_mode': ra_mode,
391 'ipv6_address_mode': add_mode}
392 kwargs = {k: v for k, v in kwargs.iteritems() if v}
393 subnet, port = self._create_subnet_router(kwargs)
394 port_ip = next(iter(port['fixed_ips']), None)['ip_address']
395 self._clean_network()
396 self.assertEqual(port_ip, subnet['gateway_ip'],
397 ("Port IP %s is not as first IP from "
398 "subnets allocation pool: %s") % (
399 port_ip, subnet['gateway_ip']))
400
401 def tearDown(self):
402 self._clean_network()
403 super(NetworksTestDHCPv6, self).tearDown()