blob: d8584ec88b6fd6abd3cfed98787cc285915e7abc [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)
zhuflafe96b82017-09-22 14:25:29 +0800226 port_id, _ = self._get_server_port_id_and_ip4(server)
227 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:
300 ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
301 ip_address, ip_mask, new_nic))
302 ssh_client.exec_command("sudo ip link set %s up" % new_nic)
Yair Fried3097dc12014-01-26 08:46:43 +0200303
304 def _get_server_nics(self, ssh_client):
James Pagea9366272017-06-09 12:05:09 +0100305 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+)[@]?.*:')
Ken'ichi Ohmichi84aeba62017-03-01 18:31:20 -0800306 ipatxt = ssh_client.exec_command("ip address")
Yair Fried3097dc12014-01-26 08:46:43 +0200307 return reg.findall(ipatxt)
308
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300309 def _check_network_internal_connectivity(self, network,
310 should_connect=True):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000311 """via ssh check VM internal connectivity:
312
Yair Fried06552292013-11-11 12:10:09 +0200313 - ping internal gateway and DHCP port, implying in-tenant connectivity
314 pinging both, because L3 and DHCP agents might be on different nodes
Tong Liu589f3152016-03-24 05:56:40 +0000315 - ping internal compute port, implying connectivity to other VMs on
316 this network
Yair Fried3097dc12014-01-26 08:46:43 +0200317 """
318 floating_ip, server = self.floating_ip_tuple
319 # get internal ports' ips:
Tong Liu589f3152016-03-24 05:56:40 +0000320 # get all network and compute ports in the new network
Jordan Pittier64e6b442017-02-20 19:29:02 +0100321 internal_ips = (
322 p['fixed_ips'][0]['ip_address'] for p in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800323 self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100324 tenant_id=server['tenant_id'],
325 network_id=network['id'])['ports']
Tong Liu589f3152016-03-24 05:56:40 +0000326 if p['device_owner'].startswith('network') or
327 p['device_owner'].startswith('compute')
Jordan Pittier64e6b442017-02-20 19:29:02 +0100328 )
Yair Fried3097dc12014-01-26 08:46:43 +0200329
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300330 self._check_server_connectivity(floating_ip,
331 internal_ips,
332 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200333
334 def _check_network_external_connectivity(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000335 """ping default gateway to imply external connectivity"""
Yair Fried06552292013-11-11 12:10:09 +0200336 if not CONF.network.public_network_id:
337 msg = 'public network not defined.'
338 LOG.info(msg)
339 return
340
Andrew Boik4a3daf12015-03-27 01:59:31 -0400341 # We ping the external IP from the instance using its floating IP
342 # which is always IPv4, so we must only test connectivity to
343 # external IPv4 IPs if the external network is dualstack.
Jordan Pittier64e6b442017-02-20 19:29:02 +0100344 v4_subnets = [
jeremy.zhang5870ff12017-05-25 11:24:23 +0800345 s for s in self.os_admin.subnets_client.list_subnets(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100346 network_id=CONF.network.public_network_id)['subnets']
347 if s['ip_version'] == 4
348 ]
Yair Fried06552292013-11-11 12:10:09 +0200349
Lukas Piwowarski2385e042020-01-31 12:28:20 +0000350 if len(v4_subnets) > 1:
351 self.assertTrue(
352 CONF.network.subnet_id,
353 "Found %d subnets. Specify subnet using configuration "
354 "option [network].subnet_id."
355 % len(v4_subnets))
356 subnet = self.os_admin.subnets_client.show_subnet(
357 CONF.network.subnet_id)['subnet']
358 external_ips = [subnet['gateway_ip']]
359 else:
360 external_ips = [v4_subnets[0]['gateway_ip']]
361
Yair Fried06552292013-11-11 12:10:09 +0200362 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
363 external_ips)
364
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300365 def _check_server_connectivity(self, floating_ip, address_list,
366 should_connect=True):
Steve Heyman33735f22016-05-24 09:28:08 -0500367 ip_address = floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300368 private_key = self._get_server_key(self.floating_ip_tuple.server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100369 ssh_source = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800370 ip_address, private_key=private_key,
371 server=self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200372
Yair Fried06552292013-11-11 12:10:09 +0200373 for remote_ip in address_list:
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900374 self.check_remote_connectivity(ssh_source, remote_ip,
375 should_connect)
Yair Fried3097dc12014-01-26 08:46:43 +0200376
zhuflafe96b82017-09-22 14:25:29 +0800377 def _update_router_admin_state(self, router, admin_state_up):
378 kwargs = dict(admin_state_up=admin_state_up)
379 router = self.routers_client.update_router(
380 router['id'], **kwargs)['router']
381 self.assertEqual(admin_state_up, router['admin_state_up'])
382
Jordan Pittier3b46d272017-04-12 16:17:28 +0200383 @decorators.attr(type='smoke')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800384 @decorators.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Andrea Frittolicd368412017-08-14 21:37:56 +0100385 @utils.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000386 def test_network_basic_ops(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000387 """Basic network operation test
388
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600389 For a freshly-booted VM with an IP address ("port") on a given network:
Yair Fried3097dc12014-01-26 08:46:43 +0200390
391 - the Tempest host can ping the IP address. This implies, but
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600392 does not guarantee (see the ssh check that follows), that the
393 VM has been assigned the correct IP address and has
394 connectivity to the Tempest host.
Yair Fried3097dc12014-01-26 08:46:43 +0200395
396 - the Tempest host can perform key-based authentication to an
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600397 ssh server hosted at the IP address. This check guarantees
398 that the IP address is associated with the target VM.
Yair Fried3097dc12014-01-26 08:46:43 +0200399
Yair Fried3097dc12014-01-26 08:46:43 +0200400 - the Tempest host can ssh into the VM via the IP address and
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600401 successfully execute the following:
Yair Fried3097dc12014-01-26 08:46:43 +0200402
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600403 - ping an external IP address, implying external connectivity.
Yair Fried3097dc12014-01-26 08:46:43 +0200404
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600405 - ping an external hostname, implying that dns is correctly
406 configured.
Yair Fried3097dc12014-01-26 08:46:43 +0200407
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600408 - ping an internal IP address, implying connectivity to another
409 VM on the same network.
Yair Fried3097dc12014-01-26 08:46:43 +0200410
Yair Fried06552292013-11-11 12:10:09 +0200411 - detach the floating-ip from the VM and verify that it becomes
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600412 unreachable
Yair Fried06552292013-11-11 12:10:09 +0200413
414 - associate detached floating ip to a new VM and verify connectivity.
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600415 VMs are created with unique keypair so connectivity also asserts
416 that floating IP is associated with the new VM instead of the old
417 one
Yair Fried06552292013-11-11 12:10:09 +0200418
Yair Fried45f92952014-06-26 05:19:19 +0300419 Verifies that floating IP status is updated correctly after each change
Yair Fried3097dc12014-01-26 08:46:43 +0200420 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400421 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800422 self._check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200423 self._check_network_internal_connectivity(network=self.network)
424 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200425 self._disassociate_floating_ips()
zhufl0ec74c42017-11-15 14:02:28 +0800426 self._check_public_network_connectivity(should_connect=False,
427 msg="after disassociate "
428 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200429 self._reassociate_floating_ips()
zhufl0ec74c42017-11-15 14:02:28 +0800430 self._check_public_network_connectivity(should_connect=True,
431 msg="after re-associate "
432 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200433
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800434 @decorators.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
Andrea Frittolicd368412017-08-14 21:37:56 +0100435 @testtools.skipUnless(utils.is_extension_enabled('net-mtu', 'network'),
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000436 'No way to calculate MTU for networks')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200437 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100438 @utils.services('compute', 'network')
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000439 def test_mtu_sized_frames(self):
440 """Validate that network MTU sized frames fit through."""
441 self._setup_network_and_servers()
Ihar Hrachyshkaaca29ed2017-09-25 12:13:53 -0700442 # first check that connectivity works in general for the instance
zhufl0ec74c42017-11-15 14:02:28 +0800443 self._check_public_network_connectivity(should_connect=True)
Ihar Hrachyshkaaca29ed2017-09-25 12:13:53 -0700444 # now that we checked general connectivity, test that full size frames
445 # can also pass between nodes
zhufl0ec74c42017-11-15 14:02:28 +0800446 self._check_public_network_connectivity(
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000447 should_connect=True, mtu=self.network['mtu'])
448
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800449 @decorators.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
Thiago Paiva66cded22016-08-15 14:55:58 -0300450 @testtools.skipIf(CONF.network.shared_physical_network,
451 'Connectivity can only be tested when in a '
452 'multitenant network environment')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200453 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100454 @utils.services('compute', 'network')
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300455 def test_connectivity_between_vms_on_different_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000456 """Test connectivity between VMs on different networks
457
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600458 For a freshly-booted VM with an IP address ("port") on a given network:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300459
460 - the Tempest host can ping the IP address.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300461 - the Tempest host can ssh into the VM via the IP address and
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600462 successfully execute the following:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300463
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600464 - ping an external IP address, implying external connectivity.
465 - ping an external hostname, implying that dns is correctly
466 configured.
467 - ping an internal IP address, implying connectivity to another
468 VM on the same network.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300469
470 - Create another network on the same tenant with subnet, create
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600471 an VM on the new network.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300472
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600473 - Ping the new VM from previous VM failed since the new network
474 was not attached to router yet.
475 - Attach the new network to the router, Ping the new VM from
476 previous VM succeed.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300477
478 """
479 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800480 self._check_public_network_connectivity(should_connect=True)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300481 self._check_network_internal_connectivity(network=self.network)
482 self._check_network_external_connectivity()
483 self._create_new_network(create_gateway=True)
Lucas Alvares Gomesd595c362018-10-16 14:38:11 +0100484 new_server = self._create_server(self.new_net)
485 new_server_ips = [addr['addr'] for addr in
486 new_server['addresses'][self.new_net['name']]]
487
488 # Assert that pinging the new VM fails since the new network is not
489 # connected to a router
490 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
491 new_server_ips, should_connect=False)
Steve Heyman33735f22016-05-24 09:28:08 -0500492 router_id = self.router['id']
493 self.routers_client.add_router_interface(
494 router_id, subnet_id=self.new_subnet['id'])
495
496 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
497 self.routers_client.remove_router_interface,
498 router_id, subnet_id=self.new_subnet['id'])
Lucas Alvares Gomesd595c362018-10-16 14:38:11 +0100499
500 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
501 new_server_ips, should_connect=True)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300502
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800503 @decorators.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400504 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
505 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200506 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
507 'NIC hotplug not supported for '
508 'vnic_type direct or macvtap')
Andrea Frittolicd368412017-08-14 21:37:56 +0100509 @utils.services('compute', 'network')
Yair Fried3097dc12014-01-26 08:46:43 +0200510 def test_hotplug_nic(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000511 """Test hotplug network interface
512
Arief3f6e812016-09-28 16:48:20 +0300513 1. Create a network and a VM.
514 2. Check connectivity to the VM via a public network.
515 3. Create a new network, with no gateway.
516 4. Bring up a new interface
517 5. check the VM reach the new network
Yair Fried3097dc12014-01-26 08:46:43 +0200518
519 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400520 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800521 self._check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200522 self._create_new_network()
523 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200524 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700525
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800526 @decorators.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Thiago Paiva66cded22016-08-15 14:55:58 -0300527 @testtools.skipIf(CONF.network.shared_physical_network,
528 'Router state can be altered only with multitenant '
529 'networks capabilities')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200530 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100531 @utils.services('compute', 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700532 def test_update_router_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000533 """Test to update admin state up of router
534
Alok Maurya6384bbb2014-07-13 06:44:29 -0700535 1. Check public connectivity before updating
536 admin_state_up attribute of router to False
537 2. Check public connectivity after updating
538 admin_state_up attribute of router to False
539 3. Check public connectivity after updating
540 admin_state_up attribute of router to True
541 """
542 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800543 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700544 should_connect=True, msg="before updating "
545 "admin_state_up of router to False")
546 self._update_router_admin_state(self.router, False)
547 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
548 # once bug 1396310 is fixed
549
zhufl0ec74c42017-11-15 14:02:28 +0800550 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700551 should_connect=False, msg="after updating "
552 "admin_state_up of router to False",
553 should_check_floating_ip_status=False)
554 self._update_router_admin_state(self.router, True)
zhufl0ec74c42017-11-15 14:02:28 +0800555 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700556 should_connect=True, msg="after updating "
557 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200558
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800559 @decorators.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Thiago Paiva66cded22016-08-15 14:55:58 -0300560 @testtools.skipIf(CONF.network.shared_physical_network,
561 'network isolation not available')
Yair Fried413bf2d2014-11-19 17:07:11 +0200562 @testtools.skipUnless(CONF.scenario.dhcp_client,
563 "DHCP client is not available.")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200564 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100565 @utils.services('compute', 'network')
Yair Fried413bf2d2014-11-19 17:07:11 +0200566 def test_subnet_details(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000567 """Tests that subnet's extra configuration details are affecting VMs.
568
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600569 This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200570
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600571 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
572 update in subnet requires server to actively renew its DHCP lease.
Yair Fried413bf2d2014-11-19 17:07:11 +0200573
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600574 1. Configure subnet with dns nameserver
575 2. retrieve the VM's configured dns and verify it matches the one
576 configured for the subnet.
577 3. update subnet's dns
578 4. retrieve the VM's configured dns and verify it matches the new one
579 configured for the subnet.
Yair Fried413bf2d2014-11-19 17:07:11 +0200580
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600581 TODO(yfried): add host_routes
Yair Fried413bf2d2014-11-19 17:07:11 +0200582
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600583 any resolution check would be testing either:
584
585 * l3 forwarding (tested in test_network_basic_ops)
586 * Name resolution of an external DNS nameserver - out of scope for
587 Tempest
Yair Fried413bf2d2014-11-19 17:07:11 +0200588 """
589 # this test check only updates (no actual resolution) so using
590 # arbitrary ip addresses as nameservers, instead of parsing CONF
591 initial_dns_server = '1.2.3.4'
592 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000593
Bence Romsics199e0222019-01-28 14:18:00 +0100594 # Original timeouts are suggested by salvatore-orlando in
Yair Friedbb0ea392015-01-19 07:26:08 +0000595 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
Bence Romsics199e0222019-01-28 14:18:00 +0100596 #
597 # Compared to that renew_delay was increased, because
598 # busybox's udhcpc accepts SIGUSR1 as a renew request. Internally
599 # it goes into RENEW_REQUESTED state. If it receives a 2nd SIGUSR1
600 # signal while in that state then it calls the deconfig script
601 # ("/sbin/cirros-dhcpc deconfig" in sufficiently new cirros versions)
602 # which leads to the address being transiently deconfigured which
603 # for our case is unwanted.
604 renew_delay = 3 * CONF.network.build_interval
Yair Friedbb0ea392015-01-19 07:26:08 +0000605 renew_timeout = CONF.network.build_timeout
606
Yair Fried413bf2d2014-11-19 17:07:11 +0200607 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
zhufl0ec74c42017-11-15 14:02:28 +0800608 self._check_public_network_connectivity(should_connect=True)
Yair Fried413bf2d2014-11-19 17:07:11 +0200609
610 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500611 ip_address = floating_ip['floating_ip_address']
Yair Fried413bf2d2014-11-19 17:07:11 +0200612 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100613 ssh_client = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800614 ip_address, private_key=private_key, server=server)
Yair Fried413bf2d2014-11-19 17:07:11 +0200615
armando-migliaccio424aa412015-02-22 17:55:17 -0800616 dns_servers = [initial_dns_server]
617 servers = ssh_client.get_dns_servers()
618 self.assertEqual(set(dns_servers), set(servers),
619 'Looking for servers: {trgt_serv}. '
620 'Retrieved DNS nameservers: {act_serv} '
621 'From host: {host}.'
622 .format(host=ssh_client.ssh_client.host,
623 act_serv=servers,
624 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200625
Steve Heyman33735f22016-05-24 09:28:08 -0500626 self.subnet = self.subnets_client.update_subnet(
627 self.subnet['id'], dns_nameservers=[alt_dns_server])['subnet']
628
Yair Fried413bf2d2014-11-19 17:07:11 +0200629 # asserts that Neutron DB has updated the nameservers
Steve Heyman33735f22016-05-24 09:28:08 -0500630 self.assertEqual([alt_dns_server], self.subnet['dns_nameservers'],
Yair Fried413bf2d2014-11-19 17:07:11 +0200631 "Failed to update subnet's nameservers")
632
Yair Friedbb0ea392015-01-19 07:26:08 +0000633 def check_new_dns_server():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000634 # NOTE: Server needs to renew its dhcp lease in order to get new
635 # definitions from subnet
636 # NOTE(amuller): we are renewing the lease as part of the retry
637 # because Neutron updates dnsmasq asynchronously after the
638 # subnet-update API call returns.
Ken'ichi Ohmichi4e337852017-03-01 12:04:23 -0800639 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'],
640 dhcp_client=CONF.scenario.dhcp_client)
armando-migliaccio424aa412015-02-22 17:55:17 -0800641 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000642 LOG.debug("Failed to update DNS nameservers")
643 return False
644 return True
645
Jordan Pittier35a63752016-08-30 13:09:12 +0200646 self.assertTrue(test_utils.call_until_true(check_new_dns_server,
647 renew_timeout,
648 renew_delay),
Yair Friedbb0ea392015-01-19 07:26:08 +0000649 msg="DHCP renewal failed to fetch "
650 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800651
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800652 @decorators.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300653 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
654 "Changing a port's admin state is not supported "
655 "by the test environment")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200656 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100657 @utils.services('compute', 'network')
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800658 def test_update_instance_port_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000659 """Test to update admin_state_up attribute of instance port
660
Carlos Goncalves539f8362016-11-04 14:55:02 +0100661 1. Check public and project connectivity before updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800662 admin_state_up attribute of instance port to False
Carlos Goncalves539f8362016-11-04 14:55:02 +0100663 2. Check public and project connectivity after updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800664 admin_state_up attribute of instance port to False
Carlos Goncalves539f8362016-11-04 14:55:02 +0100665 3. Check public and project connectivity after updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800666 admin_state_up attribute of instance port to True
667 """
668 self._setup_network_and_servers()
Ferenc Horváthbce1fcf2017-06-07 11:19:51 +0200669 _, server = self.floating_ip_tuple
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800670 server_id = server['id']
jeremy.zhang5870ff12017-05-25 11:24:23 +0800671 port_id = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100672 device_id=server_id)['ports'][0]['id']
Carlos Goncalves539f8362016-11-04 14:55:02 +0100673 server_pip = server['addresses'][self.network['name']][0]['addr']
674
675 server2 = self._create_server(self.network)
676 server2_fip = self.create_floating_ip(server2)
677
678 private_key = self._get_server_key(server2)
679 ssh_client = self.get_remote_client(server2_fip['floating_ip_address'],
zhuflf52c7592017-05-25 13:55:24 +0800680 private_key=private_key,
681 server=server2)
Carlos Goncalves539f8362016-11-04 14:55:02 +0100682
zhufl0ec74c42017-11-15 14:02:28 +0800683 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800684 should_connect=True, msg="before updating "
685 "admin_state_up of instance port to False")
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900686 self.check_remote_connectivity(ssh_client, dest=server_pip,
687 should_succeed=True)
John Warren49c0fe52015-10-22 12:35:54 -0400688 self.ports_client.update_port(port_id, admin_state_up=False)
zhufl0ec74c42017-11-15 14:02:28 +0800689 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800690 should_connect=False, msg="after updating "
691 "admin_state_up of instance port to False",
692 should_check_floating_ip_status=False)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900693 self.check_remote_connectivity(ssh_client, dest=server_pip,
694 should_succeed=False)
John Warren49c0fe52015-10-22 12:35:54 -0400695 self.ports_client.update_port(port_id, admin_state_up=True)
zhufl0ec74c42017-11-15 14:02:28 +0800696 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800697 should_connect=True, msg="after updating "
698 "admin_state_up of instance port to True")
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900699 self.check_remote_connectivity(ssh_client, dest=server_pip,
700 should_succeed=True)
Matt Riedemann17940732015-03-13 14:18:19 +0000701
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800702 @decorators.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200703 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100704 @utils.services('compute', 'network')
Matt Riedemann17940732015-03-13 14:18:19 +0000705 def test_preserve_preexisting_port(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000706 """Test preserve pre-existing port
707
708 Tests that a pre-existing port provided on server boot is not deleted
709 if the server is deleted.
Matt Riedemann17940732015-03-13 14:18:19 +0000710
711 Nova should unbind the port from the instance on delete if the port was
712 not created by Nova as part of the boot request.
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400713
714 We should also be able to boot another server with the same port.
Matt Riedemann17940732015-03-13 14:18:19 +0000715 """
716 # Setup the network, create a port and boot the server from that port.
717 self._setup_network_and_servers(boot_with_port=True)
718 _, server = self.floating_ip_tuple
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000719 self.assertEqual(1, len(self.ports),
720 'There should only be one port created for '
721 'server %s.' % server['id'])
722 port_id = self.ports[0]['port']
723 self.assertIsNotNone(port_id,
Matt Riedemann17940732015-03-13 14:18:19 +0000724 'Server should have been created from a '
725 'pre-existing port.')
726 # Assert the port is bound to the server.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800727 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100728 device_id=server['id'], network_id=self.network['id'])['ports']
Matt Riedemann17940732015-03-13 14:18:19 +0000729 self.assertEqual(1, len(port_list),
730 'There should only be one port created for '
731 'server %s.' % server['id'])
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000732 self.assertEqual(port_id, port_list[0]['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000733 # Delete the server.
734 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000735 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000736 # Assert the port still exists on the network but is unbound from
737 # the deleted server.
John Warren49c0fe52015-10-22 12:35:54 -0400738 port = self.ports_client.show_port(port_id)['port']
Matt Riedemann17940732015-03-13 14:18:19 +0000739 self.assertEqual(self.network['id'], port['network_id'])
740 self.assertEqual('', port['device_id'])
741 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300742
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400743 # Boot another server with the same port to make sure nothing was
744 # left around that could cause issues.
zhufl24208c22016-10-25 15:23:48 +0800745 server = self._create_server(self.network, port['id'])
jeremy.zhang5870ff12017-05-25 11:24:23 +0800746 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100747 device_id=server['id'], network_id=self.network['id'])['ports']
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400748 self.assertEqual(1, len(port_list),
749 'There should only be one port created for '
750 'server %s.' % server['id'])
751 self.assertEqual(port['id'], port_list[0]['id'])
752
Andrea Frittolicd368412017-08-14 21:37:56 +0100753 @utils.requires_ext(service='network', extension='l3_agent_scheduler')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800754 @decorators.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200755 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100756 @utils.services('compute', 'network')
Yair Fried564d89d2015-08-06 17:02:12 +0300757 def test_router_rescheduling(self):
758 """Tests that router can be removed from agent and add to a new agent.
759
760 1. Verify connectivity
761 2. Remove router from all l3-agents
762 3. Verify connectivity is down
763 4. Assign router to new l3-agent (or old one if no new agent is
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600764 available)
Yair Fried564d89d2015-08-06 17:02:12 +0300765 5. Verify connectivity
766 """
767
768 # TODO(yfried): refactor this test to be used for other agents (dhcp)
769 # as well
770
jeremy.zhang5870ff12017-05-25 11:24:23 +0800771 list_hosts = (self.os_admin.routers_client.
Yair Fried564d89d2015-08-06 17:02:12 +0300772 list_l3_agents_hosting_router)
jeremy.zhang5870ff12017-05-25 11:24:23 +0800773 schedule_router = (self.os_admin.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000774 create_router_on_l3_agent)
jeremy.zhang5870ff12017-05-25 11:24:23 +0800775 unschedule_router = (self.os_admin.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000776 delete_router_from_l3_agent)
Yair Fried564d89d2015-08-06 17:02:12 +0300777
Jordan Pittier64e6b442017-02-20 19:29:02 +0100778 agent_list_alive = set(
779 a["id"] for a in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800780 self.os_admin.network_agents_client.list_agents(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100781 agent_type="L3 agent")['agents'] if a["alive"] is True
782 )
Yair Fried564d89d2015-08-06 17:02:12 +0300783 self._setup_network_and_servers()
Kevin Benton3b63aa12015-08-27 17:15:44 -0700784
785 # NOTE(kevinbenton): we have to use the admin credentials to check
Sean Dagueed6e5862016-04-04 10:49:13 -0400786 # for the distributed flag because self.router only has a project view.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800787 admin = self.os_admin.routers_client.show_router(
Steve Heyman33735f22016-05-24 09:28:08 -0500788 self.router['id'])
Kevin Benton3b63aa12015-08-27 17:15:44 -0700789 if admin['router'].get('distributed', False):
790 msg = "Rescheduling test does not apply to distributed routers."
791 raise self.skipException(msg)
792
zhufl0ec74c42017-11-15 14:02:28 +0800793 self._check_public_network_connectivity(should_connect=True)
Yair Fried564d89d2015-08-06 17:02:12 +0300794
795 # remove resource from agents
796 hosting_agents = set(a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500797 list_hosts(self.router['id'])['agents'])
shipeiqic9a4a102016-04-20 17:39:03 +0800798 no_migration = agent_list_alive == hosting_agents
Yair Fried564d89d2015-08-06 17:02:12 +0300799 LOG.info("Router will be assigned to {mig} hosting agent".
800 format(mig="the same" if no_migration else "a new"))
801
802 for hosting_agent in hosting_agents:
Steve Heyman33735f22016-05-24 09:28:08 -0500803 unschedule_router(hosting_agent, self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300804 self.assertNotIn(hosting_agent,
805 [a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500806 list_hosts(self.router['id'])['agents']],
Yair Fried564d89d2015-08-06 17:02:12 +0300807 'unscheduling router failed')
808
809 # verify resource is un-functional
zhufl0ec74c42017-11-15 14:02:28 +0800810 self._check_public_network_connectivity(
Yair Fried564d89d2015-08-06 17:02:12 +0300811 should_connect=False,
812 msg='after router unscheduling',
Yair Fried564d89d2015-08-06 17:02:12 +0300813 )
814
815 # schedule resource to new agent
816 target_agent = list(hosting_agents if no_migration else
shipeiqic9a4a102016-04-20 17:39:03 +0800817 agent_list_alive - hosting_agents)[0]
Yair Fried564d89d2015-08-06 17:02:12 +0300818 schedule_router(target_agent,
piyush110786bc0faa62015-12-03 14:54:48 +0530819 router_id=self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300820 self.assertEqual(
821 target_agent,
Steve Heyman33735f22016-05-24 09:28:08 -0500822 list_hosts(self.router['id'])['agents'][0]['id'],
Yair Fried564d89d2015-08-06 17:02:12 +0300823 "Router failed to reschedule. Hosting agent doesn't match "
824 "target agent")
825
826 # verify resource is functional
zhufl0ec74c42017-11-15 14:02:28 +0800827 self._check_public_network_connectivity(
Yair Fried564d89d2015-08-06 17:02:12 +0300828 should_connect=True,
829 msg='After router rescheduling')
Yair Friedbc46f592015-11-18 16:29:34 +0200830
Andrea Frittolicd368412017-08-14 21:37:56 +0100831 @utils.requires_ext(service='network', extension='port-security')
Evgeny Antyshevaaf3fc92016-02-15 11:49:22 +0000832 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
833 'NIC hotplug not available')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800834 @decorators.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200835 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100836 @utils.services('compute', 'network')
Yair Friedbc46f592015-11-18 16:29:34 +0200837 def test_port_security_macspoofing_port(self):
838 """Tests port_security extension enforces mac spoofing
839
Eran Kuris7969e802015-12-15 13:43:46 +0200840 Neutron security groups always apply anti-spoof rules on the VMs. This
841 allows traffic to originate and terminate at the VM as expected, but
842 prevents traffic to pass through the VM. Anti-spoof rules are not
843 required in cases where the VM routes traffic through it.
844
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600845 The test steps are:
846
Eran Kuris7969e802015-12-15 13:43:46 +0200847 1. Create a new network.
848 2. Connect (hotplug) the VM to a new network.
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900849 3. Check the VM can ping a server on the new network ("peer")
Eran Kuris7969e802015-12-15 13:43:46 +0200850 4. Spoof the mac address of the new VM interface.
851 5. Check the Security Group enforces mac spoofing and blocks pings via
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900852 spoofed interface (VM cannot ping the peer).
Eran Kuris7969e802015-12-15 13:43:46 +0200853 6. Disable port-security of the spoofed port- set the flag to false.
854 7. Retest 3rd step and check that the Security Group allows pings via
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600855 the spoofed interface.
Yair Friedbc46f592015-11-18 16:29:34 +0200856 """
Eran Kuris7969e802015-12-15 13:43:46 +0200857
Yair Friedbc46f592015-11-18 16:29:34 +0200858 spoof_mac = "00:00:00:00:00:01"
859
860 # Create server
861 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800862 self._check_public_network_connectivity(should_connect=True)
Yair Friedbc46f592015-11-18 16:29:34 +0200863 self._create_new_network()
864 self._hotplug_server()
865 fip, server = self.floating_ip_tuple
jeremy.zhang5870ff12017-05-25 11:24:23 +0800866 new_ports = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100867 device_id=server["id"], network_id=self.new_net["id"])['ports']
Yair Friedbc46f592015-11-18 16:29:34 +0200868 spoof_port = new_ports[0]
869 private_key = self._get_server_key(server)
Steve Heyman33735f22016-05-24 09:28:08 -0500870 ssh_client = self.get_remote_client(fip['floating_ip_address'],
zhuflf52c7592017-05-25 13:55:24 +0800871 private_key=private_key,
872 server=server)
Evgeny Antyshev9b77ae52016-02-16 09:48:57 +0000873 spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
zhufl24208c22016-10-25 15:23:48 +0800874 peer = self._create_server(self.new_net)
Steve Heyman33735f22016-05-24 09:28:08 -0500875 peer_address = peer['addresses'][self.new_net['name']][0]['addr']
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900876 self.check_remote_connectivity(ssh_client, dest=peer_address,
877 nic=spoof_nic, should_succeed=True)
Ken'ichi Ohmichi5129c622017-03-22 11:18:42 -0700878 # Set a mac address by making nic down temporary
879 cmd = ("sudo ip link set {nic} down;"
880 "sudo ip link set dev {nic} address {mac};"
881 "sudo ip link set {nic} up").format(nic=spoof_nic,
882 mac=spoof_mac)
883 ssh_client.exec_command(cmd)
884
Yair Friedbc46f592015-11-18 16:29:34 +0200885 new_mac = ssh_client.get_mac_address(nic=spoof_nic)
886 self.assertEqual(spoof_mac, new_mac)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900887 self.check_remote_connectivity(ssh_client, dest=peer_address,
888 nic=spoof_nic, should_succeed=False)
Yair Friedbc46f592015-11-18 16:29:34 +0200889 self.ports_client.update_port(spoof_port["id"],
890 port_security_enabled=False,
891 security_groups=[])
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900892 self.check_remote_connectivity(ssh_client, dest=peer_address,
893 nic=spoof_nic, should_succeed=True)