blob: f46c7e8c20bd613e31d73e77bc01d6c16742b684 [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 ]
Andrew Boik4a3daf12015-03-27 01:59:31 -0400349 self.assertEqual(1, len(v4_subnets),
350 "Found %d IPv4 subnets" % len(v4_subnets))
Yair Fried06552292013-11-11 12:10:09 +0200351
Andrew Boik4a3daf12015-03-27 01:59:31 -0400352 external_ips = [v4_subnets[0]['gateway_ip']]
Yair Fried06552292013-11-11 12:10:09 +0200353 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
354 external_ips)
355
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300356 def _check_server_connectivity(self, floating_ip, address_list,
357 should_connect=True):
Steve Heyman33735f22016-05-24 09:28:08 -0500358 ip_address = floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300359 private_key = self._get_server_key(self.floating_ip_tuple.server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100360 ssh_source = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800361 ip_address, private_key=private_key,
362 server=self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200363
Yair Fried06552292013-11-11 12:10:09 +0200364 for remote_ip in address_list:
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900365 self.check_remote_connectivity(ssh_source, remote_ip,
366 should_connect)
Yair Fried3097dc12014-01-26 08:46:43 +0200367
zhuflafe96b82017-09-22 14:25:29 +0800368 def _update_router_admin_state(self, router, admin_state_up):
369 kwargs = dict(admin_state_up=admin_state_up)
370 router = self.routers_client.update_router(
371 router['id'], **kwargs)['router']
372 self.assertEqual(admin_state_up, router['admin_state_up'])
373
Jordan Pittier3b46d272017-04-12 16:17:28 +0200374 @decorators.attr(type='smoke')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800375 @decorators.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Andrea Frittolicd368412017-08-14 21:37:56 +0100376 @utils.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000377 def test_network_basic_ops(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000378 """Basic network operation test
379
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600380 For a freshly-booted VM with an IP address ("port") on a given network:
Yair Fried3097dc12014-01-26 08:46:43 +0200381
382 - the Tempest host can ping the IP address. This implies, but
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600383 does not guarantee (see the ssh check that follows), that the
384 VM has been assigned the correct IP address and has
385 connectivity to the Tempest host.
Yair Fried3097dc12014-01-26 08:46:43 +0200386
387 - the Tempest host can perform key-based authentication to an
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600388 ssh server hosted at the IP address. This check guarantees
389 that the IP address is associated with the target VM.
Yair Fried3097dc12014-01-26 08:46:43 +0200390
Yair Fried3097dc12014-01-26 08:46:43 +0200391 - the Tempest host can ssh into the VM via the IP address and
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600392 successfully execute the following:
Yair Fried3097dc12014-01-26 08:46:43 +0200393
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600394 - ping an external IP address, implying external connectivity.
Yair Fried3097dc12014-01-26 08:46:43 +0200395
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600396 - ping an external hostname, implying that dns is correctly
397 configured.
Yair Fried3097dc12014-01-26 08:46:43 +0200398
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600399 - ping an internal IP address, implying connectivity to another
400 VM on the same network.
Yair Fried3097dc12014-01-26 08:46:43 +0200401
Yair Fried06552292013-11-11 12:10:09 +0200402 - detach the floating-ip from the VM and verify that it becomes
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600403 unreachable
Yair Fried06552292013-11-11 12:10:09 +0200404
405 - associate detached floating ip to a new VM and verify connectivity.
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600406 VMs are created with unique keypair so connectivity also asserts
407 that floating IP is associated with the new VM instead of the old
408 one
Yair Fried06552292013-11-11 12:10:09 +0200409
Yair Fried45f92952014-06-26 05:19:19 +0300410 Verifies that floating IP status is updated correctly after each change
Yair Fried3097dc12014-01-26 08:46:43 +0200411 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400412 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800413 self._check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200414 self._check_network_internal_connectivity(network=self.network)
415 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200416 self._disassociate_floating_ips()
zhufl0ec74c42017-11-15 14:02:28 +0800417 self._check_public_network_connectivity(should_connect=False,
418 msg="after disassociate "
419 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200420 self._reassociate_floating_ips()
zhufl0ec74c42017-11-15 14:02:28 +0800421 self._check_public_network_connectivity(should_connect=True,
422 msg="after re-associate "
423 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200424
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800425 @decorators.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
Andrea Frittolicd368412017-08-14 21:37:56 +0100426 @testtools.skipUnless(utils.is_extension_enabled('net-mtu', 'network'),
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000427 'No way to calculate MTU for networks')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200428 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100429 @utils.services('compute', 'network')
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000430 def test_mtu_sized_frames(self):
431 """Validate that network MTU sized frames fit through."""
432 self._setup_network_and_servers()
Ihar Hrachyshkaaca29ed2017-09-25 12:13:53 -0700433 # first check that connectivity works in general for the instance
zhufl0ec74c42017-11-15 14:02:28 +0800434 self._check_public_network_connectivity(should_connect=True)
Ihar Hrachyshkaaca29ed2017-09-25 12:13:53 -0700435 # now that we checked general connectivity, test that full size frames
436 # can also pass between nodes
zhufl0ec74c42017-11-15 14:02:28 +0800437 self._check_public_network_connectivity(
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000438 should_connect=True, mtu=self.network['mtu'])
439
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800440 @decorators.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
Thiago Paiva66cded22016-08-15 14:55:58 -0300441 @testtools.skipIf(CONF.network.shared_physical_network,
442 'Connectivity can only be tested when in a '
443 'multitenant network environment')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200444 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100445 @utils.services('compute', 'network')
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300446 def test_connectivity_between_vms_on_different_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000447 """Test connectivity between VMs on different networks
448
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600449 For a freshly-booted VM with an IP address ("port") on a given network:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300450
451 - the Tempest host can ping the IP address.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300452 - the Tempest host can ssh into the VM via the IP address and
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600453 successfully execute the following:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300454
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600455 - ping an external IP address, implying external connectivity.
456 - ping an external hostname, implying that dns is correctly
457 configured.
458 - ping an internal IP address, implying connectivity to another
459 VM on the same network.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300460
461 - Create another network on the same tenant with subnet, create
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600462 an VM on the new network.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300463
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600464 - Ping the new VM from previous VM failed since the new network
465 was not attached to router yet.
466 - Attach the new network to the router, Ping the new VM from
467 previous VM succeed.
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300468
469 """
470 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800471 self._check_public_network_connectivity(should_connect=True)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300472 self._check_network_internal_connectivity(network=self.network)
473 self._check_network_external_connectivity()
474 self._create_new_network(create_gateway=True)
Lucas Alvares Gomesd595c362018-10-16 14:38:11 +0100475 new_server = self._create_server(self.new_net)
476 new_server_ips = [addr['addr'] for addr in
477 new_server['addresses'][self.new_net['name']]]
478
479 # Assert that pinging the new VM fails since the new network is not
480 # connected to a router
481 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
482 new_server_ips, should_connect=False)
Steve Heyman33735f22016-05-24 09:28:08 -0500483 router_id = self.router['id']
484 self.routers_client.add_router_interface(
485 router_id, subnet_id=self.new_subnet['id'])
486
487 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
488 self.routers_client.remove_router_interface,
489 router_id, subnet_id=self.new_subnet['id'])
Lucas Alvares Gomesd595c362018-10-16 14:38:11 +0100490
491 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
492 new_server_ips, should_connect=True)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300493
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800494 @decorators.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400495 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
496 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200497 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
498 'NIC hotplug not supported for '
499 'vnic_type direct or macvtap')
Andrea Frittolicd368412017-08-14 21:37:56 +0100500 @utils.services('compute', 'network')
Yair Fried3097dc12014-01-26 08:46:43 +0200501 def test_hotplug_nic(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000502 """Test hotplug network interface
503
Arief3f6e812016-09-28 16:48:20 +0300504 1. Create a network and a VM.
505 2. Check connectivity to the VM via a public network.
506 3. Create a new network, with no gateway.
507 4. Bring up a new interface
508 5. check the VM reach the new network
Yair Fried3097dc12014-01-26 08:46:43 +0200509
510 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400511 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800512 self._check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200513 self._create_new_network()
514 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200515 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700516
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800517 @decorators.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Thiago Paiva66cded22016-08-15 14:55:58 -0300518 @testtools.skipIf(CONF.network.shared_physical_network,
519 'Router state can be altered only with multitenant '
520 'networks capabilities')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200521 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100522 @utils.services('compute', 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700523 def test_update_router_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000524 """Test to update admin state up of router
525
Alok Maurya6384bbb2014-07-13 06:44:29 -0700526 1. Check public connectivity before updating
527 admin_state_up attribute of router to False
528 2. Check public connectivity after updating
529 admin_state_up attribute of router to False
530 3. Check public connectivity after updating
531 admin_state_up attribute of router to True
532 """
533 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800534 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700535 should_connect=True, msg="before updating "
536 "admin_state_up of router to False")
537 self._update_router_admin_state(self.router, False)
538 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
539 # once bug 1396310 is fixed
540
zhufl0ec74c42017-11-15 14:02:28 +0800541 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700542 should_connect=False, msg="after updating "
543 "admin_state_up of router to False",
544 should_check_floating_ip_status=False)
545 self._update_router_admin_state(self.router, True)
zhufl0ec74c42017-11-15 14:02:28 +0800546 self._check_public_network_connectivity(
Alok Maurya6384bbb2014-07-13 06:44:29 -0700547 should_connect=True, msg="after updating "
548 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200549
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800550 @decorators.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Thiago Paiva66cded22016-08-15 14:55:58 -0300551 @testtools.skipIf(CONF.network.shared_physical_network,
552 'network isolation not available')
Yair Fried413bf2d2014-11-19 17:07:11 +0200553 @testtools.skipUnless(CONF.scenario.dhcp_client,
554 "DHCP client is not available.")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200555 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100556 @utils.services('compute', 'network')
Yair Fried413bf2d2014-11-19 17:07:11 +0200557 def test_subnet_details(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000558 """Tests that subnet's extra configuration details are affecting VMs.
559
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600560 This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200561
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600562 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
563 update in subnet requires server to actively renew its DHCP lease.
Yair Fried413bf2d2014-11-19 17:07:11 +0200564
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600565 1. Configure subnet with dns nameserver
566 2. retrieve the VM's configured dns and verify it matches the one
567 configured for the subnet.
568 3. update subnet's dns
569 4. retrieve the VM's configured dns and verify it matches the new one
570 configured for the subnet.
Yair Fried413bf2d2014-11-19 17:07:11 +0200571
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600572 TODO(yfried): add host_routes
Yair Fried413bf2d2014-11-19 17:07:11 +0200573
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600574 any resolution check would be testing either:
575
576 * l3 forwarding (tested in test_network_basic_ops)
577 * Name resolution of an external DNS nameserver - out of scope for
578 Tempest
Yair Fried413bf2d2014-11-19 17:07:11 +0200579 """
580 # this test check only updates (no actual resolution) so using
581 # arbitrary ip addresses as nameservers, instead of parsing CONF
582 initial_dns_server = '1.2.3.4'
583 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000584
Bence Romsics199e0222019-01-28 14:18:00 +0100585 # Original timeouts are suggested by salvatore-orlando in
Yair Friedbb0ea392015-01-19 07:26:08 +0000586 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
Bence Romsics199e0222019-01-28 14:18:00 +0100587 #
588 # Compared to that renew_delay was increased, because
589 # busybox's udhcpc accepts SIGUSR1 as a renew request. Internally
590 # it goes into RENEW_REQUESTED state. If it receives a 2nd SIGUSR1
591 # signal while in that state then it calls the deconfig script
592 # ("/sbin/cirros-dhcpc deconfig" in sufficiently new cirros versions)
593 # which leads to the address being transiently deconfigured which
594 # for our case is unwanted.
595 renew_delay = 3 * CONF.network.build_interval
Yair Friedbb0ea392015-01-19 07:26:08 +0000596 renew_timeout = CONF.network.build_timeout
597
Yair Fried413bf2d2014-11-19 17:07:11 +0200598 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
zhufl0ec74c42017-11-15 14:02:28 +0800599 self._check_public_network_connectivity(should_connect=True)
Yair Fried413bf2d2014-11-19 17:07:11 +0200600
601 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500602 ip_address = floating_ip['floating_ip_address']
Yair Fried413bf2d2014-11-19 17:07:11 +0200603 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100604 ssh_client = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800605 ip_address, private_key=private_key, server=server)
Yair Fried413bf2d2014-11-19 17:07:11 +0200606
armando-migliaccio424aa412015-02-22 17:55:17 -0800607 dns_servers = [initial_dns_server]
608 servers = ssh_client.get_dns_servers()
609 self.assertEqual(set(dns_servers), set(servers),
610 'Looking for servers: {trgt_serv}. '
611 'Retrieved DNS nameservers: {act_serv} '
612 'From host: {host}.'
613 .format(host=ssh_client.ssh_client.host,
614 act_serv=servers,
615 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200616
Steve Heyman33735f22016-05-24 09:28:08 -0500617 self.subnet = self.subnets_client.update_subnet(
618 self.subnet['id'], dns_nameservers=[alt_dns_server])['subnet']
619
Yair Fried413bf2d2014-11-19 17:07:11 +0200620 # asserts that Neutron DB has updated the nameservers
Steve Heyman33735f22016-05-24 09:28:08 -0500621 self.assertEqual([alt_dns_server], self.subnet['dns_nameservers'],
Yair Fried413bf2d2014-11-19 17:07:11 +0200622 "Failed to update subnet's nameservers")
623
Yair Friedbb0ea392015-01-19 07:26:08 +0000624 def check_new_dns_server():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000625 # NOTE: Server needs to renew its dhcp lease in order to get new
626 # definitions from subnet
627 # NOTE(amuller): we are renewing the lease as part of the retry
628 # because Neutron updates dnsmasq asynchronously after the
629 # subnet-update API call returns.
Ken'ichi Ohmichi4e337852017-03-01 12:04:23 -0800630 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'],
631 dhcp_client=CONF.scenario.dhcp_client)
armando-migliaccio424aa412015-02-22 17:55:17 -0800632 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000633 LOG.debug("Failed to update DNS nameservers")
634 return False
635 return True
636
Jordan Pittier35a63752016-08-30 13:09:12 +0200637 self.assertTrue(test_utils.call_until_true(check_new_dns_server,
638 renew_timeout,
639 renew_delay),
Yair Friedbb0ea392015-01-19 07:26:08 +0000640 msg="DHCP renewal failed to fetch "
641 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800642
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800643 @decorators.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300644 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
645 "Changing a port's admin state is not supported "
646 "by the test environment")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200647 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100648 @utils.services('compute', 'network')
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800649 def test_update_instance_port_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000650 """Test to update admin_state_up attribute of instance port
651
Carlos Goncalves539f8362016-11-04 14:55:02 +0100652 1. Check public and project connectivity before updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800653 admin_state_up attribute of instance port to False
Carlos Goncalves539f8362016-11-04 14:55:02 +0100654 2. Check public and project connectivity after updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800655 admin_state_up attribute of instance port to False
Carlos Goncalves539f8362016-11-04 14:55:02 +0100656 3. Check public and project connectivity after updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800657 admin_state_up attribute of instance port to True
658 """
659 self._setup_network_and_servers()
Ferenc Horváthbce1fcf2017-06-07 11:19:51 +0200660 _, server = self.floating_ip_tuple
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800661 server_id = server['id']
jeremy.zhang5870ff12017-05-25 11:24:23 +0800662 port_id = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100663 device_id=server_id)['ports'][0]['id']
Carlos Goncalves539f8362016-11-04 14:55:02 +0100664 server_pip = server['addresses'][self.network['name']][0]['addr']
665
666 server2 = self._create_server(self.network)
667 server2_fip = self.create_floating_ip(server2)
668
669 private_key = self._get_server_key(server2)
670 ssh_client = self.get_remote_client(server2_fip['floating_ip_address'],
zhuflf52c7592017-05-25 13:55:24 +0800671 private_key=private_key,
672 server=server2)
Carlos Goncalves539f8362016-11-04 14:55:02 +0100673
zhufl0ec74c42017-11-15 14:02:28 +0800674 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800675 should_connect=True, msg="before updating "
676 "admin_state_up of instance port to False")
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900677 self.check_remote_connectivity(ssh_client, dest=server_pip,
678 should_succeed=True)
John Warren49c0fe52015-10-22 12:35:54 -0400679 self.ports_client.update_port(port_id, admin_state_up=False)
zhufl0ec74c42017-11-15 14:02:28 +0800680 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800681 should_connect=False, msg="after updating "
682 "admin_state_up of instance port to False",
683 should_check_floating_ip_status=False)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900684 self.check_remote_connectivity(ssh_client, dest=server_pip,
685 should_succeed=False)
John Warren49c0fe52015-10-22 12:35:54 -0400686 self.ports_client.update_port(port_id, admin_state_up=True)
zhufl0ec74c42017-11-15 14:02:28 +0800687 self._check_public_network_connectivity(
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800688 should_connect=True, msg="after updating "
689 "admin_state_up of instance port to True")
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900690 self.check_remote_connectivity(ssh_client, dest=server_pip,
691 should_succeed=True)
Matt Riedemann17940732015-03-13 14:18:19 +0000692
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800693 @decorators.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200694 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100695 @utils.services('compute', 'network')
Matt Riedemann17940732015-03-13 14:18:19 +0000696 def test_preserve_preexisting_port(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000697 """Test preserve pre-existing port
698
699 Tests that a pre-existing port provided on server boot is not deleted
700 if the server is deleted.
Matt Riedemann17940732015-03-13 14:18:19 +0000701
702 Nova should unbind the port from the instance on delete if the port was
703 not created by Nova as part of the boot request.
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400704
705 We should also be able to boot another server with the same port.
Matt Riedemann17940732015-03-13 14:18:19 +0000706 """
707 # Setup the network, create a port and boot the server from that port.
708 self._setup_network_and_servers(boot_with_port=True)
709 _, server = self.floating_ip_tuple
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000710 self.assertEqual(1, len(self.ports),
711 'There should only be one port created for '
712 'server %s.' % server['id'])
713 port_id = self.ports[0]['port']
714 self.assertIsNotNone(port_id,
Matt Riedemann17940732015-03-13 14:18:19 +0000715 'Server should have been created from a '
716 'pre-existing port.')
717 # Assert the port is bound to the server.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800718 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100719 device_id=server['id'], network_id=self.network['id'])['ports']
Matt Riedemann17940732015-03-13 14:18:19 +0000720 self.assertEqual(1, len(port_list),
721 'There should only be one port created for '
722 'server %s.' % server['id'])
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000723 self.assertEqual(port_id, port_list[0]['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000724 # Delete the server.
725 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000726 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000727 # Assert the port still exists on the network but is unbound from
728 # the deleted server.
John Warren49c0fe52015-10-22 12:35:54 -0400729 port = self.ports_client.show_port(port_id)['port']
Matt Riedemann17940732015-03-13 14:18:19 +0000730 self.assertEqual(self.network['id'], port['network_id'])
731 self.assertEqual('', port['device_id'])
732 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300733
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400734 # Boot another server with the same port to make sure nothing was
735 # left around that could cause issues.
zhufl24208c22016-10-25 15:23:48 +0800736 server = self._create_server(self.network, port['id'])
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 Riedemanna8c641a2016-07-12 17:07:33 -0400739 self.assertEqual(1, len(port_list),
740 'There should only be one port created for '
741 'server %s.' % server['id'])
742 self.assertEqual(port['id'], port_list[0]['id'])
743
Andrea Frittolicd368412017-08-14 21:37:56 +0100744 @utils.requires_ext(service='network', extension='l3_agent_scheduler')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800745 @decorators.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200746 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100747 @utils.services('compute', 'network')
Yair Fried564d89d2015-08-06 17:02:12 +0300748 def test_router_rescheduling(self):
749 """Tests that router can be removed from agent and add to a new agent.
750
751 1. Verify connectivity
752 2. Remove router from all l3-agents
753 3. Verify connectivity is down
754 4. Assign router to new l3-agent (or old one if no new agent is
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600755 available)
Yair Fried564d89d2015-08-06 17:02:12 +0300756 5. Verify connectivity
757 """
758
759 # TODO(yfried): refactor this test to be used for other agents (dhcp)
760 # as well
761
jeremy.zhang5870ff12017-05-25 11:24:23 +0800762 list_hosts = (self.os_admin.routers_client.
Yair Fried564d89d2015-08-06 17:02:12 +0300763 list_l3_agents_hosting_router)
jeremy.zhang5870ff12017-05-25 11:24:23 +0800764 schedule_router = (self.os_admin.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000765 create_router_on_l3_agent)
jeremy.zhang5870ff12017-05-25 11:24:23 +0800766 unschedule_router = (self.os_admin.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000767 delete_router_from_l3_agent)
Yair Fried564d89d2015-08-06 17:02:12 +0300768
Jordan Pittier64e6b442017-02-20 19:29:02 +0100769 agent_list_alive = set(
770 a["id"] for a in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800771 self.os_admin.network_agents_client.list_agents(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100772 agent_type="L3 agent")['agents'] if a["alive"] is True
773 )
Yair Fried564d89d2015-08-06 17:02:12 +0300774 self._setup_network_and_servers()
Kevin Benton3b63aa12015-08-27 17:15:44 -0700775
776 # NOTE(kevinbenton): we have to use the admin credentials to check
Sean Dagueed6e5862016-04-04 10:49:13 -0400777 # for the distributed flag because self.router only has a project view.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800778 admin = self.os_admin.routers_client.show_router(
Steve Heyman33735f22016-05-24 09:28:08 -0500779 self.router['id'])
Kevin Benton3b63aa12015-08-27 17:15:44 -0700780 if admin['router'].get('distributed', False):
781 msg = "Rescheduling test does not apply to distributed routers."
782 raise self.skipException(msg)
783
zhufl0ec74c42017-11-15 14:02:28 +0800784 self._check_public_network_connectivity(should_connect=True)
Yair Fried564d89d2015-08-06 17:02:12 +0300785
786 # remove resource from agents
787 hosting_agents = set(a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500788 list_hosts(self.router['id'])['agents'])
shipeiqic9a4a102016-04-20 17:39:03 +0800789 no_migration = agent_list_alive == hosting_agents
Yair Fried564d89d2015-08-06 17:02:12 +0300790 LOG.info("Router will be assigned to {mig} hosting agent".
791 format(mig="the same" if no_migration else "a new"))
792
793 for hosting_agent in hosting_agents:
Steve Heyman33735f22016-05-24 09:28:08 -0500794 unschedule_router(hosting_agent, self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300795 self.assertNotIn(hosting_agent,
796 [a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500797 list_hosts(self.router['id'])['agents']],
Yair Fried564d89d2015-08-06 17:02:12 +0300798 'unscheduling router failed')
799
800 # verify resource is un-functional
zhufl0ec74c42017-11-15 14:02:28 +0800801 self._check_public_network_connectivity(
Yair Fried564d89d2015-08-06 17:02:12 +0300802 should_connect=False,
803 msg='after router unscheduling',
Yair Fried564d89d2015-08-06 17:02:12 +0300804 )
805
806 # schedule resource to new agent
807 target_agent = list(hosting_agents if no_migration else
shipeiqic9a4a102016-04-20 17:39:03 +0800808 agent_list_alive - hosting_agents)[0]
Yair Fried564d89d2015-08-06 17:02:12 +0300809 schedule_router(target_agent,
piyush110786bc0faa62015-12-03 14:54:48 +0530810 router_id=self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300811 self.assertEqual(
812 target_agent,
Steve Heyman33735f22016-05-24 09:28:08 -0500813 list_hosts(self.router['id'])['agents'][0]['id'],
Yair Fried564d89d2015-08-06 17:02:12 +0300814 "Router failed to reschedule. Hosting agent doesn't match "
815 "target agent")
816
817 # verify resource is functional
zhufl0ec74c42017-11-15 14:02:28 +0800818 self._check_public_network_connectivity(
Yair Fried564d89d2015-08-06 17:02:12 +0300819 should_connect=True,
820 msg='After router rescheduling')
Yair Friedbc46f592015-11-18 16:29:34 +0200821
Andrea Frittolicd368412017-08-14 21:37:56 +0100822 @utils.requires_ext(service='network', extension='port-security')
Evgeny Antyshevaaf3fc92016-02-15 11:49:22 +0000823 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
824 'NIC hotplug not available')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800825 @decorators.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200826 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100827 @utils.services('compute', 'network')
Yair Friedbc46f592015-11-18 16:29:34 +0200828 def test_port_security_macspoofing_port(self):
829 """Tests port_security extension enforces mac spoofing
830
Eran Kuris7969e802015-12-15 13:43:46 +0200831 Neutron security groups always apply anti-spoof rules on the VMs. This
832 allows traffic to originate and terminate at the VM as expected, but
833 prevents traffic to pass through the VM. Anti-spoof rules are not
834 required in cases where the VM routes traffic through it.
835
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600836 The test steps are:
837
Eran Kuris7969e802015-12-15 13:43:46 +0200838 1. Create a new network.
839 2. Connect (hotplug) the VM to a new network.
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900840 3. Check the VM can ping a server on the new network ("peer")
Eran Kuris7969e802015-12-15 13:43:46 +0200841 4. Spoof the mac address of the new VM interface.
842 5. Check the Security Group enforces mac spoofing and blocks pings via
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900843 spoofed interface (VM cannot ping the peer).
Eran Kuris7969e802015-12-15 13:43:46 +0200844 6. Disable port-security of the spoofed port- set the flag to false.
845 7. Retest 3rd step and check that the Security Group allows pings via
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600846 the spoofed interface.
Yair Friedbc46f592015-11-18 16:29:34 +0200847 """
Eran Kuris7969e802015-12-15 13:43:46 +0200848
Yair Friedbc46f592015-11-18 16:29:34 +0200849 spoof_mac = "00:00:00:00:00:01"
850
851 # Create server
852 self._setup_network_and_servers()
zhufl0ec74c42017-11-15 14:02:28 +0800853 self._check_public_network_connectivity(should_connect=True)
Yair Friedbc46f592015-11-18 16:29:34 +0200854 self._create_new_network()
855 self._hotplug_server()
856 fip, server = self.floating_ip_tuple
jeremy.zhang5870ff12017-05-25 11:24:23 +0800857 new_ports = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100858 device_id=server["id"], network_id=self.new_net["id"])['ports']
Yair Friedbc46f592015-11-18 16:29:34 +0200859 spoof_port = new_ports[0]
860 private_key = self._get_server_key(server)
Steve Heyman33735f22016-05-24 09:28:08 -0500861 ssh_client = self.get_remote_client(fip['floating_ip_address'],
zhuflf52c7592017-05-25 13:55:24 +0800862 private_key=private_key,
863 server=server)
Evgeny Antyshev9b77ae52016-02-16 09:48:57 +0000864 spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
zhufl24208c22016-10-25 15:23:48 +0800865 peer = self._create_server(self.new_net)
Steve Heyman33735f22016-05-24 09:28:08 -0500866 peer_address = peer['addresses'][self.new_net['name']][0]['addr']
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900867 self.check_remote_connectivity(ssh_client, dest=peer_address,
868 nic=spoof_nic, should_succeed=True)
Ken'ichi Ohmichi5129c622017-03-22 11:18:42 -0700869 # Set a mac address by making nic down temporary
870 cmd = ("sudo ip link set {nic} down;"
871 "sudo ip link set dev {nic} address {mac};"
872 "sudo ip link set {nic} up").format(nic=spoof_nic,
873 mac=spoof_mac)
874 ssh_client.exec_command(cmd)
875
Yair Friedbc46f592015-11-18 16:29:34 +0200876 new_mac = ssh_client.get_mac_address(nic=spoof_nic)
877 self.assertEqual(spoof_mac, new_mac)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900878 self.check_remote_connectivity(ssh_client, dest=peer_address,
879 nic=spoof_nic, should_succeed=False)
Yair Friedbc46f592015-11-18 16:29:34 +0200880 self.ports_client.update_port(spoof_port["id"],
881 port_security_enabled=False,
882 security_groups=[])
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900883 self.check_remote_connectivity(ssh_client, dest=peer_address,
884 nic=spoof_nic, should_succeed=True)