blob: 0df455ec8a19ffd58ce0e47aa2082e248cbfa689 [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
Jay Pipesf4dad392012-06-05 16:03:58 -04002# 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.
Yair Friedbfdfc752014-09-28 13:56:45 +030015import itertools
Jay Pipesf4dad392012-06-05 16:03:58 -040016
Miguel Lavallecc939612013-02-22 17:27:20 -060017import netaddr
Masayuki Igawad9388762015-01-20 14:56:42 +090018from tempest_lib import exceptions as lib_exc
Jay Pipesf4dad392012-06-05 16:03:58 -040019
Sean Dague1937d092013-05-17 16:36:38 -040020from tempest.api.network import base
Rohan Kanade35589aa2014-08-19 14:56:12 +020021from tempest.common import custom_matchers
Masayuki Igawa259c1132013-10-31 17:48:44 +090022from tempest.common.utils import data_utils
Matthew Treinish03b48df2014-01-29 16:59:49 +000023from tempest import config
Masayuki Igawa6d495d62014-03-19 16:38:57 +090024from tempest import test
Unmesh Gurjar44986832012-05-08 19:57:10 +053025
Matthew Treinish03b48df2014-01-29 16:59:49 +000026CONF = config.CONF
27
Unmesh Gurjar44986832012-05-08 19:57:10 +053028
raiesmh0867698322013-08-20 13:09:01 +053029class NetworksTestJSON(base.BaseNetworkTest):
Unmesh Gurjar44986832012-05-08 19:57:10 +053030
Miguel Lavallecc939612013-02-22 17:27:20 -060031 """
Mark McClainf2982e82013-07-06 17:48:03 -040032 Tests the following operations in the Neutron API using the REST client for
33 Neutron:
Miguel Lavallecc939612013-02-22 17:27:20 -060034
35 create a network for a tenant
36 list tenant's networks
37 show a tenant network details
38 create a subnet for a tenant
39 list tenant's subnets
40 show a tenant subnet details
raiesmh08e1aad982013-08-05 14:19:36 +053041 network update
42 subnet update
sukhdevc704a702014-01-15 11:50:56 -080043 delete a network also deletes its subnets
Yair Friedbfdfc752014-09-28 13:56:45 +030044 list external networks
Miguel Lavallecc939612013-02-22 17:27:20 -060045
Henry Gessauffda37a2014-01-16 11:17:55 -050046 All subnet tests are run once with ipv4 and once with ipv6.
47
Mark McClainf2982e82013-07-06 17:48:03 -040048 v2.0 of the Neutron API is assumed. It is also assumed that the following
Miguel Lavallecc939612013-02-22 17:27:20 -060049 options are defined in the [network] section of etc/tempest.conf:
50
51 tenant_network_cidr with a block of cidr's from which smaller blocks
Henry Gessauffda37a2014-01-16 11:17:55 -050052 can be allocated for tenant ipv4 subnets
53
54 tenant_network_v6_cidr is the equivalent for ipv6 subnets
Miguel Lavallecc939612013-02-22 17:27:20 -060055
56 tenant_network_mask_bits with the mask bits to be used to partition the
Henry Gessauffda37a2014-01-16 11:17:55 -050057 block defined by tenant_network_cidr
58
59 tenant_network_v6_mask_bits is the equivalent for ipv6 subnets
Miguel Lavallecc939612013-02-22 17:27:20 -060060 """
61
Unmesh Gurjar44986832012-05-08 19:57:10 +053062 @classmethod
Andrea Frittolida4a2452014-09-15 13:12:08 +010063 def resource_setup(cls):
64 super(NetworksTestJSON, cls).resource_setup()
Jay Pipesf4dad392012-06-05 16:03:58 -040065 cls.network = cls.create_network()
66 cls.name = cls.network['name']
venakata anil1a2a64a2014-12-02 07:25:59 +000067 cls.subnet = cls._create_subnet_with_last_subnet_block(cls.network,
68 cls._ip_version)
Miguel Lavallecc939612013-02-22 17:27:20 -060069 cls.cidr = cls.subnet['cidr']
Rohan Kanade35589aa2014-08-19 14:56:12 +020070 cls._subnet_data = {6: {'gateway':
71 str(cls._get_gateway_from_tempest_conf(6)),
72 'allocation_pools':
73 cls._get_allocation_pools_from_gateway(6),
74 'dns_nameservers': ['2001:4860:4860::8844',
75 '2001:4860:4860::8888'],
76 'host_routes': [{'destination': '2001::/64',
77 'nexthop': '2003::1'}],
78 'new_host_routes': [{'destination':
79 '2001::/64',
80 'nexthop': '2005::1'}],
81 'new_dns_nameservers':
82 ['2001:4860:4860::7744',
83 '2001:4860:4860::7888']},
84 4: {'gateway':
85 str(cls._get_gateway_from_tempest_conf(4)),
86 'allocation_pools':
87 cls._get_allocation_pools_from_gateway(4),
88 'dns_nameservers': ['8.8.4.4', '8.8.8.8'],
89 'host_routes': [{'destination': '10.20.0.0/32',
90 'nexthop': '10.100.1.1'}],
91 'new_host_routes': [{'destination':
92 '10.20.0.0/32',
93 'nexthop':
94 '10.100.1.2'}],
95 'new_dns_nameservers': ['7.8.8.8', '7.8.4.4']}}
96
97 @classmethod
venakata anil1a2a64a2014-12-02 07:25:59 +000098 def _create_subnet_with_last_subnet_block(cls, network, ip_version):
99 """Derive last subnet CIDR block from tenant CIDR and
100 create the subnet with that derived CIDR
101 """
102 if ip_version == 4:
103 cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
104 mask_bits = CONF.network.tenant_network_mask_bits
105 elif ip_version == 6:
106 cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
107 mask_bits = CONF.network.tenant_network_v6_mask_bits
108
109 subnet_cidr = list(cidr.subnet(mask_bits))[-1]
110 gateway_ip = str(netaddr.IPAddress(subnet_cidr) + 1)
111 return cls.create_subnet(network, gateway=gateway_ip,
112 cidr=subnet_cidr, mask_bits=mask_bits)
113
114 @classmethod
Rohan Kanade35589aa2014-08-19 14:56:12 +0200115 def _get_gateway_from_tempest_conf(cls, ip_version):
116 """Return first subnet gateway for configured CIDR """
117 if ip_version == 4:
118 cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
119 mask_bits = CONF.network.tenant_network_mask_bits
120 elif ip_version == 6:
121 cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
122 mask_bits = CONF.network.tenant_network_v6_mask_bits
123
124 if mask_bits >= cidr.prefixlen:
125 return netaddr.IPAddress(cidr) + 1
126 else:
127 for subnet in cidr.subnet(mask_bits):
128 return netaddr.IPAddress(subnet) + 1
129
130 @classmethod
131 def _get_allocation_pools_from_gateway(cls, ip_version):
132 """Return allocation range for subnet of given gateway"""
133 gateway = cls._get_gateway_from_tempest_conf(ip_version)
134 return [{'start': str(gateway + 2), 'end': str(gateway + 3)}]
135
136 def subnet_dict(self, include_keys):
137 """Return a subnet dict which has include_keys and their corresponding
138 value from self._subnet_data
139 """
140 return dict((key, self._subnet_data[self._ip_version][key])
141 for key in include_keys)
142
143 def _compare_resource_attrs(self, actual, expected):
144 exclude_keys = set(actual).symmetric_difference(expected)
145 self.assertThat(actual, custom_matchers.MatchesDictExceptForKeys(
146 expected, exclude_keys))
147
venakata anil1a2a64a2014-12-02 07:25:59 +0000148 def _delete_network(self, network):
149 # Deleting network also deletes its subnets if exists
150 self.client.delete_network(network['id'])
151 if network in self.networks:
152 self.networks.remove(network)
153 for subnet in self.subnets:
154 if subnet['network_id'] == network['id']:
155 self.subnets.remove(subnet)
156
Rohan Kanade35589aa2014-08-19 14:56:12 +0200157 def _create_verify_delete_subnet(self, cidr=None, mask_bits=None,
158 **kwargs):
159 network = self.create_network()
160 net_id = network['id']
161 gateway = kwargs.pop('gateway', None)
162 subnet = self.create_subnet(network, gateway, cidr, mask_bits,
163 **kwargs)
164 compare_args_full = dict(gateway_ip=gateway, cidr=cidr,
165 mask_bits=mask_bits, **kwargs)
166 compare_args = dict((k, v) for k, v in compare_args_full.iteritems()
167 if v is not None)
168
169 if 'dns_nameservers' in set(subnet).intersection(compare_args):
170 self.assertEqual(sorted(compare_args['dns_nameservers']),
171 sorted(subnet['dns_nameservers']))
172 del subnet['dns_nameservers'], compare_args['dns_nameservers']
173
174 self._compare_resource_attrs(subnet, compare_args)
175 self.client.delete_network(net_id)
176 self.networks.pop()
177 self.subnets.pop()
Unmesh Gurjar44986832012-05-08 19:57:10 +0530178
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900179 @test.attr(type='smoke')
raiesmh08e1aad982013-08-05 14:19:36 +0530180 def test_create_update_delete_network_subnet(self):
Mark Maglana5885eb32014-02-28 10:57:34 -0800181 # Create a network
Masayuki Igawa259c1132013-10-31 17:48:44 +0900182 name = data_utils.rand_name('network-')
Rohan Kanade35589aa2014-08-19 14:56:12 +0200183 network = self.create_network(network_name=name)
venakata anil1a2a64a2014-12-02 07:25:59 +0000184 self.addCleanup(self._delete_network, network)
raiesmh08e1aad982013-08-05 14:19:36 +0530185 net_id = network['id']
Santosh Kumar42c94802014-08-08 04:31:42 -0700186 self.assertEqual('ACTIVE', network['status'])
Mark Maglana5885eb32014-02-28 10:57:34 -0800187 # Verify network update
raiesmh08e1aad982013-08-05 14:19:36 +0530188 new_name = "New_network"
David Kranz34e88122014-12-11 15:24:05 -0500189 body = self.client.update_network(net_id, name=new_name)
raiesmh08e1aad982013-08-05 14:19:36 +0530190 updated_net = body['network']
191 self.assertEqual(updated_net['name'], new_name)
Miguel Lavallecc939612013-02-22 17:27:20 -0600192 # Find a cidr that is not in use yet and create a subnet with it
Matthew Treinish6b8cd2a2014-03-03 20:45:56 +0000193 subnet = self.create_subnet(network)
raiesmh08e1aad982013-08-05 14:19:36 +0530194 subnet_id = subnet['id']
Mark Maglana5885eb32014-02-28 10:57:34 -0800195 # Verify subnet update
196 new_name = "New_subnet"
David Kranz34e88122014-12-11 15:24:05 -0500197 body = self.client.update_subnet(subnet_id, name=new_name)
raiesmh08e1aad982013-08-05 14:19:36 +0530198 updated_subnet = body['subnet']
Mark Maglana5885eb32014-02-28 10:57:34 -0800199 self.assertEqual(updated_subnet['name'], new_name)
Unmesh Gurjar44986832012-05-08 19:57:10 +0530200
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900201 @test.attr(type='smoke')
Unmesh Gurjar44986832012-05-08 19:57:10 +0530202 def test_show_network(self):
Mark Maglana5885eb32014-02-28 10:57:34 -0800203 # Verify the details of a network
David Kranz34e88122014-12-11 15:24:05 -0500204 body = self.client.show_network(self.network['id'])
Unmesh Gurjar44986832012-05-08 19:57:10 +0530205 network = body['network']
Mark Maglana5885eb32014-02-28 10:57:34 -0800206 for key in ['id', 'name']:
207 self.assertEqual(network[key], self.network[key])
Unmesh Gurjar44986832012-05-08 19:57:10 +0530208
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900209 @test.attr(type='smoke')
jun xied557d9b2014-01-09 14:00:36 +0800210 def test_show_network_fields(self):
Mark Maglana5885eb32014-02-28 10:57:34 -0800211 # Verify specific fields of a network
Zhi Kun Liu903596c2014-04-11 08:55:53 -0500212 fields = ['id', 'name']
David Kranz34e88122014-12-11 15:24:05 -0500213 body = self.client.show_network(self.network['id'],
214 fields=fields)
jun xied557d9b2014-01-09 14:00:36 +0800215 network = body['network']
Zhi Kun Liu903596c2014-04-11 08:55:53 -0500216 self.assertEqual(sorted(network.keys()), sorted(fields))
217 for field_name in fields:
Mark Maglana5885eb32014-02-28 10:57:34 -0800218 self.assertEqual(network[field_name], self.network[field_name])
jun xied557d9b2014-01-09 14:00:36 +0800219
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900220 @test.attr(type='smoke')
Unmesh Gurjar44986832012-05-08 19:57:10 +0530221 def test_list_networks(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -0500222 # Verify the network exists in the list of all networks
David Kranz34e88122014-12-11 15:24:05 -0500223 body = self.client.list_networks()
Mark Maglana5885eb32014-02-28 10:57:34 -0800224 networks = [network['id'] for network in body['networks']
225 if network['id'] == self.network['id']]
226 self.assertNotEmpty(networks, "Created network not found in the list")
Unmesh Gurjar44986832012-05-08 19:57:10 +0530227
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900228 @test.attr(type='smoke')
jun xie0b4735d2014-01-07 15:42:58 +0800229 def test_list_networks_fields(self):
Mark Maglana5885eb32014-02-28 10:57:34 -0800230 # Verify specific fields of the networks
Zhi Kun Liu903596c2014-04-11 08:55:53 -0500231 fields = ['id', 'name']
David Kranz34e88122014-12-11 15:24:05 -0500232 body = self.client.list_networks(fields=fields)
jun xie0b4735d2014-01-07 15:42:58 +0800233 networks = body['networks']
Mark Maglana5885eb32014-02-28 10:57:34 -0800234 self.assertNotEmpty(networks, "Network list returned is empty")
235 for network in networks:
Zhi Kun Liu903596c2014-04-11 08:55:53 -0500236 self.assertEqual(sorted(network.keys()), sorted(fields))
jun xie0b4735d2014-01-07 15:42:58 +0800237
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900238 @test.attr(type='smoke')
Miguel Lavallecc939612013-02-22 17:27:20 -0600239 def test_show_subnet(self):
Mark Maglana5885eb32014-02-28 10:57:34 -0800240 # Verify the details of a subnet
David Kranz34e88122014-12-11 15:24:05 -0500241 body = self.client.show_subnet(self.subnet['id'])
Miguel Lavallecc939612013-02-22 17:27:20 -0600242 subnet = body['subnet']
Mark Maglana5885eb32014-02-28 10:57:34 -0800243 self.assertNotEmpty(subnet, "Subnet returned has no fields")
244 for key in ['id', 'cidr']:
245 self.assertIn(key, subnet)
246 self.assertEqual(subnet[key], self.subnet[key])
Miguel Lavallecc939612013-02-22 17:27:20 -0600247
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900248 @test.attr(type='smoke')
jun xied557d9b2014-01-09 14:00:36 +0800249 def test_show_subnet_fields(self):
Mark Maglana5885eb32014-02-28 10:57:34 -0800250 # Verify specific fields of a subnet
Zhi Kun Liu903596c2014-04-11 08:55:53 -0500251 fields = ['id', 'network_id']
David Kranz34e88122014-12-11 15:24:05 -0500252 body = self.client.show_subnet(self.subnet['id'],
253 fields=fields)
jun xied557d9b2014-01-09 14:00:36 +0800254 subnet = body['subnet']
Zhi Kun Liu903596c2014-04-11 08:55:53 -0500255 self.assertEqual(sorted(subnet.keys()), sorted(fields))
256 for field_name in fields:
Mark Maglana5885eb32014-02-28 10:57:34 -0800257 self.assertEqual(subnet[field_name], self.subnet[field_name])
jun xied557d9b2014-01-09 14:00:36 +0800258
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900259 @test.attr(type='smoke')
Miguel Lavallecc939612013-02-22 17:27:20 -0600260 def test_list_subnets(self):
261 # Verify the subnet exists in the list of all subnets
David Kranz34e88122014-12-11 15:24:05 -0500262 body = self.client.list_subnets()
Mark Maglana5885eb32014-02-28 10:57:34 -0800263 subnets = [subnet['id'] for subnet in body['subnets']
264 if subnet['id'] == self.subnet['id']]
265 self.assertNotEmpty(subnets, "Created subnet not found in the list")
raiesmh08e1aad982013-08-05 14:19:36 +0530266
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900267 @test.attr(type='smoke')
jun xie0b4735d2014-01-07 15:42:58 +0800268 def test_list_subnets_fields(self):
Mark Maglana5885eb32014-02-28 10:57:34 -0800269 # Verify specific fields of subnets
Zhi Kun Liu903596c2014-04-11 08:55:53 -0500270 fields = ['id', 'network_id']
David Kranz34e88122014-12-11 15:24:05 -0500271 body = self.client.list_subnets(fields=fields)
jun xie0b4735d2014-01-07 15:42:58 +0800272 subnets = body['subnets']
Mark Maglana5885eb32014-02-28 10:57:34 -0800273 self.assertNotEmpty(subnets, "Subnet list returned is empty")
274 for subnet in subnets:
Zhi Kun Liu903596c2014-04-11 08:55:53 -0500275 self.assertEqual(sorted(subnet.keys()), sorted(fields))
jun xie0b4735d2014-01-07 15:42:58 +0800276
sukhdevc704a702014-01-15 11:50:56 -0800277 def _try_delete_network(self, net_id):
278 # delete network, if it exists
279 try:
280 self.client.delete_network(net_id)
281 # if network is not found, this means it was deleted in the test
Masayuki Igawabfa07602015-01-20 18:47:17 +0900282 except lib_exc.NotFound:
sukhdevc704a702014-01-15 11:50:56 -0800283 pass
284
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900285 @test.attr(type='smoke')
sukhdevc704a702014-01-15 11:50:56 -0800286 def test_delete_network_with_subnet(self):
287 # Creates a network
288 name = data_utils.rand_name('network-')
David Kranz34e88122014-12-11 15:24:05 -0500289 body = self.client.create_network(name=name)
sukhdevc704a702014-01-15 11:50:56 -0800290 network = body['network']
291 net_id = network['id']
292 self.addCleanup(self._try_delete_network, net_id)
293
294 # Find a cidr that is not in use yet and create a subnet with it
295 subnet = self.create_subnet(network)
296 subnet_id = subnet['id']
297
298 # Delete network while the subnet still exists
David Kranz34e88122014-12-11 15:24:05 -0500299 body = self.client.delete_network(net_id)
sukhdevc704a702014-01-15 11:50:56 -0800300
301 # Verify that the subnet got automatically deleted.
Masayuki Igawabfa07602015-01-20 18:47:17 +0900302 self.assertRaises(lib_exc.NotFound, self.client.show_subnet,
sukhdevc704a702014-01-15 11:50:56 -0800303 subnet_id)
304
305 # Since create_subnet adds the subnet to the delete list, and it is
306 # is actually deleted here - this will create and issue, hence remove
307 # it from the list.
308 self.subnets.pop()
309
Edgar Magana6a9ac342014-01-16 13:52:49 -0800310 @test.attr(type='smoke')
Sergey Shnaidman18cf5972014-09-02 22:05:00 +0400311 def test_create_delete_subnet_without_gateway(self):
312 self._create_verify_delete_subnet()
313
314 @test.attr(type='smoke')
Edgar Magana6a9ac342014-01-16 13:52:49 -0800315 def test_create_delete_subnet_with_gw(self):
Rohan Kanade35589aa2014-08-19 14:56:12 +0200316 self._create_verify_delete_subnet(
317 **self.subnet_dict(['gateway']))
Edgar Magana6a9ac342014-01-16 13:52:49 -0800318
319 @test.attr(type='smoke')
Rohan Kanade35589aa2014-08-19 14:56:12 +0200320 def test_create_delete_subnet_with_allocation_pools(self):
321 self._create_verify_delete_subnet(
322 **self.subnet_dict(['allocation_pools']))
323
324 @test.attr(type='smoke')
325 def test_create_delete_subnet_with_gw_and_allocation_pools(self):
326 self._create_verify_delete_subnet(**self.subnet_dict(
327 ['gateway', 'allocation_pools']))
328
329 @test.attr(type='smoke')
330 def test_create_delete_subnet_with_host_routes_and_dns_nameservers(self):
331 self._create_verify_delete_subnet(
332 **self.subnet_dict(['host_routes', 'dns_nameservers']))
333
334 @test.attr(type='smoke')
335 def test_create_delete_subnet_with_dhcp_enabled(self):
336 self._create_verify_delete_subnet(enable_dhcp=True)
337
338 @test.attr(type='smoke')
339 def test_update_subnet_gw_dns_host_routes_dhcp(self):
340 network = self.create_network()
venakata anil1a2a64a2014-12-02 07:25:59 +0000341 self.addCleanup(self._delete_network, network)
Rohan Kanade35589aa2014-08-19 14:56:12 +0200342
343 subnet = self.create_subnet(
344 network, **self.subnet_dict(['gateway', 'host_routes',
345 'dns_nameservers',
346 'allocation_pools']))
347 subnet_id = subnet['id']
348 new_gateway = str(netaddr.IPAddress(
349 self._subnet_data[self._ip_version]['gateway']) + 1)
350 # Verify subnet update
351 new_host_routes = self._subnet_data[self._ip_version][
352 'new_host_routes']
353
354 new_dns_nameservers = self._subnet_data[self._ip_version][
355 'new_dns_nameservers']
356 kwargs = {'host_routes': new_host_routes,
357 'dns_nameservers': new_dns_nameservers,
358 'gateway_ip': new_gateway, 'enable_dhcp': True}
359
360 new_name = "New_subnet"
David Kranz34e88122014-12-11 15:24:05 -0500361 body = self.client.update_subnet(subnet_id, name=new_name,
362 **kwargs)
Rohan Kanade35589aa2014-08-19 14:56:12 +0200363 updated_subnet = body['subnet']
364 kwargs['name'] = new_name
365 self.assertEqual(sorted(updated_subnet['dns_nameservers']),
366 sorted(kwargs['dns_nameservers']))
367 del subnet['dns_nameservers'], kwargs['dns_nameservers']
368
369 self._compare_resource_attrs(updated_subnet, kwargs)
370
371 @test.attr(type='smoke')
372 def test_create_delete_subnet_all_attributes(self):
373 self._create_verify_delete_subnet(
374 enable_dhcp=True,
375 **self.subnet_dict(['gateway', 'host_routes', 'dns_nameservers']))
Edgar Magana6a9ac342014-01-16 13:52:49 -0800376
Yair Friedbfdfc752014-09-28 13:56:45 +0300377 @test.attr(type='smoke')
378 def test_external_network_visibility(self):
379 """Verifies user can see external networks but not subnets."""
David Kranz34e88122014-12-11 15:24:05 -0500380 body = self.client.list_networks(**{'router:external': True})
Yair Friedbfdfc752014-09-28 13:56:45 +0300381 networks = [network['id'] for network in body['networks']]
382 self.assertNotEmpty(networks, "No external networks found")
383
384 nonexternal = [net for net in body['networks'] if
385 not net['router:external']]
386 self.assertEmpty(nonexternal, "Found non-external networks"
387 " in filtered list (%s)." % nonexternal)
388 self.assertIn(CONF.network.public_network_id, networks)
389
390 subnets_iter = (network['subnets'] for network in body['networks'])
391 # subnets_iter is a list (iterator) of lists. This flattens it to a
392 # list of UUIDs
393 public_subnets_iter = itertools.chain(*subnets_iter)
David Kranz34e88122014-12-11 15:24:05 -0500394 body = self.client.list_subnets()
Yair Friedbfdfc752014-09-28 13:56:45 +0300395 subnets = [sub['id'] for sub in body['subnets']
396 if sub['id'] in public_subnets_iter]
397 self.assertEmpty(subnets, "Public subnets visible")
398
raiesmh086b055e22013-09-16 12:59:57 +0530399
Ken'ichi Ohmichi91c675d2014-02-06 02:15:21 +0900400class BulkNetworkOpsTestJSON(base.BaseNetworkTest):
raiesmh086b055e22013-09-16 12:59:57 +0530401
402 """
403 Tests the following operations in the Neutron API using the REST client for
404 Neutron:
405
406 bulk network creation
407 bulk subnet creation
Eugene Nikanorove9d255a2013-12-18 16:31:42 +0400408 bulk port creation
raiesmh086b055e22013-09-16 12:59:57 +0530409 list tenant's networks
410
411 v2.0 of the Neutron API is assumed. It is also assumed that the following
412 options are defined in the [network] section of etc/tempest.conf:
413
414 tenant_network_cidr with a block of cidr's from which smaller blocks
415 can be allocated for tenant networks
416
417 tenant_network_mask_bits with the mask bits to be used to partition the
418 block defined by tenant-network_cidr
419 """
420
raiesmh086b055e22013-09-16 12:59:57 +0530421 def _delete_networks(self, created_networks):
422 for n in created_networks:
Rohan Kanadeeeb21642014-08-14 12:00:26 +0200423 self.client.delete_network(n['id'])
raiesmh086b055e22013-09-16 12:59:57 +0530424 # Asserting that the networks are not found in the list after deletion
David Kranz34e88122014-12-11 15:24:05 -0500425 body = self.client.list_networks()
Mark Maglana5885eb32014-02-28 10:57:34 -0800426 networks_list = [network['id'] for network in body['networks']]
raiesmh086b055e22013-09-16 12:59:57 +0530427 for n in created_networks:
428 self.assertNotIn(n['id'], networks_list)
429
430 def _delete_subnets(self, created_subnets):
431 for n in created_subnets:
Rohan Kanadeeeb21642014-08-14 12:00:26 +0200432 self.client.delete_subnet(n['id'])
raiesmh086b055e22013-09-16 12:59:57 +0530433 # Asserting that the subnets are not found in the list after deletion
David Kranz34e88122014-12-11 15:24:05 -0500434 body = self.client.list_subnets()
Mark Maglana5885eb32014-02-28 10:57:34 -0800435 subnets_list = [subnet['id'] for subnet in body['subnets']]
raiesmh086b055e22013-09-16 12:59:57 +0530436 for n in created_subnets:
437 self.assertNotIn(n['id'], subnets_list)
438
439 def _delete_ports(self, created_ports):
440 for n in created_ports:
Rohan Kanadeeeb21642014-08-14 12:00:26 +0200441 self.client.delete_port(n['id'])
raiesmh086b055e22013-09-16 12:59:57 +0530442 # Asserting that the ports are not found in the list after deletion
David Kranz34e88122014-12-11 15:24:05 -0500443 body = self.client.list_ports()
Mark Maglana5885eb32014-02-28 10:57:34 -0800444 ports_list = [port['id'] for port in body['ports']]
raiesmh086b055e22013-09-16 12:59:57 +0530445 for n in created_ports:
446 self.assertNotIn(n['id'], ports_list)
447
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900448 @test.attr(type='smoke')
Nayna Patelb03eab42013-08-08 08:58:48 +0000449 def test_bulk_create_delete_network(self):
450 # Creates 2 networks in one request
Masayuki Igawa259c1132013-10-31 17:48:44 +0900451 network_names = [data_utils.rand_name('network-'),
452 data_utils.rand_name('network-')]
David Kranz34e88122014-12-11 15:24:05 -0500453 body = self.client.create_bulk_network(network_names)
Nayna Patelb03eab42013-08-08 08:58:48 +0000454 created_networks = body['networks']
Nayna Patelb03eab42013-08-08 08:58:48 +0000455 self.addCleanup(self._delete_networks, created_networks)
456 # Asserting that the networks are found in the list after creation
David Kranz34e88122014-12-11 15:24:05 -0500457 body = self.client.list_networks()
Mark Maglana5885eb32014-02-28 10:57:34 -0800458 networks_list = [network['id'] for network in body['networks']]
Nayna Patelb03eab42013-08-08 08:58:48 +0000459 for n in created_networks:
460 self.assertIsNotNone(n['id'])
461 self.assertIn(n['id'], networks_list)
raiesmh0867698322013-08-20 13:09:01 +0530462
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900463 @test.attr(type='smoke')
raiesmh082d5c6512013-09-06 15:35:05 +0530464 def test_bulk_create_delete_subnet(self):
Assaf Mullere4f78992014-06-19 17:32:14 +0300465 networks = [self.create_network(), self.create_network()]
raiesmh082d5c6512013-09-06 15:35:05 +0530466 # Creates 2 subnets in one request
Matthew Treinish03b48df2014-01-29 16:59:49 +0000467 cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
468 mask_bits = CONF.network.tenant_network_mask_bits
Mark Maglana5885eb32014-02-28 10:57:34 -0800469 cidrs = [subnet_cidr for subnet_cidr in cidr.subnet(mask_bits)]
Mark Maglana5885eb32014-02-28 10:57:34 -0800470 names = [data_utils.rand_name('subnet-') for i in range(len(networks))]
471 subnets_list = []
raiesmh082d5c6512013-09-06 15:35:05 +0530472 # TODO(raies): "for IPv6, version list [4, 6] will be used.
473 # and cidr for IPv6 will be of IPv6"
474 ip_version = [4, 4]
475 for i in range(len(names)):
476 p1 = {
Assaf Mullere4f78992014-06-19 17:32:14 +0300477 'network_id': networks[i]['id'],
raiesmh082d5c6512013-09-06 15:35:05 +0530478 'cidr': str(cidrs[(i)]),
479 'name': names[i],
480 'ip_version': ip_version[i]
481 }
Mark Maglana5885eb32014-02-28 10:57:34 -0800482 subnets_list.append(p1)
483 del subnets_list[1]['name']
David Kranz34e88122014-12-11 15:24:05 -0500484 body = self.client.create_bulk_subnet(subnets_list)
raiesmh082d5c6512013-09-06 15:35:05 +0530485 created_subnets = body['subnets']
486 self.addCleanup(self._delete_subnets, created_subnets)
raiesmh082d5c6512013-09-06 15:35:05 +0530487 # Asserting that the subnets are found in the list after creation
David Kranz34e88122014-12-11 15:24:05 -0500488 body = self.client.list_subnets()
Mark Maglana5885eb32014-02-28 10:57:34 -0800489 subnets_list = [subnet['id'] for subnet in body['subnets']]
raiesmh082d5c6512013-09-06 15:35:05 +0530490 for n in created_subnets:
491 self.assertIsNotNone(n['id'])
492 self.assertIn(n['id'], subnets_list)
493
Masayuki Igawa6d495d62014-03-19 16:38:57 +0900494 @test.attr(type='smoke')
raiesmh082d5c6512013-09-06 15:35:05 +0530495 def test_bulk_create_delete_port(self):
Assaf Mullere4f78992014-06-19 17:32:14 +0300496 networks = [self.create_network(), self.create_network()]
raiesmh082d5c6512013-09-06 15:35:05 +0530497 # Creates 2 ports in one request
Mark Maglana5885eb32014-02-28 10:57:34 -0800498 names = [data_utils.rand_name('port-') for i in range(len(networks))]
raiesmh082d5c6512013-09-06 15:35:05 +0530499 port_list = []
500 state = [True, False]
501 for i in range(len(names)):
502 p1 = {
Assaf Mullere4f78992014-06-19 17:32:14 +0300503 'network_id': networks[i]['id'],
raiesmh082d5c6512013-09-06 15:35:05 +0530504 'name': names[i],
505 'admin_state_up': state[i],
506 }
507 port_list.append(p1)
508 del port_list[1]['name']
David Kranz34e88122014-12-11 15:24:05 -0500509 body = self.client.create_bulk_port(port_list)
raiesmh082d5c6512013-09-06 15:35:05 +0530510 created_ports = body['ports']
511 self.addCleanup(self._delete_ports, created_ports)
raiesmh082d5c6512013-09-06 15:35:05 +0530512 # Asserting that the ports are found in the list after creation
David Kranz34e88122014-12-11 15:24:05 -0500513 body = self.client.list_ports()
Mark Maglana5885eb32014-02-28 10:57:34 -0800514 ports_list = [port['id'] for port in body['ports']]
raiesmh082d5c6512013-09-06 15:35:05 +0530515 for n in created_ports:
516 self.assertIsNotNone(n['id'])
517 self.assertIn(n['id'], ports_list)
518
raiesmh0867698322013-08-20 13:09:01 +0530519
Henry Gessauffda37a2014-01-16 11:17:55 -0500520class NetworksIpV6TestJSON(NetworksTestJSON):
521 _ip_version = 6
Henry Gessauffda37a2014-01-16 11:17:55 -0500522
Edgar Magana6a9ac342014-01-16 13:52:49 -0800523 @test.attr(type='smoke')
524 def test_create_delete_subnet_with_gw(self):
sridhargaddamea73d532014-05-13 14:48:30 +0530525 net = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
526 gateway = str(netaddr.IPAddress(net.first + 2))
Edgar Magana6a9ac342014-01-16 13:52:49 -0800527 name = data_utils.rand_name('network-')
Rohan Kanade35589aa2014-08-19 14:56:12 +0200528 network = self.create_network(network_name=name)
Edgar Magana6a9ac342014-01-16 13:52:49 -0800529 subnet = self.create_subnet(network, gateway)
530 # Verifies Subnet GW in IPv6
531 self.assertEqual(subnet['gateway_ip'], gateway)
Edgar Magana6a9ac342014-01-16 13:52:49 -0800532
533 @test.attr(type='smoke')
Sergey Shnaidman18cf5972014-09-02 22:05:00 +0400534 def test_create_delete_subnet_with_default_gw(self):
sridhargaddamea73d532014-05-13 14:48:30 +0530535 net = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
536 gateway_ip = str(netaddr.IPAddress(net.first + 1))
Edgar Magana6a9ac342014-01-16 13:52:49 -0800537 name = data_utils.rand_name('network-')
Rohan Kanade35589aa2014-08-19 14:56:12 +0200538 network = self.create_network(network_name=name)
Edgar Magana6a9ac342014-01-16 13:52:49 -0800539 subnet = self.create_subnet(network)
540 # Verifies Subnet GW in IPv6
sridhargaddamea73d532014-05-13 14:48:30 +0530541 self.assertEqual(subnet['gateway_ip'], gateway_ip)
Edgar Magana6a9ac342014-01-16 13:52:49 -0800542
Sergey Shnaidman18cf5972014-09-02 22:05:00 +0400543 @test.attr(type='smoke')
544 def test_create_list_subnet_with_no_gw64_one_network(self):
545 name = data_utils.rand_name('network-')
546 network = self.create_network(name)
547 ipv6_gateway = self.subnet_dict(['gateway'])['gateway']
548 subnet1 = self.create_subnet(network,
549 ip_version=6,
550 gateway=ipv6_gateway)
551 self.assertEqual(netaddr.IPNetwork(subnet1['cidr']).version, 6,
552 'The created subnet is not IPv6')
553 subnet2 = self.create_subnet(network,
554 gateway=None,
555 ip_version=4)
556 self.assertEqual(netaddr.IPNetwork(subnet2['cidr']).version, 4,
557 'The created subnet is not IPv4')
558 # Verifies Subnet GW is set in IPv6
559 self.assertEqual(subnet1['gateway_ip'], ipv6_gateway)
560 # Verifies Subnet GW is None in IPv4
561 self.assertEqual(subnet2['gateway_ip'], None)
562 # Verifies all 2 subnets in the same network
David Kranz34e88122014-12-11 15:24:05 -0500563 body = self.client.list_subnets()
Sergey Shnaidman18cf5972014-09-02 22:05:00 +0400564 subnets = [sub['id'] for sub in body['subnets']
565 if sub['network_id'] == network['id']]
566 test_subnet_ids = [sub['id'] for sub in (subnet1, subnet2)]
567 self.assertItemsEqual(subnets,
568 test_subnet_ids,
569 'Subnet are not in the same network')
570
Sergey She757c332014-11-25 01:16:32 +0300571
572class NetworksIpV6TestAttrs(NetworksIpV6TestJSON):
573
574 @classmethod
575 def resource_setup(cls):
576 if not CONF.network_feature_enabled.ipv6_subnet_attributes:
577 raise cls.skipException("IPv6 extended attributes for "
578 "subnets not available")
579 super(NetworksIpV6TestAttrs, cls).resource_setup()
580
Sean M. Collinsdd27a4d2014-05-13 10:33:15 -0400581 @test.attr(type='smoke')
Sergey Shnaidman18cf5972014-09-02 22:05:00 +0400582 def test_create_delete_subnet_with_v6_attributes_stateful(self):
Rohan Kanade35589aa2014-08-19 14:56:12 +0200583 self._create_verify_delete_subnet(
584 gateway=self._subnet_data[self._ip_version]['gateway'],
Sergey Shnaidman18cf5972014-09-02 22:05:00 +0400585 ipv6_ra_mode='dhcpv6-stateful',
586 ipv6_address_mode='dhcpv6-stateful')
587
Sergey Shnaidman18cf5972014-09-02 22:05:00 +0400588 @test.attr(type='smoke')
589 def test_create_delete_subnet_with_v6_attributes_slaac(self):
590 self._create_verify_delete_subnet(
Rohan Kanade35589aa2014-08-19 14:56:12 +0200591 ipv6_ra_mode='slaac',
592 ipv6_address_mode='slaac')
Sean M. Collinsdd27a4d2014-05-13 10:33:15 -0400593
Sergey Shnaidman18cf5972014-09-02 22:05:00 +0400594 @test.attr(type='smoke')
595 def test_create_delete_subnet_with_v6_attributes_stateless(self):
596 self._create_verify_delete_subnet(
597 ipv6_ra_mode='dhcpv6-stateless',
598 ipv6_address_mode='dhcpv6-stateless')
Sergey She757c332014-11-25 01:16:32 +0300599
600 def _test_delete_subnet_with_ports(self, mode):
601 """Create subnet and delete it with existing ports"""
602 slaac_network = self.create_network()
603 subnet_slaac = self.create_subnet(slaac_network,
604 **{'ipv6_ra_mode': mode,
605 'ipv6_address_mode': mode})
606 port = self.create_port(slaac_network)
607 self.assertIsNotNone(port['fixed_ips'][0]['ip_address'])
608 self.client.delete_subnet(subnet_slaac['id'])
609 self.subnets.pop()
610 subnets = self.client.list_subnets()
611 subnet_ids = [subnet['id'] for subnet in subnets['subnets']]
612 self.assertNotIn(subnet_slaac['id'], subnet_ids,
613 "Subnet wasn't deleted")
614 self.assertRaisesRegexp(
Masayuki Igawad9388762015-01-20 14:56:42 +0900615 lib_exc.Conflict,
Sergey She757c332014-11-25 01:16:32 +0300616 "There are one or more ports still in use on the network",
617 self.client.delete_network,
618 slaac_network['id'])
619
620 @test.attr(type='smoke')
621 def test_create_delete_slaac_subnet_with_ports(self):
622 """Test deleting subnet with SLAAC ports
623
624 Create subnet with SLAAC, create ports in network
625 and then you shall be able to delete subnet without port
626 deletion. But you still can not delete the network.
627 """
628 self._test_delete_subnet_with_ports("slaac")
629
630 @test.attr(type='smoke')
631 def test_create_delete_stateless_subnet_with_ports(self):
632 """Test deleting subnet with DHCPv6 stateless ports
633
634 Create subnet with DHCPv6 stateless, create ports in network
635 and then you shall be able to delete subnet without port
636 deletion. But you still can not delete the network.
637 """
638 self._test_delete_subnet_with_ports("dhcpv6-stateless")