blob: bd58da232a32c240c9ee60434f18b4026e4777d8 [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
Gavin Brebner0f465a32013-03-14 13:26:09 +00002# Copyright 2013 Hewlett-Packard Development Company, L.P.
Maru Newby81f07a02012-09-05 20:21:19 -07003# 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.
Yair Fried2d2f3fe2014-02-24 16:19:20 +020016import collections
Yair Fried3097dc12014-01-26 08:46:43 +020017import re
Matthew Treinish96e9e882014-06-09 18:37:19 -040018
Doug Hellmann583ce2c2015-03-11 14:55:46 +000019from oslo_log import log as logging
Adam Gandelman7186f7a2014-07-23 09:28:56 -040020import testtools
Yair Fried3097dc12014-01-26 08:46:43 +020021
Andrea Frittolicd368412017-08-14 21:37:56 +010022from tempest.common import utils
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +000023from tempest.common import waiters
Matthew Treinishcb569942013-08-09 16:33:44 -040024from tempest import config
Jordan Pittier9e227c52016-02-09 14:35:18 +010025from tempest.lib.common.utils import test_utils
Sean Dague17487fb2016-08-08 10:44:20 -040026from tempest.lib import decorators
guo yunxianebb15f22016-11-01 21:03:35 +080027from tempest.lib import exceptions
Sean Dague6dbc6da2013-05-08 17:49:46 -040028from tempest.scenario import manager
Maru Newby81f07a02012-09-05 20:21:19 -070029
Sean Dague86bd8422013-12-20 09:56:44 -050030CONF = config.CONF
Matthew Treinish2b59f842013-09-09 20:32:51 +000031LOG = logging.getLogger(__name__)
32
Yair Fried2d2f3fe2014-02-24 16:19:20 +020033Floating_IP_tuple = collections.namedtuple('Floating_IP_tuple',
34 ['floating_ip', 'server'])
35
Maru Newby81f07a02012-09-05 20:21:19 -070036
Andrea Frittoli4971fc82014-09-25 10:22:20 +010037class TestNetworkBasicOps(manager.NetworkScenarioTest):
Maru Newby81f07a02012-09-05 20:21:19 -070038
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000039 """The test suite of network basic operations
40
Maru Newby81f07a02012-09-05 20:21:19 -070041 This smoke test suite assumes that Nova has been configured to
Mark McClainf2982e82013-07-06 17:48:03 -040042 boot VM's with Neutron-managed networking, and attempts to
Maru Newby81f07a02012-09-05 20:21:19 -070043 verify network connectivity as follows:
44
Maru Newby81f07a02012-09-05 20:21:19 -070045 There are presumed to be two types of networks: tenant and
46 public. A tenant network may or may not be reachable from the
47 Tempest host. A public network is assumed to be reachable from
48 the Tempest host, and it should be possible to associate a public
49 ('floating') IP address with a tenant ('fixed') IP address to
Chang Bo Guocc1623c2013-09-13 20:11:27 -070050 facilitate external connectivity to a potentially unroutable
Maru Newby81f07a02012-09-05 20:21:19 -070051 tenant IP address.
52
53 This test suite can be configured to test network connectivity to
54 a VM via a tenant network, a public network, or both. If both
55 networking types are to be evaluated, tests that need to be
56 executed remotely on the VM (via ssh) will only be run against
57 one of the networks (to minimize test execution time).
58
59 Determine which types of networks to test as follows:
60
61 * Configure tenant network checks (via the
Sean Dagueed6e5862016-04-04 10:49:13 -040062 'project_networks_reachable' key) if the Tempest host should
Maru Newby81f07a02012-09-05 20:21:19 -070063 have direct connectivity to tenant networks. This is likely to
64 be the case if Tempest is running on the same host as a
65 single-node devstack installation with IP namespaces disabled.
66
67 * Configure checks for a public network if a public network has
68 been configured prior to the test suite being run and if the
69 Tempest host should have connectivity to that public network.
70 Checking connectivity for a public network requires that a
71 value be provided for 'public_network_id'. A value can
72 optionally be provided for 'public_router_id' if tenants will
73 use a shared router to access a public network (as is likely to
74 be the case when IP namespaces are not enabled). If a value is
75 not provided for 'public_router_id', a router will be created
76 for each tenant and use the network identified by
77 'public_network_id' as its gateway.
78
79 """
80
81 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000082 def skip_checks(cls):
83 super(TestNetworkBasicOps, cls).skip_checks()
Federico Ressi2d6bcaa2018-04-11 12:37:36 +020084 if not (CONF.network.project_networks_reachable or
85 CONF.network.public_network_id):
Sean Dagueed6e5862016-04-04 10:49:13 -040086 msg = ('Either project_networks_reachable must be "true", or '
Maru Newby81f07a02012-09-05 20:21:19 -070087 'public_network_id must be defined.')
ivan-zhu1feeb382013-01-24 10:14:39 +080088 raise cls.skipException(msg)
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090089 for ext in ['router', 'security-group']:
Andrea Frittolicd368412017-08-14 21:37:56 +010090 if not utils.is_extension_enabled(ext, 'network'):
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090091 msg = "%s extension not enabled." % ext
92 raise cls.skipException(msg)
Matthew Treinish3312de32017-05-19 12:08:17 -040093 if not CONF.network_feature_enabled.floating_ips:
94 raise cls.skipException("Floating ips are not available")
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000095
96 @classmethod
97 def setup_credentials(cls):
Masayuki Igawa60ea6c52014-10-15 17:32:14 +090098 # Create no network resources for these tests.
99 cls.set_network_resources()
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +0000100 super(TestNetworkBasicOps, cls).setup_credentials()
Maru Newby81f07a02012-09-05 20:21:19 -0700101
Yair Frieded8392f2014-01-15 17:21:35 +0200102 def setUp(self):
103 super(TestNetworkBasicOps, self).setUp()
Yair Fried1fc32a12014-08-04 09:11:30 +0300104 self.keypairs = {}
105 self.servers = []
David Shrewsbury9bac3662014-08-07 15:07:01 -0400106
Yair Fried413bf2d2014-11-19 17:07:11 +0200107 def _setup_network_and_servers(self, **kwargs):
Matt Riedemann17940732015-03-13 14:18:19 +0000108 boot_with_port = kwargs.pop('boot_with_port', False)
Yair Fried413bf2d2014-11-19 17:07:11 +0200109 self.network, self.subnet, self.router = self.create_networks(**kwargs)
David Shrewsbury9bac3662014-08-07 15:07:01 -0400110 self.check_networks()
111
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000112 self.ports = []
zhufl7a8f29d2017-02-17 10:16:45 +0800113 port_id = None
Jordan Pittierf72a1dc2015-08-04 12:50:33 +0000114 if boot_with_port:
Matt Riedemann17940732015-03-13 14:18:19 +0000115 # create a port on the network and boot with that
zhufl1e446b52017-10-16 16:54:57 +0800116 port_id = self.create_port(self.network['id'])['id']
zhufl7a8f29d2017-02-17 10:16:45 +0800117 self.ports.append({'port': port_id})
Matt Riedemann17940732015-03-13 14:18:19 +0000118
zhufl7a8f29d2017-02-17 10:16:45 +0800119 server = self._create_server(self.network, port_id)
zhufl420a0192017-09-28 11:04:50 +0800120 ssh_login = CONF.validation.image_ssh_user
121 for server in self.servers:
122 # call the common method in the parent class
123 self.check_tenant_network_connectivity(
124 server, ssh_login, self._get_server_key(server),
125 servers_for_debug=self.servers)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200126
Yair Friedae0e73d2014-11-24 11:56:26 +0200127 floating_ip = self.create_floating_ip(server)
128 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Maru Newby81f07a02012-09-05 20:21:19 -0700129
Yair Frieded8392f2014-01-15 17:21:35 +0200130 def check_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000131 """Checks that we see the newly created network/subnet/router
132
133 via checking the result of list_[networks,routers,subnets]
Yair Frieded8392f2014-01-15 17:21:35 +0200134 """
135
jeremy.zhang5870ff12017-05-25 11:24:23 +0800136 seen_nets = self.os_admin.networks_client.list_networks()
Jordan Pittier64e6b442017-02-20 19:29:02 +0100137 seen_names = [n['name'] for n in seen_nets['networks']]
138 seen_ids = [n['id'] for n in seen_nets['networks']]
Steve Heyman33735f22016-05-24 09:28:08 -0500139 self.assertIn(self.network['name'], seen_names)
140 self.assertIn(self.network['id'], seen_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200141
David Shrewsbury9bac3662014-08-07 15:07:01 -0400142 if self.subnet:
jeremy.zhang5870ff12017-05-25 11:24:23 +0800143 seen_subnets = self.os_admin.subnets_client.list_subnets()
Jordan Pittier64e6b442017-02-20 19:29:02 +0100144 seen_net_ids = [n['network_id'] for n in seen_subnets['subnets']]
145 seen_subnet_ids = [n['id'] for n in seen_subnets['subnets']]
Steve Heyman33735f22016-05-24 09:28:08 -0500146 self.assertIn(self.network['id'], seen_net_ids)
147 self.assertIn(self.subnet['id'], seen_subnet_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200148
David Shrewsbury9bac3662014-08-07 15:07:01 -0400149 if self.router:
jeremy.zhang5870ff12017-05-25 11:24:23 +0800150 seen_routers = self.os_admin.routers_client.list_routers()
Jordan Pittier64e6b442017-02-20 19:29:02 +0100151 seen_router_ids = [n['id'] for n in seen_routers['routers']]
152 seen_router_names = [n['name'] for n in seen_routers['routers']]
Steve Heyman33735f22016-05-24 09:28:08 -0500153 self.assertIn(self.router['name'],
David Shrewsbury9bac3662014-08-07 15:07:01 -0400154 seen_router_names)
Steve Heyman33735f22016-05-24 09:28:08 -0500155 self.assertIn(self.router['id'],
David Shrewsbury9bac3662014-08-07 15:07:01 -0400156 seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000157
zhufl24208c22016-10-25 15:23:48 +0800158 def _create_server(self, network, port_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +0300159 keypair = self.create_keypair()
160 self.keypairs[keypair['name']] = keypair
Jordan Pittier37b94a02017-02-21 18:11:55 +0100161 security_groups = [
162 {'name': self._create_security_group()['name']}
163 ]
Steve Heyman33735f22016-05-24 09:28:08 -0500164 network = {'uuid': network['id']}
Matt Riedemann17940732015-03-13 14:18:19 +0000165 if port_id is not None:
lanoux5fc14522015-09-21 08:17:35 +0000166 network['port'] = port_id
167
168 server = self.create_server(
lanoux5fc14522015-09-21 08:17:35 +0000169 networks=[network],
170 key_name=keypair['name'],
zhufl13c9c892017-02-10 12:04:07 +0800171 security_groups=security_groups)
Yair Fried1fc32a12014-08-04 09:11:30 +0300172 self.servers.append(server)
173 return server
174
175 def _get_server_key(self, server):
176 return self.keypairs[server['key_name']]['private_key']
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700177
zhufl0ec74c42017-11-15 14:02:28 +0800178 def _check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700179 self, should_connect=True, msg=None,
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000180 should_check_floating_ip_status=True, mtu=None):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000181 """Verifies connectivty to a VM via public network and floating IP
182
Yair Fried45f92952014-06-26 05:19:19 +0300183 and verifies floating IP has resource status is correct.
184
Yair Fried45f92952014-06-26 05:19:19 +0300185 :param should_connect: bool. determines if connectivity check is
186 negative or positive.
187 :param msg: Failure message to add to Error message. Should describe
188 the place in the test scenario where the method was called,
189 to indicate the context of the failure
Alok Maurya6384bbb2014-07-13 06:44:29 -0700190 :param should_check_floating_ip_status: bool. should status of
191 floating_ip be checked or not
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000192 :param mtu: int. MTU network to use for connectivity validation
Yair Fried45f92952014-06-26 05:19:19 +0300193 """
lanoux283273b2015-12-04 03:01:54 -0800194 ssh_login = CONF.validation.image_ssh_user
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200195 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500196 ip_address = floating_ip['floating_ip_address']
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200197 private_key = None
Yair Fried45f92952014-06-26 05:19:19 +0300198 floatingip_status = 'DOWN'
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200199 if should_connect:
Yair Fried1fc32a12014-08-04 09:11:30 +0300200 private_key = self._get_server_key(server)
Yair Fried45f92952014-06-26 05:19:19 +0300201 floatingip_status = 'ACTIVE'
zhufl0ec74c42017-11-15 14:02:28 +0800202
Swaminathan Vasudevandc8bcdb2015-02-28 12:47:21 -0800203 # Check FloatingIP Status before initiating a connection
204 if should_check_floating_ip_status:
205 self.check_floating_ip_status(floating_ip, floatingip_status)
zhufl0ec74c42017-11-15 14:02:28 +0800206
207 message = 'Public network connectivity check failed'
208 if msg:
209 message += '. Reason: %s' % msg
210
211 self.check_vm_connectivity(
212 ip_address, ssh_login, private_key, should_connect,
213 message, server, mtu=mtu)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000214
Yair Fried9a551c42013-12-15 14:59:34 +0200215 def _disassociate_floating_ips(self):
Ferenc Horváthbce1fcf2017-06-07 11:19:51 +0200216 floating_ip, _ = self.floating_ip_tuple
zhuflafe96b82017-09-22 14:25:29 +0800217 floating_ip = self.floating_ips_client.update_floatingip(
218 floating_ip['id'], port_id=None)['floatingip']
219 self.assertIsNone(floating_ip['port_id'])
220 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, None)
Yair Fried9a551c42013-12-15 14:59:34 +0200221
Yair Fried05db2522013-11-18 11:02:10 +0200222 def _reassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200223 floating_ip, server = self.floating_ip_tuple
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200224 # create a new server for the floating ip
zhufl24208c22016-10-25 15:23:48 +0800225 server = self._create_server(self.network)
Soniya Vyasa446d702021-02-23 15:58:53 +0530226 port_id, _ = self.get_server_port_id_and_ip4(server)
zhuflafe96b82017-09-22 14:25:29 +0800227 floating_ip = self.floating_ips_client.update_floatingip(
228 floating_ip['id'], port_id=port_id)['floatingip']
229 self.assertEqual(port_id, floating_ip['port_id'])
230 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Yair Fried05db2522013-11-18 11:02:10 +0200231
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300232 def _create_new_network(self, create_gateway=False):
Marc Koderer410c7822016-11-08 11:47:00 +0100233 self.new_net = self._create_network()
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300234 if create_gateway:
zhufl5b0a52f2017-10-24 15:48:20 +0800235 self.new_subnet = self.create_subnet(
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300236 network=self.new_net)
237 else:
zhufl5b0a52f2017-10-24 15:48:20 +0800238 self.new_subnet = self.create_subnet(
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300239 network=self.new_net,
240 gateway_ip=None)
Yair Fried3097dc12014-01-26 08:46:43 +0200241
242 def _hotplug_server(self):
243 old_floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500244 ip_address = old_floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300245 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100246 ssh_client = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800247 ip_address, private_key=private_key, server=server)
Yair Fried3097dc12014-01-26 08:46:43 +0200248 old_nic_list = self._get_server_nics(ssh_client)
249 # get a port from a list of one item
jeremy.zhang5870ff12017-05-25 11:24:23 +0800250 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100251 device_id=server['id'])['ports']
Yair Fried3097dc12014-01-26 08:46:43 +0200252 self.assertEqual(1, len(port_list))
253 old_port = port_list[0]
David Kranzb2b0c182015-02-18 13:28:19 -0500254 interface = self.interface_client.create_interface(
Ken'ichi Ohmichi9509b962015-07-07 05:30:15 +0000255 server_id=server['id'],
Steve Heyman33735f22016-05-24 09:28:08 -0500256 net_id=self.new_net['id'])['interfaceAttachment']
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -0700257 self.addCleanup(self.ports_client.wait_for_resource_deletion,
258 interface['port_id'])
Jordan Pittier9e227c52016-02-09 14:35:18 +0100259 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Yair Fried1fc32a12014-08-04 09:11:30 +0300260 self.interface_client.delete_interface,
261 server['id'], interface['port_id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200262
263 def check_ports():
Jordan Pittier64e6b442017-02-20 19:29:02 +0100264 self.new_port_list = [
265 port for port in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800266 self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100267 device_id=server['id'])['ports']
268 if port['id'] != old_port['id']
269 ]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200270 return len(self.new_port_list) == 1
Yair Fried3097dc12014-01-26 08:46:43 +0200271
Jordan Pittier35a63752016-08-30 13:09:12 +0200272 if not test_utils.call_until_true(
273 check_ports, CONF.network.build_timeout,
274 CONF.network.build_interval):
Matt Riedemann892094e2015-02-05 07:24:02 -0800275 raise exceptions.TimeoutException(
276 "No new port attached to the server in time (%s sec)! "
277 "Old port: %s. Number of new ports: %d" % (
278 CONF.network.build_timeout, old_port,
279 len(self.new_port_list)))
Steve Heyman33735f22016-05-24 09:28:08 -0500280 new_port = self.new_port_list[0]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200281
282 def check_new_nic():
283 new_nic_list = self._get_server_nics(ssh_client)
284 self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
285 return len(self.diff_list) == 1
286
Jordan Pittier35a63752016-08-30 13:09:12 +0200287 if not test_utils.call_until_true(
288 check_new_nic, CONF.network.build_timeout,
289 CONF.network.build_interval):
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200290 raise exceptions.TimeoutException("Interface not visible on the "
291 "guest after %s sec"
292 % CONF.network.build_timeout)
293
Ferenc Horváthbce1fcf2017-06-07 11:19:51 +0200294 _, new_nic = self.diff_list[0]
Martin Kopec925188d2019-05-07 13:26:34 +0000295 ip_output = ssh_client.exec_command('ip a')
296 ip_address = new_port['fixed_ips'][0]['ip_address']
297 ip_mask = CONF.network.project_network_mask_bits
298 # check if the address is not already in use, if not, set it
299 if ' ' + ip_address + '/' + str(ip_mask) not in ip_output:
Rodolfo Alonso Hernandez15d63092020-03-31 15:34:30 +0000300 try:
301 ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
302 ip_address, ip_mask, new_nic))
303 ssh_client.exec_command("sudo ip link set %s up" % new_nic)
304 except exceptions.SSHExecCommandFailed as exc:
305 if 'RTNETLINK answers: File exists' in str(exc):
306 LOG.debug(
307 'IP address %(ip_address)s is already set in device '
308 '%(device)s\nPrevious "ip a" output: %(ip_output)s',
309 {'ip_address': ip_address, 'device': new_nic,
310 'ip_output': ip_output})
311 else:
312 raise exc
Yair Fried3097dc12014-01-26 08:46:43 +0200313
314 def _get_server_nics(self, ssh_client):
James Pagea9366272017-06-09 12:05:09 +0100315 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+)[@]?.*:')
Ken'ichi Ohmichi84aeba62017-03-01 18:31:20 -0800316 ipatxt = ssh_client.exec_command("ip address")
Yair Fried3097dc12014-01-26 08:46:43 +0200317 return reg.findall(ipatxt)
318
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300319 def _check_network_internal_connectivity(self, network,
320 should_connect=True):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000321 """via ssh check VM internal connectivity:
322
Yair Fried06552292013-11-11 12:10:09 +0200323 - ping internal gateway and DHCP port, implying in-tenant connectivity
324 pinging both, because L3 and DHCP agents might be on different nodes
Tong Liu589f3152016-03-24 05:56:40 +0000325 - ping internal compute port, implying connectivity to other VMs on
326 this network
Yair Fried3097dc12014-01-26 08:46:43 +0200327 """
328 floating_ip, server = self.floating_ip_tuple
329 # get internal ports' ips:
Tong Liu589f3152016-03-24 05:56:40 +0000330 # get all network and compute ports in the new network
Jordan Pittier64e6b442017-02-20 19:29:02 +0100331 internal_ips = (
332 p['fixed_ips'][0]['ip_address'] for p in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800333 self.os_admin.ports_client.list_ports(
Rodolfo Alonso Hernandezc1449d42020-02-15 13:24:28 +0000334 project_id=server['tenant_id'],
Jordan Pittier64e6b442017-02-20 19:29:02 +0100335 network_id=network['id'])['ports']
Tong Liu589f3152016-03-24 05:56:40 +0000336 if p['device_owner'].startswith('network') or
337 p['device_owner'].startswith('compute')
Jordan Pittier64e6b442017-02-20 19:29:02 +0100338 )
Yair Fried3097dc12014-01-26 08:46:43 +0200339
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300340 self._check_server_connectivity(floating_ip,
341 internal_ips,
342 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200343
344 def _check_network_external_connectivity(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000345 """ping default gateway to imply external connectivity"""
Yair Fried06552292013-11-11 12:10:09 +0200346 if not CONF.network.public_network_id:
347 msg = 'public network not defined.'
348 LOG.info(msg)
349 return
350
Andrew Boik4a3daf12015-03-27 01:59:31 -0400351 # We ping the external IP from the instance using its floating IP
352 # which is always IPv4, so we must only test connectivity to
353 # external IPv4 IPs if the external network is dualstack.
Jordan Pittier64e6b442017-02-20 19:29:02 +0100354 v4_subnets = [
jeremy.zhang5870ff12017-05-25 11:24:23 +0800355 s for s in self.os_admin.subnets_client.list_subnets(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100356 network_id=CONF.network.public_network_id)['subnets']
357 if s['ip_version'] == 4
358 ]
Yair Fried06552292013-11-11 12:10:09 +0200359
Lukas Piwowarski2385e042020-01-31 12:28:20 +0000360 if len(v4_subnets) > 1:
361 self.assertTrue(
362 CONF.network.subnet_id,
363 "Found %d subnets. Specify subnet using configuration "
364 "option [network].subnet_id."
365 % len(v4_subnets))
366 subnet = self.os_admin.subnets_client.show_subnet(
367 CONF.network.subnet_id)['subnet']
368 external_ips = [subnet['gateway_ip']]
369 else:
370 external_ips = [v4_subnets[0]['gateway_ip']]
371
Yair Fried06552292013-11-11 12:10:09 +0200372 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
373 external_ips)
374
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300375 def _check_server_connectivity(self, floating_ip, address_list,
376 should_connect=True):
Steve Heyman33735f22016-05-24 09:28:08 -0500377 ip_address = floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300378 private_key = self._get_server_key(self.floating_ip_tuple.server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100379 ssh_source = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800380 ip_address, private_key=private_key,
381 server=self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200382
Yair Fried06552292013-11-11 12:10:09 +0200383 for remote_ip in address_list:
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900384 self.check_remote_connectivity(ssh_source, remote_ip,
385 should_connect)
Yair Fried3097dc12014-01-26 08:46:43 +0200386
zhuflafe96b82017-09-22 14:25:29 +0800387 def _update_router_admin_state(self, router, admin_state_up):
388 kwargs = dict(admin_state_up=admin_state_up)
389 router = self.routers_client.update_router(
390 router['id'], **kwargs)['router']
391 self.assertEqual(admin_state_up, router['admin_state_up'])
392
Jordan Pittier3b46d272017-04-12 16:17:28 +0200393 @decorators.attr(type='smoke')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800394 @decorators.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Andrea Frittolicd368412017-08-14 21:37:56 +0100395 @utils.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000396 def test_network_basic_ops(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000397 """Basic network operation test
398
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600399 For a freshly-booted VM with an IP address ("port") on a given network:
Yair Fried3097dc12014-01-26 08:46:43 +0200400
401 - the Tempest host can ping the IP address. This implies, but
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600402 does not guarantee (see the ssh check that follows), that the
403 VM has been assigned the correct IP address and has
404 connectivity to the Tempest host.
Yair Fried3097dc12014-01-26 08:46:43 +0200405
406 - the Tempest host can perform key-based authentication to an
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600407 ssh server hosted at the IP address. This check guarantees
408 that the IP address is associated with the target VM.
Yair Fried3097dc12014-01-26 08:46:43 +0200409
Yair Fried3097dc12014-01-26 08:46:43 +0200410 - the Tempest host can ssh into the VM via the IP address and
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600411 successfully execute the following:
Yair Fried3097dc12014-01-26 08:46:43 +0200412
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600413 - ping an external IP address, implying external connectivity.
Yair Fried3097dc12014-01-26 08:46:43 +0200414
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600415 - ping an external hostname, implying that dns is correctly
416 configured.
Yair Fried3097dc12014-01-26 08:46:43 +0200417
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600418 - ping an internal IP address, implying connectivity to another
419 VM on the same network.
Yair Fried3097dc12014-01-26 08:46:43 +0200420
Yair Fried06552292013-11-11 12:10:09 +0200421 - detach the floating-ip from the VM and verify that it becomes
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600422 unreachable
Yair Fried06552292013-11-11 12:10:09 +0200423
424 - associate detached floating ip to a new VM and verify connectivity.
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600425 VMs are created with unique keypair so connectivity also asserts
426 that floating IP is associated with the new VM instead of the old
427 one
Yair Fried06552292013-11-11 12:10:09 +0200428
Yair Fried45f92952014-06-26 05:19:19 +0300429 Verifies that floating IP status is updated correctly after each change
Yair Fried3097dc12014-01-26 08:46:43 +0200430 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400431 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800432 self._check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200433 self._check_network_internal_connectivity(network=self.network)
434 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200435 self._disassociate_floating_ips()
zhufl0ec74c42017-11-15 14:02:28 +0800436 self._check_public_network_connectivity(should_connect=False,
437 msg="after disassociate "
438 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200439 self._reassociate_floating_ips()
zhufl0ec74c42017-11-15 14:02:28 +0800440 self._check_public_network_connectivity(should_connect=True,
441 msg="after re-associate "
442 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200443
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800444 @decorators.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
Andrea Frittolicd368412017-08-14 21:37:56 +0100445 @testtools.skipUnless(utils.is_extension_enabled('net-mtu', 'network'),
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000446 'No way to calculate MTU for networks')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200447 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100448 @utils.services('compute', 'network')
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000449 def test_mtu_sized_frames(self):
450 """Validate that network MTU sized frames fit through."""
451 self._setup_network_and_servers()
Ihar Hrachyshkaaca29ed2017-09-25 12:13:53 -0700452 # first check that connectivity works in general for the instance
zhufl0ec74c42017-11-15 14:02:28 +0800453 self._check_public_network_connectivity(should_connect=True)
Ihar Hrachyshkaaca29ed2017-09-25 12:13:53 -0700454 # now that we checked general connectivity, test that full size frames
455 # can also pass between nodes
zhufl0ec74c42017-11-15 14:02:28 +0800456 self._check_public_network_connectivity(
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000457 should_connect=True, mtu=self.network['mtu'])
458
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800459 @decorators.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
Thiago Paiva66cded22016-08-15 14:55:58 -0300460 @testtools.skipIf(CONF.network.shared_physical_network,
461 'Connectivity can only be tested when in a '
462 'multitenant network environment')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200463 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100464 @utils.services('compute', 'network')
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300465 def test_connectivity_between_vms_on_different_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000466 """Test connectivity between VMs on different networks
467
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600468 For a freshly-booted VM with an IP address ("port") on a given network:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300469
470 - the Tempest host can ping the IP address.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300471 - the Tempest host can ssh into the VM via the IP address and
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600472 successfully execute the following:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300473
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600474 - ping an external IP address, implying external connectivity.
475 - ping an external hostname, implying that dns is correctly
476 configured.
477 - ping an internal IP address, implying connectivity to another
478 VM on the same network.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300479
480 - Create another network on the same tenant with subnet, create
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600481 an VM on the new network.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300482
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600483 - Ping the new VM from previous VM failed since the new network
484 was not attached to router yet.
485 - Attach the new network to the router, Ping the new VM from
486 previous VM succeed.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300487
488 """
489 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800490 self._check_public_network_connectivity(should_connect=True)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300491 self._check_network_internal_connectivity(network=self.network)
492 self._check_network_external_connectivity()
493 self._create_new_network(create_gateway=True)
Lucas Alvares Gomesd595c362018-10-16 14:38:11 +0100494 new_server = self._create_server(self.new_net)
495 new_server_ips = [addr['addr'] for addr in
496 new_server['addresses'][self.new_net['name']]]
497
498 # Assert that pinging the new VM fails since the new network is not
499 # connected to a router
500 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
501 new_server_ips, should_connect=False)
Steve Heyman33735f22016-05-24 09:28:08 -0500502 router_id = self.router['id']
503 self.routers_client.add_router_interface(
504 router_id, subnet_id=self.new_subnet['id'])
505
506 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
507 self.routers_client.remove_router_interface,
508 router_id, subnet_id=self.new_subnet['id'])
Lucas Alvares Gomesd595c362018-10-16 14:38:11 +0100509
510 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
511 new_server_ips, should_connect=True)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300512
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800513 @decorators.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400514 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
515 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200516 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
517 'NIC hotplug not supported for '
518 'vnic_type direct or macvtap')
Andrea Frittolicd368412017-08-14 21:37:56 +0100519 @utils.services('compute', 'network')
Yair Fried3097dc12014-01-26 08:46:43 +0200520 def test_hotplug_nic(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000521 """Test hotplug network interface
522
Arief3f6e812016-09-28 16:48:20 +0300523 1. Create a network and a VM.
524 2. Check connectivity to the VM via a public network.
525 3. Create a new network, with no gateway.
526 4. Bring up a new interface
527 5. check the VM reach the new network
Yair Fried3097dc12014-01-26 08:46:43 +0200528
529 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400530 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800531 self._check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200532 self._create_new_network()
533 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200534 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700535
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800536 @decorators.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Thiago Paiva66cded22016-08-15 14:55:58 -0300537 @testtools.skipIf(CONF.network.shared_physical_network,
538 'Router state can be altered only with multitenant '
539 'networks capabilities')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200540 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100541 @utils.services('compute', 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700542 def test_update_router_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000543 """Test to update admin state up of router
544
Alok Maurya6384bbb2014-07-13 06:44:29 -0700545 1. Check public connectivity before updating
546 admin_state_up attribute of router to False
547 2. Check public connectivity after updating
548 admin_state_up attribute of router to False
549 3. Check public connectivity after updating
550 admin_state_up attribute of router to True
551 """
552 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800553 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700554 should_connect=True, msg="before updating "
555 "admin_state_up of router to False")
556 self._update_router_admin_state(self.router, False)
557 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
558 # once bug 1396310 is fixed
559
zhufl0ec74c42017-11-15 14:02:28 +0800560 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700561 should_connect=False, msg="after updating "
562 "admin_state_up of router to False",
563 should_check_floating_ip_status=False)
564 self._update_router_admin_state(self.router, True)
zhufl0ec74c42017-11-15 14:02:28 +0800565 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700566 should_connect=True, msg="after updating "
567 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200568
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800569 @decorators.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Thiago Paiva66cded22016-08-15 14:55:58 -0300570 @testtools.skipIf(CONF.network.shared_physical_network,
571 'network isolation not available')
Yair Fried413bf2d2014-11-19 17:07:11 +0200572 @testtools.skipUnless(CONF.scenario.dhcp_client,
573 "DHCP client is not available.")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200574 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100575 @utils.services('compute', 'network')
Yair Fried413bf2d2014-11-19 17:07:11 +0200576 def test_subnet_details(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000577 """Tests that subnet's extra configuration details are affecting VMs.
578
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600579 This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200580
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600581 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
582 update in subnet requires server to actively renew its DHCP lease.
Yair Fried413bf2d2014-11-19 17:07:11 +0200583
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600584 1. Configure subnet with dns nameserver
585 2. retrieve the VM's configured dns and verify it matches the one
586 configured for the subnet.
587 3. update subnet's dns
588 4. retrieve the VM's configured dns and verify it matches the new one
589 configured for the subnet.
Yair Fried413bf2d2014-11-19 17:07:11 +0200590
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600591 TODO(yfried): add host_routes
Yair Fried413bf2d2014-11-19 17:07:11 +0200592
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600593 any resolution check would be testing either:
594
595 * l3 forwarding (tested in test_network_basic_ops)
596 * Name resolution of an external DNS nameserver - out of scope for
597 Tempest
Yair Fried413bf2d2014-11-19 17:07:11 +0200598 """
599 # this test check only updates (no actual resolution) so using
600 # arbitrary ip addresses as nameservers, instead of parsing CONF
601 initial_dns_server = '1.2.3.4'
602 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000603
Bence Romsics199e0222019-01-28 14:18:00 +0100604 # Original timeouts are suggested by salvatore-orlando in
Yair Friedbb0ea392015-01-19 07:26:08 +0000605 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
Bence Romsics199e0222019-01-28 14:18:00 +0100606 #
607 # Compared to that renew_delay was increased, because
608 # busybox's udhcpc accepts SIGUSR1 as a renew request. Internally
609 # it goes into RENEW_REQUESTED state. If it receives a 2nd SIGUSR1
610 # signal while in that state then it calls the deconfig script
611 # ("/sbin/cirros-dhcpc deconfig" in sufficiently new cirros versions)
612 # which leads to the address being transiently deconfigured which
613 # for our case is unwanted.
614 renew_delay = 3 * CONF.network.build_interval
Yair Friedbb0ea392015-01-19 07:26:08 +0000615 renew_timeout = CONF.network.build_timeout
616
Yair Fried413bf2d2014-11-19 17:07:11 +0200617 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
zhufl0ec74c42017-11-15 14:02:28 +0800618 self._check_public_network_connectivity(should_connect=True)
Yair Fried413bf2d2014-11-19 17:07:11 +0200619
620 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500621 ip_address = floating_ip['floating_ip_address']
Yair Fried413bf2d2014-11-19 17:07:11 +0200622 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100623 ssh_client = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800624 ip_address, private_key=private_key, server=server)
Yair Fried413bf2d2014-11-19 17:07:11 +0200625
armando-migliaccio424aa412015-02-22 17:55:17 -0800626 dns_servers = [initial_dns_server]
627 servers = ssh_client.get_dns_servers()
628 self.assertEqual(set(dns_servers), set(servers),
629 'Looking for servers: {trgt_serv}. '
630 'Retrieved DNS nameservers: {act_serv} '
631 'From host: {host}.'
632 .format(host=ssh_client.ssh_client.host,
633 act_serv=servers,
634 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200635
Steve Heyman33735f22016-05-24 09:28:08 -0500636 self.subnet = self.subnets_client.update_subnet(
637 self.subnet['id'], dns_nameservers=[alt_dns_server])['subnet']
638
Yair Fried413bf2d2014-11-19 17:07:11 +0200639 # asserts that Neutron DB has updated the nameservers
Steve Heyman33735f22016-05-24 09:28:08 -0500640 self.assertEqual([alt_dns_server], self.subnet['dns_nameservers'],
Yair Fried413bf2d2014-11-19 17:07:11 +0200641 "Failed to update subnet's nameservers")
642
Yair Friedbb0ea392015-01-19 07:26:08 +0000643 def check_new_dns_server():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000644 # NOTE: Server needs to renew its dhcp lease in order to get new
645 # definitions from subnet
646 # NOTE(amuller): we are renewing the lease as part of the retry
647 # because Neutron updates dnsmasq asynchronously after the
648 # subnet-update API call returns.
Ken'ichi Ohmichi4e337852017-03-01 12:04:23 -0800649 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'],
650 dhcp_client=CONF.scenario.dhcp_client)
armando-migliaccio424aa412015-02-22 17:55:17 -0800651 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000652 LOG.debug("Failed to update DNS nameservers")
653 return False
654 return True
655
Jordan Pittier35a63752016-08-30 13:09:12 +0200656 self.assertTrue(test_utils.call_until_true(check_new_dns_server,
657 renew_timeout,
658 renew_delay),
Yair Friedbb0ea392015-01-19 07:26:08 +0000659 msg="DHCP renewal failed to fetch "
660 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800661
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800662 @decorators.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300663 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
664 "Changing a port's admin state is not supported "
665 "by the test environment")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200666 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100667 @utils.services('compute', 'network')
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800668 def test_update_instance_port_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000669 """Test to update admin_state_up attribute of instance port
670
Carlos Goncalves539f8362016-11-04 14:55:02 +0100671 1. Check public and project connectivity before updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800672 admin_state_up attribute of instance port to False
Carlos Goncalves539f8362016-11-04 14:55:02 +0100673 2. Check public and project connectivity after updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800674 admin_state_up attribute of instance port to False
Carlos Goncalves539f8362016-11-04 14:55:02 +0100675 3. Check public and project connectivity after updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800676 admin_state_up attribute of instance port to True
677 """
678 self._setup_network_and_servers()
Ferenc Horváthbce1fcf2017-06-07 11:19:51 +0200679 _, server = self.floating_ip_tuple
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800680 server_id = server['id']
jeremy.zhang5870ff12017-05-25 11:24:23 +0800681 port_id = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100682 device_id=server_id)['ports'][0]['id']
Carlos Goncalves539f8362016-11-04 14:55:02 +0100683 server_pip = server['addresses'][self.network['name']][0]['addr']
684
685 server2 = self._create_server(self.network)
686 server2_fip = self.create_floating_ip(server2)
687
688 private_key = self._get_server_key(server2)
689 ssh_client = self.get_remote_client(server2_fip['floating_ip_address'],
zhuflf52c7592017-05-25 13:55:24 +0800690 private_key=private_key,
691 server=server2)
Carlos Goncalves539f8362016-11-04 14:55:02 +0100692
zhufl0ec74c42017-11-15 14:02:28 +0800693 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800694 should_connect=True, msg="before updating "
695 "admin_state_up of instance port to False")
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900696 self.check_remote_connectivity(ssh_client, dest=server_pip,
697 should_succeed=True)
John Warren49c0fe52015-10-22 12:35:54 -0400698 self.ports_client.update_port(port_id, admin_state_up=False)
zhufl0ec74c42017-11-15 14:02:28 +0800699 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800700 should_connect=False, msg="after updating "
701 "admin_state_up of instance port to False",
702 should_check_floating_ip_status=False)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900703 self.check_remote_connectivity(ssh_client, dest=server_pip,
704 should_succeed=False)
John Warren49c0fe52015-10-22 12:35:54 -0400705 self.ports_client.update_port(port_id, admin_state_up=True)
zhufl0ec74c42017-11-15 14:02:28 +0800706 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800707 should_connect=True, msg="after updating "
708 "admin_state_up of instance port to True")
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900709 self.check_remote_connectivity(ssh_client, dest=server_pip,
710 should_succeed=True)
Matt Riedemann17940732015-03-13 14:18:19 +0000711
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800712 @decorators.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200713 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100714 @utils.services('compute', 'network')
Matt Riedemann17940732015-03-13 14:18:19 +0000715 def test_preserve_preexisting_port(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000716 """Test preserve pre-existing port
717
718 Tests that a pre-existing port provided on server boot is not deleted
719 if the server is deleted.
Matt Riedemann17940732015-03-13 14:18:19 +0000720
721 Nova should unbind the port from the instance on delete if the port was
722 not created by Nova as part of the boot request.
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400723
724 We should also be able to boot another server with the same port.
Matt Riedemann17940732015-03-13 14:18:19 +0000725 """
726 # Setup the network, create a port and boot the server from that port.
727 self._setup_network_and_servers(boot_with_port=True)
728 _, server = self.floating_ip_tuple
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000729 self.assertEqual(1, len(self.ports),
730 'There should only be one port created for '
731 'server %s.' % server['id'])
732 port_id = self.ports[0]['port']
733 self.assertIsNotNone(port_id,
Matt Riedemann17940732015-03-13 14:18:19 +0000734 'Server should have been created from a '
735 'pre-existing port.')
736 # Assert the port is bound to the server.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800737 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100738 device_id=server['id'], network_id=self.network['id'])['ports']
Matt Riedemann17940732015-03-13 14:18:19 +0000739 self.assertEqual(1, len(port_list),
740 'There should only be one port created for '
741 'server %s.' % server['id'])
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000742 self.assertEqual(port_id, port_list[0]['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000743 # Delete the server.
744 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000745 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000746 # Assert the port still exists on the network but is unbound from
747 # the deleted server.
John Warren49c0fe52015-10-22 12:35:54 -0400748 port = self.ports_client.show_port(port_id)['port']
Matt Riedemann17940732015-03-13 14:18:19 +0000749 self.assertEqual(self.network['id'], port['network_id'])
750 self.assertEqual('', port['device_id'])
751 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300752
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400753 # Boot another server with the same port to make sure nothing was
754 # left around that could cause issues.
zhufl24208c22016-10-25 15:23:48 +0800755 server = self._create_server(self.network, port['id'])
jeremy.zhang5870ff12017-05-25 11:24:23 +0800756 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100757 device_id=server['id'], network_id=self.network['id'])['ports']
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400758 self.assertEqual(1, len(port_list),
759 'There should only be one port created for '
760 'server %s.' % server['id'])
761 self.assertEqual(port['id'], port_list[0]['id'])
762
Andrea Frittolicd368412017-08-14 21:37:56 +0100763 @utils.requires_ext(service='network', extension='l3_agent_scheduler')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800764 @decorators.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200765 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100766 @utils.services('compute', 'network')
Yair Fried564d89d2015-08-06 17:02:12 +0300767 def test_router_rescheduling(self):
768 """Tests that router can be removed from agent and add to a new agent.
769
770 1. Verify connectivity
771 2. Remove router from all l3-agents
772 3. Verify connectivity is down
773 4. Assign router to new l3-agent (or old one if no new agent is
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600774 available)
Yair Fried564d89d2015-08-06 17:02:12 +0300775 5. Verify connectivity
776 """
777
778 # TODO(yfried): refactor this test to be used for other agents (dhcp)
779 # as well
780
jeremy.zhang5870ff12017-05-25 11:24:23 +0800781 list_hosts = (self.os_admin.routers_client.
Yair Fried564d89d2015-08-06 17:02:12 +0300782 list_l3_agents_hosting_router)
jeremy.zhang5870ff12017-05-25 11:24:23 +0800783 schedule_router = (self.os_admin.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000784 create_router_on_l3_agent)
jeremy.zhang5870ff12017-05-25 11:24:23 +0800785 unschedule_router = (self.os_admin.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000786 delete_router_from_l3_agent)
Yair Fried564d89d2015-08-06 17:02:12 +0300787
Jordan Pittier64e6b442017-02-20 19:29:02 +0100788 agent_list_alive = set(
789 a["id"] for a in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800790 self.os_admin.network_agents_client.list_agents(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100791 agent_type="L3 agent")['agents'] if a["alive"] is True
792 )
Yair Fried564d89d2015-08-06 17:02:12 +0300793 self._setup_network_and_servers()
Kevin Benton3b63aa12015-08-27 17:15:44 -0700794
795 # NOTE(kevinbenton): we have to use the admin credentials to check
Sean Dagueed6e5862016-04-04 10:49:13 -0400796 # for the distributed flag because self.router only has a project view.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800797 admin = self.os_admin.routers_client.show_router(
Steve Heyman33735f22016-05-24 09:28:08 -0500798 self.router['id'])
Kevin Benton3b63aa12015-08-27 17:15:44 -0700799 if admin['router'].get('distributed', False):
800 msg = "Rescheduling test does not apply to distributed routers."
801 raise self.skipException(msg)
802
zhufl0ec74c42017-11-15 14:02:28 +0800803 self._check_public_network_connectivity(should_connect=True)
Yair Fried564d89d2015-08-06 17:02:12 +0300804
805 # remove resource from agents
806 hosting_agents = set(a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500807 list_hosts(self.router['id'])['agents'])
shipeiqic9a4a102016-04-20 17:39:03 +0800808 no_migration = agent_list_alive == hosting_agents
Yair Fried564d89d2015-08-06 17:02:12 +0300809 LOG.info("Router will be assigned to {mig} hosting agent".
810 format(mig="the same" if no_migration else "a new"))
811
812 for hosting_agent in hosting_agents:
Steve Heyman33735f22016-05-24 09:28:08 -0500813 unschedule_router(hosting_agent, self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300814 self.assertNotIn(hosting_agent,
815 [a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500816 list_hosts(self.router['id'])['agents']],
Yair Fried564d89d2015-08-06 17:02:12 +0300817 'unscheduling router failed')
818
819 # verify resource is un-functional
zhufl0ec74c42017-11-15 14:02:28 +0800820 self._check_public_network_connectivity(
Yair Fried564d89d2015-08-06 17:02:12 +0300821 should_connect=False,
822 msg='after router unscheduling',
Yair Fried564d89d2015-08-06 17:02:12 +0300823 )
824
825 # schedule resource to new agent
826 target_agent = list(hosting_agents if no_migration else
shipeiqic9a4a102016-04-20 17:39:03 +0800827 agent_list_alive - hosting_agents)[0]
Yair Fried564d89d2015-08-06 17:02:12 +0300828 schedule_router(target_agent,
piyush110786bc0faa62015-12-03 14:54:48 +0530829 router_id=self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300830 self.assertEqual(
831 target_agent,
Steve Heyman33735f22016-05-24 09:28:08 -0500832 list_hosts(self.router['id'])['agents'][0]['id'],
Yair Fried564d89d2015-08-06 17:02:12 +0300833 "Router failed to reschedule. Hosting agent doesn't match "
834 "target agent")
835
836 # verify resource is functional
zhufl0ec74c42017-11-15 14:02:28 +0800837 self._check_public_network_connectivity(
Yair Fried564d89d2015-08-06 17:02:12 +0300838 should_connect=True,
839 msg='After router rescheduling')
Yair Friedbc46f592015-11-18 16:29:34 +0200840
Andrea Frittolicd368412017-08-14 21:37:56 +0100841 @utils.requires_ext(service='network', extension='port-security')
Evgeny Antyshevaaf3fc92016-02-15 11:49:22 +0000842 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
843 'NIC hotplug not available')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800844 @decorators.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200845 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100846 @utils.services('compute', 'network')
Yair Friedbc46f592015-11-18 16:29:34 +0200847 def test_port_security_macspoofing_port(self):
848 """Tests port_security extension enforces mac spoofing
849
Eran Kuris7969e802015-12-15 13:43:46 +0200850 Neutron security groups always apply anti-spoof rules on the VMs. This
851 allows traffic to originate and terminate at the VM as expected, but
852 prevents traffic to pass through the VM. Anti-spoof rules are not
853 required in cases where the VM routes traffic through it.
854
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600855 The test steps are:
856
Eran Kuris7969e802015-12-15 13:43:46 +0200857 1. Create a new network.
858 2. Connect (hotplug) the VM to a new network.
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900859 3. Check the VM can ping a server on the new network ("peer")
Eran Kuris7969e802015-12-15 13:43:46 +0200860 4. Spoof the mac address of the new VM interface.
861 5. Check the Security Group enforces mac spoofing and blocks pings via
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900862 spoofed interface (VM cannot ping the peer).
Eran Kuris7969e802015-12-15 13:43:46 +0200863 6. Disable port-security of the spoofed port- set the flag to false.
864 7. Retest 3rd step and check that the Security Group allows pings via
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600865 the spoofed interface.
Yair Friedbc46f592015-11-18 16:29:34 +0200866 """
Eran Kuris7969e802015-12-15 13:43:46 +0200867
Yair Friedbc46f592015-11-18 16:29:34 +0200868 spoof_mac = "00:00:00:00:00:01"
869
870 # Create server
871 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800872 self._check_public_network_connectivity(should_connect=True)
Yair Friedbc46f592015-11-18 16:29:34 +0200873 self._create_new_network()
874 self._hotplug_server()
875 fip, server = self.floating_ip_tuple
jeremy.zhang5870ff12017-05-25 11:24:23 +0800876 new_ports = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100877 device_id=server["id"], network_id=self.new_net["id"])['ports']
Yair Friedbc46f592015-11-18 16:29:34 +0200878 spoof_port = new_ports[0]
879 private_key = self._get_server_key(server)
Steve Heyman33735f22016-05-24 09:28:08 -0500880 ssh_client = self.get_remote_client(fip['floating_ip_address'],
zhuflf52c7592017-05-25 13:55:24 +0800881 private_key=private_key,
882 server=server)
Evgeny Antyshev9b77ae52016-02-16 09:48:57 +0000883 spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
zhufl24208c22016-10-25 15:23:48 +0800884 peer = self._create_server(self.new_net)
Steve Heyman33735f22016-05-24 09:28:08 -0500885 peer_address = peer['addresses'][self.new_net['name']][0]['addr']
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900886 self.check_remote_connectivity(ssh_client, dest=peer_address,
887 nic=spoof_nic, should_succeed=True)
Ken'ichi Ohmichi5129c622017-03-22 11:18:42 -0700888 # Set a mac address by making nic down temporary
889 cmd = ("sudo ip link set {nic} down;"
890 "sudo ip link set dev {nic} address {mac};"
891 "sudo ip link set {nic} up").format(nic=spoof_nic,
892 mac=spoof_mac)
893 ssh_client.exec_command(cmd)
894
Yair Friedbc46f592015-11-18 16:29:34 +0200895 new_mac = ssh_client.get_mac_address(nic=spoof_nic)
896 self.assertEqual(spoof_mac, new_mac)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900897 self.check_remote_connectivity(ssh_client, dest=peer_address,
898 nic=spoof_nic, should_succeed=False)
Yair Friedbc46f592015-11-18 16:29:34 +0200899 self.ports_client.update_port(spoof_port["id"],
900 port_security_enabled=False,
901 security_groups=[])
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900902 self.check_remote_connectivity(ssh_client, dest=peer_address,
903 nic=spoof_nic, should_succeed=True)