blob: a10f749b23b7b86034370499200e193c66b17c31 [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):
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040044 msg = None
45 if not CONF.network_feature_enabled.ipv6:
46 msg = "IPv6 is not enabled"
47 elif not CONF.network_feature_enabled.ipv6_subnet_attributes:
48 msg = "DHCPv6 attributes are not enabled."
49 if msg:
50 raise cls.skipException(msg)
Sergey Shnaidman64303102014-12-23 13:09:09 +030051
52 @classmethod
53 def resource_setup(cls):
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040054 super(NetworksTestDHCPv6, cls).resource_setup()
55 cls.network = cls.create_network()
56
57 def _remove_from_list_by_index(self, things_list, elem):
58 for index, i in enumerate(things_list):
59 if i['id'] == elem['id']:
60 break
61 del things_list[index]
62
63 def _clean_network(self):
David Kranz34e88122014-12-11 15:24:05 -050064 body = self.client.list_ports()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040065 ports = body['ports']
66 for port in ports:
Michael Smithc0514d52014-12-18 10:37:49 -080067 if (port['device_owner'].startswith('network:router_interface')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040068 and port['device_id'] in [r['id'] for r in self.routers]):
69 self.client.remove_router_interface_with_port_id(
70 port['device_id'], port['id']
71 )
72 else:
73 if port['id'] in [p['id'] for p in self.ports]:
74 self.client.delete_port(port['id'])
75 self._remove_from_list_by_index(self.ports, port)
David Kranz34e88122014-12-11 15:24:05 -050076 body = self.client.list_subnets()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040077 subnets = body['subnets']
78 for subnet in subnets:
79 if subnet['id'] in [s['id'] for s in self.subnets]:
80 self.client.delete_subnet(subnet['id'])
81 self._remove_from_list_by_index(self.subnets, subnet)
David Kranz34e88122014-12-11 15:24:05 -050082 body = self.client.list_routers()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040083 routers = body['routers']
84 for router in routers:
85 if router['id'] in [r['id'] for r in self.routers]:
86 self.client.delete_router(router['id'])
87 self._remove_from_list_by_index(self.routers, router)
88
89 def _get_ips_from_subnet(self, **kwargs):
90 subnet = self.create_subnet(self.network, **kwargs)
91 port_mac = data_utils.rand_mac_address()
92 port = self.create_port(self.network, mac_address=port_mac)
93 real_ip = next(iter(port['fixed_ips']), None)['ip_address']
94 eui_ip = data_utils.get_ipv6_addr_by_EUI64(subnet['cidr'],
95 port_mac).format()
96 return real_ip, eui_ip
97
Chris Hoge7579c1a2015-02-26 14:12:15 -080098 @test.idempotent_id('e5517e62-6f16-430d-a672-f80875493d4c')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +040099 def test_dhcpv6_stateless_eui64(self):
100 """When subnets configured with RAs SLAAC (AOM=100) and DHCP stateless
101 (AOM=110) both for radvd and dnsmasq, port shall receive IP address
102 calculated from its MAC.
103 """
104 for ra_mode, add_mode in (
105 ('slaac', 'slaac'),
106 ('dhcpv6-stateless', 'dhcpv6-stateless'),
107 ):
108 kwargs = {'ipv6_ra_mode': ra_mode,
109 'ipv6_address_mode': add_mode}
110 real_ip, eui_ip = self._get_ips_from_subnet(**kwargs)
111 self._clean_network()
112 self.assertEqual(eui_ip, real_ip,
113 ('Real port IP is %s, but shall be %s when '
114 'ipv6_ra_mode=%s and ipv6_address_mode=%s') % (
115 real_ip, eui_ip, ra_mode, add_mode))
116
Chris Hoge7579c1a2015-02-26 14:12:15 -0800117 @test.idempotent_id('ae2f4a5d-03ff-4c42-a3b0-ce2fcb7ea832')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400118 def test_dhcpv6_stateless_no_ra(self):
119 """When subnets configured with dnsmasq SLAAC and DHCP stateless
120 and there is no radvd, port shall receive IP address calculated
121 from its MAC and mask of subnet.
122 """
123 for ra_mode, add_mode in (
124 (None, 'slaac'),
125 (None, 'dhcpv6-stateless'),
126 ):
127 kwargs = {'ipv6_ra_mode': ra_mode,
128 'ipv6_address_mode': add_mode}
129 kwargs = {k: v for k, v in kwargs.iteritems() if v}
130 real_ip, eui_ip = self._get_ips_from_subnet(**kwargs)
131 self._clean_network()
132 self.assertEqual(eui_ip, real_ip,
133 ('Real port IP %s shall be equal to EUI-64 %s'
134 'when ipv6_ra_mode=%s,ipv6_address_mode=%s') % (
135 real_ip, eui_ip,
136 ra_mode if ra_mode else "Off",
137 add_mode if add_mode else "Off"))
138
Chris Hoge7579c1a2015-02-26 14:12:15 -0800139 @test.idempotent_id('81f18ef6-95b5-4584-9966-10d480b7496a')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400140 def test_dhcpv6_invalid_options(self):
141 """Different configurations for radvd and dnsmasq are not allowed"""
142 for ra_mode, add_mode in (
143 ('dhcpv6-stateless', 'dhcpv6-stateful'),
144 ('dhcpv6-stateless', 'slaac'),
145 ('slaac', 'dhcpv6-stateful'),
146 ('dhcpv6-stateful', 'dhcpv6-stateless'),
147 ('dhcpv6-stateful', 'slaac'),
148 ('slaac', 'dhcpv6-stateless'),
149 ):
150 kwargs = {'ipv6_ra_mode': ra_mode,
151 'ipv6_address_mode': add_mode}
Masayuki Igawa4b29e472015-02-16 10:41:54 +0900152 self.assertRaises(lib_exc.BadRequest,
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400153 self.create_subnet,
154 self.network,
155 **kwargs)
156
Chris Hoge7579c1a2015-02-26 14:12:15 -0800157 @test.idempotent_id('21635b6f-165a-4d42-bf49-7d195e47342f')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400158 def test_dhcpv6_stateless_no_ra_no_dhcp(self):
159 """If no radvd option and no dnsmasq option is configured
160 port shall receive IP from fixed IPs list of subnet.
161 """
162 real_ip, eui_ip = self._get_ips_from_subnet()
163 self._clean_network()
164 self.assertNotEqual(eui_ip, real_ip,
165 ('Real port IP %s equal to EUI-64 %s when '
166 'ipv6_ra_mode=Off and ipv6_address_mode=Off,'
167 'but shall be taken from fixed IPs') % (
168 real_ip, eui_ip))
169
Chris Hoge7579c1a2015-02-26 14:12:15 -0800170 @test.idempotent_id('4544adf7-bb5f-4bdc-b769-b3e77026cef2')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400171 def test_dhcpv6_two_subnets(self):
172 """When one IPv6 subnet configured with dnsmasq SLAAC or DHCP stateless
173 and other IPv6 is with DHCP stateful, port shall receive EUI-64 IP
174 addresses from first subnet and DHCP address from second one.
175 Order of subnet creating should be unimportant.
176 """
177 for order in ("slaac_first", "dhcp_first"):
178 for ra_mode, add_mode in (
179 ('slaac', 'slaac'),
180 ('dhcpv6-stateless', 'dhcpv6-stateless'),
181 ):
182 kwargs = {'ipv6_ra_mode': ra_mode,
183 'ipv6_address_mode': add_mode}
184 kwargs_dhcp = {'ipv6_address_mode': 'dhcpv6-stateful'}
185 if order == "slaac_first":
186 subnet_slaac = self.create_subnet(self.network, **kwargs)
187 subnet_dhcp = self.create_subnet(
188 self.network, **kwargs_dhcp)
189 else:
190 subnet_dhcp = self.create_subnet(
191 self.network, **kwargs_dhcp)
192 subnet_slaac = self.create_subnet(self.network, **kwargs)
193 port_mac = data_utils.rand_mac_address()
194 dhcp_ip = subnet_dhcp["allocation_pools"][0]["start"]
195 eui_ip = data_utils.get_ipv6_addr_by_EUI64(
196 subnet_slaac['cidr'],
197 port_mac
198 ).format()
199 # TODO(sergsh): remove this when 1219795 is fixed
200 dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
201 port = self.create_port(self.network, mac_address=port_mac)
202 real_ips = dict([(k['subnet_id'], k['ip_address'])
203 for k in port['fixed_ips']])
204 real_dhcp_ip, real_eui_ip = [real_ips[sub['id']]
205 for sub in subnet_dhcp,
206 subnet_slaac]
207 self.client.delete_port(port['id'])
208 self.ports.pop()
David Kranz34e88122014-12-11 15:24:05 -0500209 body = self.client.list_ports()
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400210 ports_id_list = [i['id'] for i in body['ports']]
211 self.assertNotIn(port['id'], ports_id_list)
212 self._clean_network()
213 self.assertEqual(real_eui_ip,
214 eui_ip,
215 'Real IP is {0}, but shall be {1}'.format(
216 real_eui_ip,
217 eui_ip))
218 self.assertIn(
219 real_dhcp_ip, dhcp_ip,
220 'Real IP is {0}, but shall be one from {1}'.format(
221 real_dhcp_ip,
222 str(dhcp_ip)))
223
Chris Hoge7579c1a2015-02-26 14:12:15 -0800224 @test.idempotent_id('4256c61d-c538-41ea-9147-3c450c36669e')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400225 def test_dhcpv6_64_subnets(self):
226 """When one IPv6 subnet configured with dnsmasq SLAAC or DHCP stateless
227 and other IPv4 is with DHCP of IPv4, port shall receive EUI-64 IP
228 addresses from first subnet and IPv4 DHCP address from second one.
229 Order of subnet creating should be unimportant.
230 """
231 for order in ("slaac_first", "dhcp_first"):
232 for ra_mode, add_mode in (
233 ('slaac', 'slaac'),
234 ('dhcpv6-stateless', 'dhcpv6-stateless'),
235 ):
236 kwargs = {'ipv6_ra_mode': ra_mode,
237 'ipv6_address_mode': add_mode}
238 if order == "slaac_first":
239 subnet_slaac = self.create_subnet(self.network, **kwargs)
240 subnet_dhcp = self.create_subnet(
241 self.network, ip_version=4)
242 else:
243 subnet_dhcp = self.create_subnet(
244 self.network, ip_version=4)
245 subnet_slaac = self.create_subnet(self.network, **kwargs)
246 port_mac = data_utils.rand_mac_address()
247 dhcp_ip = subnet_dhcp["allocation_pools"][0]["start"]
248 eui_ip = data_utils.get_ipv6_addr_by_EUI64(
249 subnet_slaac['cidr'],
250 port_mac
251 ).format()
252 # TODO(sergsh): remove this when 1219795 is fixed
253 dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
254 port = self.create_port(self.network, mac_address=port_mac)
255 real_ips = dict([(k['subnet_id'], k['ip_address'])
256 for k in port['fixed_ips']])
257 real_dhcp_ip, real_eui_ip = [real_ips[sub['id']]
258 for sub in subnet_dhcp,
259 subnet_slaac]
260 self._clean_network()
261 self.assertTrue({real_eui_ip,
262 real_dhcp_ip}.issubset([eui_ip] + dhcp_ip))
263 self.assertEqual(real_eui_ip,
264 eui_ip,
265 'Real IP is {0}, but shall be {1}'.format(
266 real_eui_ip,
267 eui_ip))
268 self.assertIn(
269 real_dhcp_ip, dhcp_ip,
270 'Real IP is {0}, but shall be one from {1}'.format(
271 real_dhcp_ip,
272 str(dhcp_ip)))
273
Chris Hoge7579c1a2015-02-26 14:12:15 -0800274 @test.idempotent_id('4ab211a0-276f-4552-9070-51e27f58fecf')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400275 def test_dhcp_stateful(self):
276 """With all options below, DHCPv6 shall allocate first
277 address from subnet pool to port.
278 """
279 for ra_mode, add_mode in (
280 ('dhcpv6-stateful', 'dhcpv6-stateful'),
281 ('dhcpv6-stateful', None),
282 (None, 'dhcpv6-stateful'),
283 ):
284 kwargs = {'ipv6_ra_mode': ra_mode,
285 'ipv6_address_mode': add_mode}
286 kwargs = {k: v for k, v in kwargs.iteritems() if v}
287 subnet = self.create_subnet(self.network, **kwargs)
288 port = self.create_port(self.network)
289 port_ip = next(iter(port['fixed_ips']), None)['ip_address']
290 dhcp_ip = subnet["allocation_pools"][0]["start"]
291 # TODO(sergsh): remove this when 1219795 is fixed
292 dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
293 self._clean_network()
294 self.assertIn(
295 port_ip, dhcp_ip,
296 'Real IP is {0}, but shall be one from {1}'.format(
297 port_ip,
298 str(dhcp_ip)))
299
Chris Hoge7579c1a2015-02-26 14:12:15 -0800300 @test.idempotent_id('51a5e97f-f02e-4e4e-9a17-a69811d300e3')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400301 def test_dhcp_stateful_fixedips(self):
302 """With all options below, port shall be able to get
303 requested IP from fixed IP range not depending on
304 DHCP stateful (not SLAAC!) settings configured.
305 """
306 for ra_mode, add_mode in (
307 ('dhcpv6-stateful', 'dhcpv6-stateful'),
308 ('dhcpv6-stateful', None),
309 (None, 'dhcpv6-stateful'),
310 ):
311 kwargs = {'ipv6_ra_mode': ra_mode,
312 'ipv6_address_mode': add_mode}
313 kwargs = {k: v for k, v in kwargs.iteritems() if v}
314 subnet = self.create_subnet(self.network, **kwargs)
315 ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
316 subnet["allocation_pools"][0]["end"])
317 ip = netaddr.IPAddress(random.randrange(ip_range.first,
318 ip_range.last)).format()
319 port = self.create_port(self.network,
320 fixed_ips=[{'subnet_id': subnet['id'],
321 'ip_address': ip}])
322 port_ip = next(iter(port['fixed_ips']), None)['ip_address']
323 self._clean_network()
324 self.assertEqual(port_ip, ip,
325 ("Port IP %s is not as fixed IP from "
326 "port create request: %s") % (
327 port_ip, ip))
328
Chris Hoge7579c1a2015-02-26 14:12:15 -0800329 @test.idempotent_id('98244d88-d990-4570-91d4-6b25d70d08af')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400330 def test_dhcp_stateful_fixedips_outrange(self):
331 """When port gets IP address from fixed IP range it
332 shall be checked if it's from subnets range.
333 """
334 kwargs = {'ipv6_ra_mode': 'dhcpv6-stateful',
335 'ipv6_address_mode': 'dhcpv6-stateful'}
336 subnet = self.create_subnet(self.network, **kwargs)
337 ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
338 subnet["allocation_pools"][0]["end"])
339 ip = netaddr.IPAddress(random.randrange(
340 ip_range.last + 1, ip_range.last + 10)).format()
Masayuki Igawa4b29e472015-02-16 10:41:54 +0900341 self.assertRaises(lib_exc.BadRequest,
Qin Zhaoa4cae612015-01-28 16:27:00 +0800342 self.create_port,
343 self.network,
344 fixed_ips=[{'subnet_id': subnet['id'],
345 'ip_address': ip}])
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400346
Chris Hoge7579c1a2015-02-26 14:12:15 -0800347 @test.idempotent_id('57b8302b-cba9-4fbb-8835-9168df029051')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400348 def test_dhcp_stateful_fixedips_duplicate(self):
349 """When port gets IP address from fixed IP range it
350 shall be checked if it's not duplicate.
351 """
352 kwargs = {'ipv6_ra_mode': 'dhcpv6-stateful',
353 'ipv6_address_mode': 'dhcpv6-stateful'}
354 subnet = self.create_subnet(self.network, **kwargs)
355 ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
356 subnet["allocation_pools"][0]["end"])
357 ip = netaddr.IPAddress(random.randrange(
358 ip_range.first, ip_range.last)).format()
359 self.create_port(self.network,
360 fixed_ips=[
361 {'subnet_id': subnet['id'],
362 'ip_address': ip}])
Masayuki Igawad9388762015-01-20 14:56:42 +0900363 self.assertRaisesRegexp(lib_exc.Conflict,
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400364 "object with that identifier already exists",
365 self.create_port,
366 self.network,
367 fixed_ips=[{'subnet_id': subnet['id'],
368 'ip_address': ip}])
369
370 def _create_subnet_router(self, kwargs):
371 subnet = self.create_subnet(self.network, **kwargs)
372 router = self.create_router(
373 router_name=data_utils.rand_name("routerv6-"),
374 admin_state_up=True)
375 port = self.create_router_interface(router['id'],
376 subnet['id'])
David Kranz34e88122014-12-11 15:24:05 -0500377 body = self.client.show_port(port['port_id'])
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400378 return subnet, body['port']
379
Chris Hoge7579c1a2015-02-26 14:12:15 -0800380 @test.idempotent_id('e98f65db-68f4-4330-9fea-abd8c5192d4d')
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400381 def test_dhcp_stateful_router(self):
382 """With all options below the router interface shall
383 receive DHCPv6 IP address from allocation pool.
384 """
385 for ra_mode, add_mode in (
386 ('dhcpv6-stateful', 'dhcpv6-stateful'),
387 ('dhcpv6-stateful', None),
Sergey Shnaidmanf0ce2252014-08-28 13:05:08 +0400388 ):
389 kwargs = {'ipv6_ra_mode': ra_mode,
390 'ipv6_address_mode': add_mode}
391 kwargs = {k: v for k, v in kwargs.iteritems() if v}
392 subnet, port = self._create_subnet_router(kwargs)
393 port_ip = next(iter(port['fixed_ips']), None)['ip_address']
394 self._clean_network()
395 self.assertEqual(port_ip, subnet['gateway_ip'],
396 ("Port IP %s is not as first IP from "
397 "subnets allocation pool: %s") % (
398 port_ip, subnet['gateway_ip']))
399
400 def tearDown(self):
401 self._clean_network()
402 super(NetworksTestDHCPv6, self).tearDown()