blob: 6b36d9fdd87f5138a9eafefe0325d8db50849e60 [file] [log] [blame]
Andrea Frittolif4510a12017-03-07 19:17:11 +00001# Copyright 2012 OpenStack Foundation
2# Copyright 2013 IBM Corp.
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
Andrea Frittolif4510a12017-03-07 19:17:11 +000017import netaddr
18from oslo_log import log
Goutham Pacha Ravi37ee6772019-10-18 12:53:22 -070019from oslo_utils import uuidutils
Andrea Frittolif4510a12017-03-07 19:17:11 +000020from tempest.common import image as common_image
Andrea Frittolif4510a12017-03-07 19:17:11 +000021from tempest import config
Ken'ichi Ohmichi02d1f242017-03-12 18:56:27 -070022from tempest.lib.common.utils import data_utils
Andrea Frittolif4510a12017-03-07 19:17:11 +000023from tempest.lib.common.utils import test_utils
24from tempest.lib import exceptions as lib_exc
Roman Popelka290ef292022-02-28 10:41:04 +010025from tempest.scenario import manager
Andrea Frittolif4510a12017-03-07 19:17:11 +000026
27CONF = config.CONF
28
29LOG = log.getLogger(__name__)
30
31
Roman Popelka1118f3e2022-03-21 09:18:53 +010032class ScenarioTest(manager.NetworkScenarioTest):
Andrea Frittolif4510a12017-03-07 19:17:11 +000033 """Base class for scenario tests. Uses tempest own clients. """
34
35 credentials = ['primary']
36
37 @classmethod
38 def setup_clients(cls):
39 super(ScenarioTest, cls).setup_clients()
40 # Clients (in alphabetical order)
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070041 cls.flavors_client = cls.os_primary.flavors_client
Andrea Frittolif4510a12017-03-07 19:17:11 +000042 cls.compute_floating_ips_client = (
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070043 cls.os_primary.compute_floating_ips_client)
Andrea Frittolif4510a12017-03-07 19:17:11 +000044 if CONF.service_available.glance:
45 # Check if glance v1 is available to determine which client to use.
46 if CONF.image_feature_enabled.api_v1:
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070047 cls.image_client = cls.os_primary.image_client
Andrea Frittolif4510a12017-03-07 19:17:11 +000048 elif CONF.image_feature_enabled.api_v2:
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070049 cls.image_client = cls.os_primary.image_client_v2
Andrea Frittolif4510a12017-03-07 19:17:11 +000050 else:
51 raise lib_exc.InvalidConfiguration(
52 'Either api_v1 or api_v2 must be True in '
53 '[image-feature-enabled].')
54 # Compute image client
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070055 cls.compute_images_client = cls.os_primary.compute_images_client
56 cls.keypairs_client = cls.os_primary.keypairs_client
Andrea Frittolif4510a12017-03-07 19:17:11 +000057 # Nova security groups client
58 cls.compute_security_groups_client = (
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070059 cls.os_primary.compute_security_groups_client)
Andrea Frittolif4510a12017-03-07 19:17:11 +000060 cls.compute_security_group_rules_client = (
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070061 cls.os_primary.compute_security_group_rules_client)
62 cls.servers_client = cls.os_primary.servers_client
63 cls.interface_client = cls.os_primary.interfaces_client
Andrea Frittolif4510a12017-03-07 19:17:11 +000064 # Neutron network client
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070065 cls.networks_client = cls.os_primary.networks_client
66 cls.ports_client = cls.os_primary.ports_client
67 cls.routers_client = cls.os_primary.routers_client
68 cls.subnets_client = cls.os_primary.subnets_client
69 cls.floating_ips_client = cls.os_primary.floating_ips_client
70 cls.security_groups_client = cls.os_primary.security_groups_client
Andrea Frittolif4510a12017-03-07 19:17:11 +000071 cls.security_group_rules_client = (
Vu Cong Tuandb2abab2017-06-21 20:38:39 +070072 cls.os_primary.security_group_rules_client)
Andrea Frittolif4510a12017-03-07 19:17:11 +000073
Andrea Frittolif4510a12017-03-07 19:17:11 +000074 # ## Test functions library
75 #
76 # The create_[resource] functions only return body and discard the
77 # resp part which is not used in scenario tests
78
Andrea Frittolif4510a12017-03-07 19:17:11 +000079 def _create_loginable_secgroup_rule(self, secgroup_id=None):
80 _client = self.compute_security_groups_client
81 _client_rules = self.compute_security_group_rules_client
82 if secgroup_id is None:
83 sgs = _client.list_security_groups()['security_groups']
84 for sg in sgs:
85 if sg['name'] == 'default':
86 secgroup_id = sg['id']
87
88 # These rules are intended to permit inbound ssh and icmp
89 # traffic from all sources, so no group_id is provided.
90 # Setting a group_id would only permit traffic from ports
91 # belonging to the same security group.
92 rulesets = [
93 {
94 # ssh
95 'ip_protocol': 'tcp',
96 'from_port': 22,
97 'to_port': 22,
98 'cidr': '0.0.0.0/0',
99 },
100 {
101 # ping
102 'ip_protocol': 'icmp',
103 'from_port': -1,
104 'to_port': -1,
105 'cidr': '0.0.0.0/0',
106 }
107 ]
108 rules = list()
109 for ruleset in rulesets:
110 sg_rule = _client_rules.create_security_group_rule(
111 parent_group_id=secgroup_id, **ruleset)['security_group_rule']
112 rules.append(sg_rule)
113 return rules
114
115 def _create_security_group(self):
116 # Create security group
117 sg_name = data_utils.rand_name(self.__class__.__name__)
118 sg_desc = sg_name + " description"
119 secgroup = self.compute_security_groups_client.create_security_group(
120 name=sg_name, description=sg_desc)['security_group']
121 self.assertEqual(secgroup['name'], sg_name)
122 self.assertEqual(secgroup['description'], sg_desc)
123 self.addCleanup(
124 test_utils.call_and_ignore_notfound_exc,
125 self.compute_security_groups_client.delete_security_group,
126 secgroup['id'])
127
128 # Add rules to the security group
129 self._create_loginable_secgroup_rule(secgroup['id'])
130
131 return secgroup
132
Andrea Frittolif4510a12017-03-07 19:17:11 +0000133 def _image_create(self, name, fmt, path,
134 disk_format=None, properties=None):
135 if properties is None:
136 properties = {}
137 name = data_utils.rand_name('%s-' % name)
138 params = {
139 'name': name,
140 'container_format': fmt,
141 'disk_format': disk_format or fmt,
142 }
143 if CONF.image_feature_enabled.api_v1:
144 params['is_public'] = 'False'
145 params['properties'] = properties
146 params = {'headers': common_image.image_meta_to_headers(**params)}
147 else:
148 params['visibility'] = 'private'
149 # Additional properties are flattened out in the v2 API.
150 params.update(properties)
151 body = self.image_client.create_image(**params)
152 image = body['image'] if 'image' in body else body
153 self.addCleanup(self.image_client.delete_image, image['id'])
154 self.assertEqual("queued", image['status'])
155 with open(path, 'rb') as image_file:
156 if CONF.image_feature_enabled.api_v1:
157 self.image_client.update_image(image['id'], data=image_file)
158 else:
159 self.image_client.store_image_file(image['id'], image_file)
160 return image['id']
161
162 def glance_image_create(self):
Martin Kopec258cc6c2020-04-15 22:55:25 +0000163 img_path = CONF.scenario.img_file
Andrea Frittolif4510a12017-03-07 19:17:11 +0000164 img_container_format = CONF.scenario.img_container_format
165 img_disk_format = CONF.scenario.img_disk_format
166 img_properties = CONF.scenario.img_properties
167 LOG.debug("paths: img: %s, container_format: %s, disk_format: %s, "
Martin Kopec258cc6c2020-04-15 22:55:25 +0000168 "properties: %s",
Andrea Frittolif4510a12017-03-07 19:17:11 +0000169 img_path, img_container_format, img_disk_format,
Martin Kopec258cc6c2020-04-15 22:55:25 +0000170 img_properties)
171 image = self._image_create('scenario-img',
172 img_container_format,
173 img_path,
174 disk_format=img_disk_format,
175 properties=img_properties)
Andrea Frittolif4510a12017-03-07 19:17:11 +0000176 LOG.debug("image:%s", image)
177
178 return image
179
Andrea Frittolif4510a12017-03-07 19:17:11 +0000180 def _log_net_info(self, exc):
181 # network debug is called as part of ssh init
182 if not isinstance(exc, lib_exc.SSHTimeout):
183 LOG.debug('Network information on a devstack host')
184
Andrea Frittolif4510a12017-03-07 19:17:11 +0000185
186class NetworkScenarioTest(ScenarioTest):
187 """Base class for network scenario tests.
188
189 This class provide helpers for network scenario tests, using the neutron
190 API. Helpers from ancestor which use the nova network API are overridden
191 with the neutron API.
192
193 This Class also enforces using Neutron instead of novanetwork.
194 Subclassed tests will be skipped if Neutron is not enabled
195
196 """
197
198 credentials = ['primary', 'admin']
199
200 @classmethod
201 def skip_checks(cls):
202 super(NetworkScenarioTest, cls).skip_checks()
203 if not CONF.service_available.neutron:
204 raise cls.skipException('Neutron not available')
205
Andrea Frittolif4510a12017-03-07 19:17:11 +0000206 def _create_subnet(self, network, subnets_client=None,
207 routers_client=None, namestart='subnet-smoke',
208 **kwargs):
209 """Create a subnet for the given network
210
211 within the cidr block configured for tenant networks.
212 """
213 if not subnets_client:
214 subnets_client = self.subnets_client
215 if not routers_client:
216 routers_client = self.routers_client
217
218 def cidr_in_use(cidr, tenant_id):
219 """Check cidr existence
220
221 :returns: True if subnet with cidr already exist in tenant
222 False else
223 """
Vu Cong Tuan99751862017-06-23 19:46:40 +0700224 cidr_in_use = self.os_admin.subnets_client.list_subnets(
Andrea Frittolif4510a12017-03-07 19:17:11 +0000225 tenant_id=tenant_id, cidr=cidr)['subnets']
226 return len(cidr_in_use) != 0
227
Rodrigo Barbieri797257e2017-11-21 11:00:45 -0200228 def _make_create_subnet_request(namestart, network,
229 ip_version, subnets_client, **kwargs):
Andrea Frittolif4510a12017-03-07 19:17:11 +0000230
231 subnet = dict(
232 name=data_utils.rand_name(namestart),
233 network_id=network['id'],
234 tenant_id=network['tenant_id'],
Andrea Frittolif4510a12017-03-07 19:17:11 +0000235 ip_version=ip_version,
236 **kwargs
237 )
Rodrigo Barbieri797257e2017-11-21 11:00:45 -0200238
239 if ip_version == 6:
240 subnet['ipv6_address_mode'] = 'slaac'
241 subnet['ipv6_ra_mode'] = 'slaac'
242
Andrea Frittolif4510a12017-03-07 19:17:11 +0000243 try:
Rodrigo Barbieri797257e2017-11-21 11:00:45 -0200244 return subnets_client.create_subnet(**subnet)
Andrea Frittolif4510a12017-03-07 19:17:11 +0000245 except lib_exc.Conflict as e:
haixin48895812020-09-30 13:50:37 +0800246 if 'overlaps with another subnet' not in str(e):
Andrea Frittolif4510a12017-03-07 19:17:11 +0000247 raise
Rodrigo Barbieri797257e2017-11-21 11:00:45 -0200248
249 result = None
250 str_cidr = None
251
252 use_default_subnetpool = kwargs.get('use_default_subnetpool', False)
253
254 ip_version = kwargs.pop('ip_version', 4)
255
256 if not use_default_subnetpool:
257
258 if ip_version == 6:
259 tenant_cidr = netaddr.IPNetwork(
260 CONF.network.project_network_v6_cidr)
261 num_bits = CONF.network.project_network_v6_mask_bits
262 else:
263 tenant_cidr = netaddr.IPNetwork(
264 CONF.network.project_network_cidr)
265 num_bits = CONF.network.project_network_mask_bits
266
267 # Repeatedly attempt subnet creation with sequential cidr
268 # blocks until an unallocated block is found.
269 for subnet_cidr in tenant_cidr.subnet(num_bits):
270 str_cidr = str(subnet_cidr)
271 if cidr_in_use(str_cidr, tenant_id=network['tenant_id']):
272 continue
273
274 result = _make_create_subnet_request(
275 namestart, network, ip_version, subnets_client,
276 cidr=str_cidr, **kwargs)
277 if result is not None:
278 break
279 else:
280 result = _make_create_subnet_request(
281 namestart, network, ip_version, subnets_client,
282 **kwargs)
283
284 self.assertIsNotNone(result)
Andrea Frittolif4510a12017-03-07 19:17:11 +0000285
286 subnet = result['subnet']
Rodrigo Barbieri797257e2017-11-21 11:00:45 -0200287 if str_cidr is not None:
288 self.assertEqual(subnet['cidr'], str_cidr)
Andrea Frittolif4510a12017-03-07 19:17:11 +0000289
290 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
291 subnets_client.delete_subnet, subnet['id'])
292
293 return subnet
294
Goutham Pacha Ravi37ee6772019-10-18 12:53:22 -0700295 def _get_network_by_name_or_id(self, identifier):
296
297 if uuidutils.is_uuid_like(identifier):
298 return self.os_admin.networks_client.show_network(
299 identifier)['network']
300
301 networks = self.os_admin.networks_client.list_networks(
302 name=identifier)['networks']
303 self.assertNotEqual(len(networks), 0,
304 "Unable to get network by name: %s" % identifier)
305 return networks[0]
306
307 def get_networks(self):
308 return self.os_admin.networks_client.list_networks()['networks']
Andrea Frittolif4510a12017-03-07 19:17:11 +0000309
310 def create_floating_ip(self, thing, external_network_id=None,
lkuchlan7636a1f2020-04-30 16:13:13 +0300311 port_id=None, ip_addr=None, client=None):
Andrea Frittolif4510a12017-03-07 19:17:11 +0000312 """Create a floating IP and associates to a resource/port on Neutron"""
313 if not external_network_id:
314 external_network_id = CONF.network.public_network_id
315 if not client:
316 client = self.floating_ips_client
317 if not port_id:
Roman Popelkaf880ce32022-03-22 13:26:51 +0100318 port_id, ip4 = self.get_server_port_id_and_ip4(thing,
319 ip_addr=ip_addr)
Andrea Frittolif4510a12017-03-07 19:17:11 +0000320 else:
321 ip4 = None
322 result = client.create_floatingip(
323 floating_network_id=external_network_id,
324 port_id=port_id,
325 tenant_id=thing['tenant_id'],
326 fixed_ip_address=ip4
327 )
328 floating_ip = result['floatingip']
329 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
330 client.delete_floatingip,
331 floating_ip['id'])
332 return floating_ip
333
334 def _associate_floating_ip(self, floating_ip, server):
Roman Popelkaf880ce32022-03-22 13:26:51 +0100335 port_id, _ = self.get_server_port_id_and_ip4(server)
Andrea Frittolif4510a12017-03-07 19:17:11 +0000336 kwargs = dict(port_id=port_id)
337 floating_ip = self.floating_ips_client.update_floatingip(
338 floating_ip['id'], **kwargs)['floatingip']
339 self.assertEqual(port_id, floating_ip['port_id'])
340 return floating_ip
341
Andrea Frittolif4510a12017-03-07 19:17:11 +0000342 def check_floating_ip_status(self, floating_ip, status):
343 """Verifies floatingip reaches the given status
344
345 :param dict floating_ip: floating IP dict to check status
346 :param status: target status
347 :raises: AssertionError if status doesn't match
348 """
349 floatingip_id = floating_ip['id']
350
351 def refresh():
352 result = (self.floating_ips_client.
353 show_floatingip(floatingip_id)['floatingip'])
354 return status == result['status']
355
356 test_utils.call_until_true(refresh,
357 CONF.network.build_timeout,
358 CONF.network.build_interval)
359 floating_ip = self.floating_ips_client.show_floatingip(
360 floatingip_id)['floatingip']
361 self.assertEqual(status, floating_ip['status'],
362 message="FloatingIP: {fp} is at status: {cst}. "
363 "failed to reach status: {st}"
364 .format(fp=floating_ip, cst=floating_ip['status'],
365 st=status))
366 LOG.info("FloatingIP: {fp} is at status: {st}"
367 .format(fp=floating_ip, st=status))
368
369 def _check_tenant_network_connectivity(self, server,
370 username,
371 private_key,
372 should_connect=True,
373 servers_for_debug=None):
374 if not CONF.network.project_networks_reachable:
375 msg = 'Tenant networks not configured to be reachable.'
376 LOG.info(msg)
377 return
378 # The target login is assumed to have been configured for
379 # key-based authentication by cloud-init.
380 try:
381 for ip_addresses in server['addresses'].values():
382 for ip_address in ip_addresses:
383 self.check_vm_connectivity(ip_address['addr'],
384 username,
385 private_key,
Roman Popelkafd4e2f32022-03-21 10:16:30 +0100386 should_connect=should_connect,
387 server=server)
Andrea Frittolif4510a12017-03-07 19:17:11 +0000388 except Exception as e:
389 LOG.exception('Tenant network connectivity check failed')
Roman Popelka164898c2022-03-21 09:12:38 +0100390 self.log_console_output(servers_for_debug)
Andrea Frittolif4510a12017-03-07 19:17:11 +0000391 self._log_net_info(e)
392 raise
393
394 def _check_remote_connectivity(self, source, dest, should_succeed=True,
395 nic=None):
396 """assert ping server via source ssh connection
397
398 Note: This is an internal method. Use check_remote_connectivity
399 instead.
400
401 :param source: RemoteClient: an ssh connection from which to ping
402 :param dest: and IP to ping against
403 :param should_succeed: boolean should ping succeed or not
404 :param nic: specific network interface to ping from
405 """
406 def ping_remote():
407 try:
408 source.ping_host(dest, nic=nic)
409 except lib_exc.SSHExecCommandFailed:
410 LOG.warning('Failed to ping IP: %s via a ssh connection '
411 'from: %s.', dest, source.ssh_client.host)
412 return not should_succeed
413 return should_succeed
414
415 return test_utils.call_until_true(ping_remote,
416 CONF.validation.ping_timeout,
417 1)
418
419 def check_remote_connectivity(self, source, dest, should_succeed=True,
420 nic=None):
421 """assert ping server via source ssh connection
422
423 :param source: RemoteClient: an ssh connection from which to ping
424 :param dest: and IP to ping against
425 :param should_succeed: boolean should ping succeed or not
426 :param nic: specific network interface to ping from
427 """
428 result = self._check_remote_connectivity(source, dest, should_succeed,
429 nic)
430 source_host = source.ssh_client.host
431 if should_succeed:
zhongjun39e9c582017-06-21 15:17:11 +0800432 msg = ("Timed out waiting for %s to become reachable from %s"
433 % (dest, source_host))
Andrea Frittolif4510a12017-03-07 19:17:11 +0000434 else:
435 msg = "%s is reachable from %s" % (dest, source_host)
436 self.assertTrue(result, msg)
437
438 def _create_security_group(self, security_group_rules_client=None,
439 tenant_id=None,
440 namestart='secgroup-smoke',
441 security_groups_client=None):
442 if security_group_rules_client is None:
443 security_group_rules_client = self.security_group_rules_client
444 if security_groups_client is None:
445 security_groups_client = self.security_groups_client
446 if tenant_id is None:
447 tenant_id = security_groups_client.tenant_id
448 secgroup = self._create_empty_security_group(
449 namestart=namestart, client=security_groups_client,
450 tenant_id=tenant_id)
451
452 # Add rules to the security group
453 rules = self._create_loginable_secgroup_rule(
454 security_group_rules_client=security_group_rules_client,
455 secgroup=secgroup,
456 security_groups_client=security_groups_client)
457 for rule in rules:
458 self.assertEqual(tenant_id, rule['tenant_id'])
459 self.assertEqual(secgroup['id'], rule['security_group_id'])
460 return secgroup
461
462 def _create_empty_security_group(self, client=None, tenant_id=None,
463 namestart='secgroup-smoke'):
464 """Create a security group without rules.
465
466 Default rules will be created:
467 - IPv4 egress to any
468 - IPv6 egress to any
469
470 :param tenant_id: secgroup will be created in this tenant
471 :returns: the created security group
472 """
473 if client is None:
474 client = self.security_groups_client
475 if not tenant_id:
476 tenant_id = client.tenant_id
477 sg_name = data_utils.rand_name(namestart)
478 sg_desc = sg_name + " description"
479 sg_dict = dict(name=sg_name,
480 description=sg_desc)
481 sg_dict['tenant_id'] = tenant_id
482 result = client.create_security_group(**sg_dict)
483
484 secgroup = result['security_group']
485 self.assertEqual(secgroup['name'], sg_name)
486 self.assertEqual(tenant_id, secgroup['tenant_id'])
487 self.assertEqual(secgroup['description'], sg_desc)
488
489 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
490 client.delete_security_group, secgroup['id'])
491 return secgroup
492
493 def _default_security_group(self, client=None, tenant_id=None):
494 """Get default secgroup for given tenant_id.
495
496 :returns: default secgroup for given tenant
497 """
498 if client is None:
499 client = self.security_groups_client
500 if not tenant_id:
501 tenant_id = client.tenant_id
502 sgs = [
503 sg for sg in list(client.list_security_groups().values())[0]
504 if sg['tenant_id'] == tenant_id and sg['name'] == 'default'
505 ]
506 msg = "No default security group for tenant %s." % (tenant_id)
507 self.assertGreater(len(sgs), 0, msg)
508 return sgs[0]
509
510 def _create_security_group_rule(self, secgroup=None,
511 sec_group_rules_client=None,
512 tenant_id=None,
513 security_groups_client=None, **kwargs):
514 """Create a rule from a dictionary of rule parameters.
515
516 Create a rule in a secgroup. if secgroup not defined will search for
517 default secgroup in tenant_id.
518
519 :param secgroup: the security group.
520 :param tenant_id: if secgroup not passed -- the tenant in which to
521 search for default secgroup
522 :param kwargs: a dictionary containing rule parameters:
523 for example, to allow incoming ssh:
524 rule = {
525 direction: 'ingress'
526 protocol:'tcp',
527 port_range_min: 22,
528 port_range_max: 22
529 }
530 """
531 if sec_group_rules_client is None:
532 sec_group_rules_client = self.security_group_rules_client
533 if security_groups_client is None:
534 security_groups_client = self.security_groups_client
535 if not tenant_id:
536 tenant_id = security_groups_client.tenant_id
537 if secgroup is None:
538 secgroup = self._default_security_group(
539 client=security_groups_client, tenant_id=tenant_id)
540
541 ruleset = dict(security_group_id=secgroup['id'],
542 tenant_id=secgroup['tenant_id'])
543 ruleset.update(kwargs)
544
545 sg_rule = sec_group_rules_client.create_security_group_rule(**ruleset)
546 sg_rule = sg_rule['security_group_rule']
547
548 self.assertEqual(secgroup['tenant_id'], sg_rule['tenant_id'])
549 self.assertEqual(secgroup['id'], sg_rule['security_group_id'])
550
551 return sg_rule
552
553 def _create_loginable_secgroup_rule(self, security_group_rules_client=None,
554 secgroup=None,
555 security_groups_client=None):
556 """Create loginable security group rule
557
558 This function will create:
559 1. egress and ingress tcp port 22 allow rule in order to allow ssh
560 access for ipv4.
561 2. egress and ingress ipv6 icmp allow rule, in order to allow icmpv6.
562 3. egress and ingress ipv4 icmp allow rule, in order to allow icmpv4.
563 """
564
565 if security_group_rules_client is None:
566 security_group_rules_client = self.security_group_rules_client
567 if security_groups_client is None:
568 security_groups_client = self.security_groups_client
569 rules = []
570 rulesets = [
571 dict(
572 # ssh
573 protocol='tcp',
574 port_range_min=22,
575 port_range_max=22,
576 ),
577 dict(
Rodrigo Barbieri797257e2017-11-21 11:00:45 -0200578 # ipv6-ssh
579 protocol='tcp',
580 port_range_min=22,
581 port_range_max=22,
582 ethertype='IPv6',
583 ),
584 dict(
Andrea Frittolif4510a12017-03-07 19:17:11 +0000585 # ping
586 protocol='icmp',
587 ),
588 dict(
589 # ipv6-icmp for ping6
590 protocol='icmp',
591 ethertype='IPv6',
592 )
593 ]
594 sec_group_rules_client = security_group_rules_client
595 for ruleset in rulesets:
596 for r_direction in ['ingress', 'egress']:
597 ruleset['direction'] = r_direction
598 try:
599 sg_rule = self._create_security_group_rule(
600 sec_group_rules_client=sec_group_rules_client,
601 secgroup=secgroup,
602 security_groups_client=security_groups_client,
603 **ruleset)
604 except lib_exc.Conflict as ex:
605 # if rule already exist - skip rule and continue
606 msg = 'Security group rule already exists'
607 if msg not in ex._error_string:
608 raise ex
609 else:
610 self.assertEqual(r_direction, sg_rule['direction'])
611 rules.append(sg_rule)
612
613 return rules
614
615 def _get_router(self, client=None, tenant_id=None):
616 """Retrieve a router for the given tenant id.
617
618 If a public router has been configured, it will be returned.
619
620 If a public router has not been configured, but a public
621 network has, a tenant router will be created and returned that
622 routes traffic to the public network.
623 """
624 if not client:
625 client = self.routers_client
626 if not tenant_id:
627 tenant_id = client.tenant_id
628 router_id = CONF.network.public_router_id
629 network_id = CONF.network.public_network_id
630 if router_id:
631 body = client.show_router(router_id)
632 return body['router']
633 elif network_id:
634 router = self._create_router(client, tenant_id)
635 kwargs = {'external_gateway_info': dict(network_id=network_id)}
636 router = client.update_router(router['id'], **kwargs)['router']
637 return router
638 else:
639 raise Exception("Neither of 'public_router_id' or "
640 "'public_network_id' has been defined.")
641
642 def _create_router(self, client=None, tenant_id=None,
643 namestart='router-smoke'):
644 if not client:
645 client = self.routers_client
646 if not tenant_id:
647 tenant_id = client.tenant_id
648 name = data_utils.rand_name(namestart)
649 result = client.create_router(name=name,
650 admin_state_up=True,
651 tenant_id=tenant_id)
652 router = result['router']
653 self.assertEqual(router['name'], name)
654 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
655 client.delete_router,
656 router['id'])
657 return router
658
659 def _update_router_admin_state(self, router, admin_state_up):
660 kwargs = dict(admin_state_up=admin_state_up)
661 router = self.routers_client.update_router(
662 router['id'], **kwargs)['router']
663 self.assertEqual(admin_state_up, router['admin_state_up'])
664
665 def create_networks(self, networks_client=None,
666 routers_client=None, subnets_client=None,
667 tenant_id=None, dns_nameservers=None,
668 port_security_enabled=True):
669 """Create a network with a subnet connected to a router.
670
671 The baremetal driver is a special case since all nodes are
672 on the same shared network.
673
674 :param tenant_id: id of tenant to create resources in.
675 :param dns_nameservers: list of dns servers to send to subnet.
676 :returns: network, subnet, router
677 """
678 if CONF.network.shared_physical_network:
679 # NOTE(Shrews): This exception is for environments where tenant
680 # credential isolation is available, but network separation is
681 # not (the current baremetal case). Likely can be removed when
682 # test account mgmt is reworked:
683 # https://blueprints.launchpad.net/tempest/+spec/test-accounts
684 if not CONF.compute.fixed_network_name:
685 m = 'fixed_network_name must be specified in config'
686 raise lib_exc.InvalidConfiguration(m)
Goutham Pacha Ravi37ee6772019-10-18 12:53:22 -0700687 network = self._get_network_by_name_or_id(
Andrea Frittolif4510a12017-03-07 19:17:11 +0000688 CONF.compute.fixed_network_name)
689 router = None
690 subnet = None
691 else:
Roman Popelka1118f3e2022-03-21 09:18:53 +0100692 network = self.create_network(
Andrea Frittolif4510a12017-03-07 19:17:11 +0000693 networks_client=networks_client,
694 tenant_id=tenant_id,
695 port_security_enabled=port_security_enabled)
696 router = self._get_router(client=routers_client,
697 tenant_id=tenant_id)
698 subnet_kwargs = dict(network=network,
699 subnets_client=subnets_client,
700 routers_client=routers_client)
701 # use explicit check because empty list is a valid option
702 if dns_nameservers is not None:
703 subnet_kwargs['dns_nameservers'] = dns_nameservers
704 subnet = self._create_subnet(**subnet_kwargs)
705 if not routers_client:
706 routers_client = self.routers_client
707 router_id = router['id']
708 routers_client.add_router_interface(router_id,
709 subnet_id=subnet['id'])
710
711 # save a cleanup job to remove this association between
712 # router and subnet
713 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
714 routers_client.remove_router_interface, router_id,
715 subnet_id=subnet['id'])
716 return network, subnet, router