blob: 1c4e26223f8e579ed9da2d4f6990461816bdfb7b [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()
Sean Dagueed6e5862016-04-04 10:49:13 -040084 if not (CONF.network.project_networks_reachable
Matthew Treinish6c072292014-01-29 19:15:52 +000085 or 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)
Yair Frieded8392f2014-01-15 17:21:35 +0200120 self._check_tenant_network_connectivity()
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200121
Yair Friedae0e73d2014-11-24 11:56:26 +0200122 floating_ip = self.create_floating_ip(server)
123 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Maru Newby81f07a02012-09-05 20:21:19 -0700124
Yair Frieded8392f2014-01-15 17:21:35 +0200125 def check_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000126 """Checks that we see the newly created network/subnet/router
127
128 via checking the result of list_[networks,routers,subnets]
Yair Frieded8392f2014-01-15 17:21:35 +0200129 """
130
jeremy.zhang5870ff12017-05-25 11:24:23 +0800131 seen_nets = self.os_admin.networks_client.list_networks()
Jordan Pittier64e6b442017-02-20 19:29:02 +0100132 seen_names = [n['name'] for n in seen_nets['networks']]
133 seen_ids = [n['id'] for n in seen_nets['networks']]
Steve Heyman33735f22016-05-24 09:28:08 -0500134 self.assertIn(self.network['name'], seen_names)
135 self.assertIn(self.network['id'], seen_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200136
David Shrewsbury9bac3662014-08-07 15:07:01 -0400137 if self.subnet:
jeremy.zhang5870ff12017-05-25 11:24:23 +0800138 seen_subnets = self.os_admin.subnets_client.list_subnets()
Jordan Pittier64e6b442017-02-20 19:29:02 +0100139 seen_net_ids = [n['network_id'] for n in seen_subnets['subnets']]
140 seen_subnet_ids = [n['id'] for n in seen_subnets['subnets']]
Steve Heyman33735f22016-05-24 09:28:08 -0500141 self.assertIn(self.network['id'], seen_net_ids)
142 self.assertIn(self.subnet['id'], seen_subnet_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200143
David Shrewsbury9bac3662014-08-07 15:07:01 -0400144 if self.router:
jeremy.zhang5870ff12017-05-25 11:24:23 +0800145 seen_routers = self.os_admin.routers_client.list_routers()
Jordan Pittier64e6b442017-02-20 19:29:02 +0100146 seen_router_ids = [n['id'] for n in seen_routers['routers']]
147 seen_router_names = [n['name'] for n in seen_routers['routers']]
Steve Heyman33735f22016-05-24 09:28:08 -0500148 self.assertIn(self.router['name'],
David Shrewsbury9bac3662014-08-07 15:07:01 -0400149 seen_router_names)
Steve Heyman33735f22016-05-24 09:28:08 -0500150 self.assertIn(self.router['id'],
David Shrewsbury9bac3662014-08-07 15:07:01 -0400151 seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000152
zhufl24208c22016-10-25 15:23:48 +0800153 def _create_server(self, network, port_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +0300154 keypair = self.create_keypair()
155 self.keypairs[keypair['name']] = keypair
Jordan Pittier37b94a02017-02-21 18:11:55 +0100156 security_groups = [
157 {'name': self._create_security_group()['name']}
158 ]
Steve Heyman33735f22016-05-24 09:28:08 -0500159 network = {'uuid': network['id']}
Matt Riedemann17940732015-03-13 14:18:19 +0000160 if port_id is not None:
lanoux5fc14522015-09-21 08:17:35 +0000161 network['port'] = port_id
162
163 server = self.create_server(
lanoux5fc14522015-09-21 08:17:35 +0000164 networks=[network],
165 key_name=keypair['name'],
zhufl13c9c892017-02-10 12:04:07 +0800166 security_groups=security_groups)
Yair Fried1fc32a12014-08-04 09:11:30 +0300167 self.servers.append(server)
168 return server
169
170 def _get_server_key(self, server):
171 return self.keypairs[server['key_name']]['private_key']
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700172
Matthew Treinish2b59f842013-09-09 20:32:51 +0000173 def _check_tenant_network_connectivity(self):
lanoux283273b2015-12-04 03:01:54 -0800174 ssh_login = CONF.validation.image_ssh_user
Yair Fried1fc32a12014-08-04 09:11:30 +0300175 for server in self.servers:
Matt Riedemann2d005be2014-05-27 10:52:35 -0700176 # call the common method in the parent class
177 super(TestNetworkBasicOps, self).\
178 _check_tenant_network_connectivity(
Yair Fried1fc32a12014-08-04 09:11:30 +0300179 server, ssh_login, self._get_server_key(server),
180 servers_for_debug=self.servers)
Brent Eaglesc26d4522013-12-02 13:28:49 -0500181
Alok Maurya6384bbb2014-07-13 06:44:29 -0700182 def check_public_network_connectivity(
183 self, should_connect=True, msg=None,
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000184 should_check_floating_ip_status=True, mtu=None):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000185 """Verifies connectivty to a VM via public network and floating IP
186
Yair Fried45f92952014-06-26 05:19:19 +0300187 and verifies floating IP has resource status is correct.
188
Yair Fried45f92952014-06-26 05:19:19 +0300189 :param should_connect: bool. determines if connectivity check is
190 negative or positive.
191 :param msg: Failure message to add to Error message. Should describe
192 the place in the test scenario where the method was called,
193 to indicate the context of the failure
Alok Maurya6384bbb2014-07-13 06:44:29 -0700194 :param should_check_floating_ip_status: bool. should status of
195 floating_ip be checked or not
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000196 :param mtu: int. MTU network to use for connectivity validation
Yair Fried45f92952014-06-26 05:19:19 +0300197 """
lanoux283273b2015-12-04 03:01:54 -0800198 ssh_login = CONF.validation.image_ssh_user
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200199 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500200 ip_address = floating_ip['floating_ip_address']
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200201 private_key = None
Yair Fried45f92952014-06-26 05:19:19 +0300202 floatingip_status = 'DOWN'
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200203 if should_connect:
Yair Fried1fc32a12014-08-04 09:11:30 +0300204 private_key = self._get_server_key(server)
Yair Fried45f92952014-06-26 05:19:19 +0300205 floatingip_status = 'ACTIVE'
Swaminathan Vasudevandc8bcdb2015-02-28 12:47:21 -0800206 # Check FloatingIP Status before initiating a connection
207 if should_check_floating_ip_status:
208 self.check_floating_ip_status(floating_ip, floatingip_status)
Matt Riedemann343305f2014-05-27 09:55:03 -0700209 # call the common method in the parent class
Yair Friedae0e73d2014-11-24 11:56:26 +0200210 super(TestNetworkBasicOps, self).check_public_network_connectivity(
Matt Riedemann343305f2014-05-27 09:55:03 -0700211 ip_address, ssh_login, private_key, should_connect, msg,
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000212 self.servers, mtu=mtu)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000213
Yair Fried9a551c42013-12-15 14:59:34 +0200214 def _disassociate_floating_ips(self):
Ferenc Horváthbce1fcf2017-06-07 11:19:51 +0200215 floating_ip, _ = self.floating_ip_tuple
zhuflafe96b82017-09-22 14:25:29 +0800216 floating_ip = self.floating_ips_client.update_floatingip(
217 floating_ip['id'], port_id=None)['floatingip']
218 self.assertIsNone(floating_ip['port_id'])
219 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, None)
Yair Fried9a551c42013-12-15 14:59:34 +0200220
Yair Fried05db2522013-11-18 11:02:10 +0200221 def _reassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200222 floating_ip, server = self.floating_ip_tuple
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200223 # create a new server for the floating ip
zhufl24208c22016-10-25 15:23:48 +0800224 server = self._create_server(self.network)
zhuflafe96b82017-09-22 14:25:29 +0800225 port_id, _ = self._get_server_port_id_and_ip4(server)
226 floating_ip = self.floating_ips_client.update_floatingip(
227 floating_ip['id'], port_id=port_id)['floatingip']
228 self.assertEqual(port_id, floating_ip['port_id'])
229 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Yair Fried05db2522013-11-18 11:02:10 +0200230
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300231 def _create_new_network(self, create_gateway=False):
Marc Koderer410c7822016-11-08 11:47:00 +0100232 self.new_net = self._create_network()
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300233 if create_gateway:
234 self.new_subnet = self._create_subnet(
235 network=self.new_net)
236 else:
237 self.new_subnet = self._create_subnet(
238 network=self.new_net,
239 gateway_ip=None)
Yair Fried3097dc12014-01-26 08:46:43 +0200240
241 def _hotplug_server(self):
242 old_floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500243 ip_address = old_floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300244 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100245 ssh_client = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800246 ip_address, private_key=private_key, server=server)
Yair Fried3097dc12014-01-26 08:46:43 +0200247 old_nic_list = self._get_server_nics(ssh_client)
248 # get a port from a list of one item
jeremy.zhang5870ff12017-05-25 11:24:23 +0800249 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100250 device_id=server['id'])['ports']
Yair Fried3097dc12014-01-26 08:46:43 +0200251 self.assertEqual(1, len(port_list))
252 old_port = port_list[0]
David Kranzb2b0c182015-02-18 13:28:19 -0500253 interface = self.interface_client.create_interface(
Ken'ichi Ohmichi9509b962015-07-07 05:30:15 +0000254 server_id=server['id'],
Steve Heyman33735f22016-05-24 09:28:08 -0500255 net_id=self.new_net['id'])['interfaceAttachment']
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -0700256 self.addCleanup(self.ports_client.wait_for_resource_deletion,
257 interface['port_id'])
Jordan Pittier9e227c52016-02-09 14:35:18 +0100258 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Yair Fried1fc32a12014-08-04 09:11:30 +0300259 self.interface_client.delete_interface,
260 server['id'], interface['port_id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200261
262 def check_ports():
Jordan Pittier64e6b442017-02-20 19:29:02 +0100263 self.new_port_list = [
264 port for port in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800265 self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100266 device_id=server['id'])['ports']
267 if port['id'] != old_port['id']
268 ]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200269 return len(self.new_port_list) == 1
Yair Fried3097dc12014-01-26 08:46:43 +0200270
Jordan Pittier35a63752016-08-30 13:09:12 +0200271 if not test_utils.call_until_true(
272 check_ports, CONF.network.build_timeout,
273 CONF.network.build_interval):
Matt Riedemann892094e2015-02-05 07:24:02 -0800274 raise exceptions.TimeoutException(
275 "No new port attached to the server in time (%s sec)! "
276 "Old port: %s. Number of new ports: %d" % (
277 CONF.network.build_timeout, old_port,
278 len(self.new_port_list)))
Steve Heyman33735f22016-05-24 09:28:08 -0500279 new_port = self.new_port_list[0]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200280
281 def check_new_nic():
282 new_nic_list = self._get_server_nics(ssh_client)
283 self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
284 return len(self.diff_list) == 1
285
Jordan Pittier35a63752016-08-30 13:09:12 +0200286 if not test_utils.call_until_true(
287 check_new_nic, CONF.network.build_timeout,
288 CONF.network.build_interval):
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200289 raise exceptions.TimeoutException("Interface not visible on the "
290 "guest after %s sec"
291 % CONF.network.build_timeout)
292
Ferenc Horváthbce1fcf2017-06-07 11:19:51 +0200293 _, new_nic = self.diff_list[0]
Ken'ichi Ohmichi679f8c32017-03-17 11:05:26 -0700294 ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
295 new_port['fixed_ips'][0]['ip_address'],
296 CONF.network.project_network_mask_bits,
297 new_nic))
Ken'ichi Ohmichi126fe982017-03-17 10:41:44 -0700298 ssh_client.exec_command("sudo ip link set %s up" % new_nic)
Yair Fried3097dc12014-01-26 08:46:43 +0200299
300 def _get_server_nics(self, ssh_client):
James Pagea9366272017-06-09 12:05:09 +0100301 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+)[@]?.*:')
Ken'ichi Ohmichi84aeba62017-03-01 18:31:20 -0800302 ipatxt = ssh_client.exec_command("ip address")
Yair Fried3097dc12014-01-26 08:46:43 +0200303 return reg.findall(ipatxt)
304
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300305 def _check_network_internal_connectivity(self, network,
306 should_connect=True):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000307 """via ssh check VM internal connectivity:
308
Yair Fried06552292013-11-11 12:10:09 +0200309 - ping internal gateway and DHCP port, implying in-tenant connectivity
310 pinging both, because L3 and DHCP agents might be on different nodes
Yair Fried3097dc12014-01-26 08:46:43 +0200311 """
312 floating_ip, server = self.floating_ip_tuple
313 # get internal ports' ips:
314 # get all network ports in the new network
Jordan Pittier64e6b442017-02-20 19:29:02 +0100315 internal_ips = (
316 p['fixed_ips'][0]['ip_address'] for p in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800317 self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100318 tenant_id=server['tenant_id'],
319 network_id=network['id'])['ports']
320 if p['device_owner'].startswith('network')
321 )
Yair Fried3097dc12014-01-26 08:46:43 +0200322
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300323 self._check_server_connectivity(floating_ip,
324 internal_ips,
325 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200326
327 def _check_network_external_connectivity(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000328 """ping default gateway to imply external connectivity"""
Yair Fried06552292013-11-11 12:10:09 +0200329 if not CONF.network.public_network_id:
330 msg = 'public network not defined.'
331 LOG.info(msg)
332 return
333
Andrew Boik4a3daf12015-03-27 01:59:31 -0400334 # We ping the external IP from the instance using its floating IP
335 # which is always IPv4, so we must only test connectivity to
336 # external IPv4 IPs if the external network is dualstack.
Jordan Pittier64e6b442017-02-20 19:29:02 +0100337 v4_subnets = [
jeremy.zhang5870ff12017-05-25 11:24:23 +0800338 s for s in self.os_admin.subnets_client.list_subnets(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100339 network_id=CONF.network.public_network_id)['subnets']
340 if s['ip_version'] == 4
341 ]
Andrew Boik4a3daf12015-03-27 01:59:31 -0400342 self.assertEqual(1, len(v4_subnets),
343 "Found %d IPv4 subnets" % len(v4_subnets))
Yair Fried06552292013-11-11 12:10:09 +0200344
Andrew Boik4a3daf12015-03-27 01:59:31 -0400345 external_ips = [v4_subnets[0]['gateway_ip']]
Yair Fried06552292013-11-11 12:10:09 +0200346 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
347 external_ips)
348
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300349 def _check_server_connectivity(self, floating_ip, address_list,
350 should_connect=True):
Steve Heyman33735f22016-05-24 09:28:08 -0500351 ip_address = floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300352 private_key = self._get_server_key(self.floating_ip_tuple.server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100353 ssh_source = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800354 ip_address, private_key=private_key,
355 server=self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200356
Yair Fried06552292013-11-11 12:10:09 +0200357 for remote_ip in address_list:
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900358 self.check_remote_connectivity(ssh_source, remote_ip,
359 should_connect)
Yair Fried3097dc12014-01-26 08:46:43 +0200360
zhuflafe96b82017-09-22 14:25:29 +0800361 def _update_router_admin_state(self, router, admin_state_up):
362 kwargs = dict(admin_state_up=admin_state_up)
363 router = self.routers_client.update_router(
364 router['id'], **kwargs)['router']
365 self.assertEqual(admin_state_up, router['admin_state_up'])
366
Jordan Pittier3b46d272017-04-12 16:17:28 +0200367 @decorators.attr(type='smoke')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800368 @decorators.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Andrea Frittolicd368412017-08-14 21:37:56 +0100369 @utils.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000370 def test_network_basic_ops(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000371 """Basic network operation test
372
Yair Fried3097dc12014-01-26 08:46:43 +0200373 For a freshly-booted VM with an IP address ("port") on a given
374 network:
375
376 - the Tempest host can ping the IP address. This implies, but
377 does not guarantee (see the ssh check that follows), that the
378 VM has been assigned the correct IP address and has
379 connectivity to the Tempest host.
380
381 - the Tempest host can perform key-based authentication to an
382 ssh server hosted at the IP address. This check guarantees
383 that the IP address is associated with the target VM.
384
Yair Fried3097dc12014-01-26 08:46:43 +0200385 - the Tempest host can ssh into the VM via the IP address and
386 successfully execute the following:
387
388 - ping an external IP address, implying external connectivity.
389
390 - ping an external hostname, implying that dns is correctly
391 configured.
392
393 - ping an internal IP address, implying connectivity to another
394 VM on the same network.
395
Yair Fried06552292013-11-11 12:10:09 +0200396 - detach the floating-ip from the VM and verify that it becomes
397 unreachable
398
399 - associate detached floating ip to a new VM and verify connectivity.
400 VMs are created with unique keypair so connectivity also asserts that
401 floating IP is associated with the new VM instead of the old one
402
Yair Fried45f92952014-06-26 05:19:19 +0300403 Verifies that floating IP status is updated correctly after each change
404
Yair Fried06552292013-11-11 12:10:09 +0200405
Yair Fried3097dc12014-01-26 08:46:43 +0200406 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400407 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200408 self.check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200409 self._check_network_internal_connectivity(network=self.network)
410 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200411 self._disassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200412 self.check_public_network_connectivity(should_connect=False,
413 msg="after disassociate "
414 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200415 self._reassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200416 self.check_public_network_connectivity(should_connect=True,
417 msg="after re-associate "
418 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200419
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800420 @decorators.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
Andrea Frittolicd368412017-08-14 21:37:56 +0100421 @testtools.skipUnless(utils.is_extension_enabled('net-mtu', 'network'),
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000422 'No way to calculate MTU for networks')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200423 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100424 @utils.services('compute', 'network')
Ihar Hrachyshkaf9227c02016-09-15 11:16:47 +0000425 def test_mtu_sized_frames(self):
426 """Validate that network MTU sized frames fit through."""
427 self._setup_network_and_servers()
428 self.check_public_network_connectivity(
429 should_connect=True, mtu=self.network['mtu'])
430
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800431 @decorators.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
Thiago Paiva66cded22016-08-15 14:55:58 -0300432 @testtools.skipIf(CONF.network.shared_physical_network,
433 'Connectivity can only be tested when in a '
434 'multitenant network environment')
Sean Dague17487fb2016-08-08 10:44:20 -0400435 @decorators.skip_because(bug="1610994")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200436 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100437 @utils.services('compute', 'network')
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300438 def test_connectivity_between_vms_on_different_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000439 """Test connectivity between VMs on different networks
440
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300441 For a freshly-booted VM with an IP address ("port") on a given
442 network:
443
444 - the Tempest host can ping the IP address.
445
446 - the Tempest host can ssh into the VM via the IP address and
447 successfully execute the following:
448
449 - ping an external IP address, implying external connectivity.
450
451 - ping an external hostname, implying that dns is correctly
452 configured.
453
454 - ping an internal IP address, implying connectivity to another
455 VM on the same network.
456
457 - Create another network on the same tenant with subnet, create
458 an VM on the new network.
459
460 - Ping the new VM from previous VM failed since the new network
461 was not attached to router yet.
462
463 - Attach the new network to the router, Ping the new VM from
464 previous VM succeed.
465
466 """
467 self._setup_network_and_servers()
468 self.check_public_network_connectivity(should_connect=True)
469 self._check_network_internal_connectivity(network=self.network)
470 self._check_network_external_connectivity()
471 self._create_new_network(create_gateway=True)
zhufl24208c22016-10-25 15:23:48 +0800472 self._create_server(self.new_net)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300473 self._check_network_internal_connectivity(network=self.new_net,
474 should_connect=False)
Steve Heyman33735f22016-05-24 09:28:08 -0500475 router_id = self.router['id']
476 self.routers_client.add_router_interface(
477 router_id, subnet_id=self.new_subnet['id'])
478
479 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
480 self.routers_client.remove_router_interface,
481 router_id, subnet_id=self.new_subnet['id'])
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300482 self._check_network_internal_connectivity(network=self.new_net,
483 should_connect=True)
484
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800485 @decorators.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400486 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
487 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200488 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
489 'NIC hotplug not supported for '
490 'vnic_type direct or macvtap')
Andrea Frittolicd368412017-08-14 21:37:56 +0100491 @utils.services('compute', 'network')
Yair Fried3097dc12014-01-26 08:46:43 +0200492 def test_hotplug_nic(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000493 """Test hotplug network interface
494
Arief3f6e812016-09-28 16:48:20 +0300495 1. Create a network and a VM.
496 2. Check connectivity to the VM via a public network.
497 3. Create a new network, with no gateway.
498 4. Bring up a new interface
499 5. check the VM reach the new network
Yair Fried3097dc12014-01-26 08:46:43 +0200500
501 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400502 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200503 self.check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200504 self._create_new_network()
505 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200506 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700507
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800508 @decorators.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Thiago Paiva66cded22016-08-15 14:55:58 -0300509 @testtools.skipIf(CONF.network.shared_physical_network,
510 'Router state can be altered only with multitenant '
511 'networks capabilities')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200512 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100513 @utils.services('compute', 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700514 def test_update_router_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000515 """Test to update admin state up of router
516
Alok Maurya6384bbb2014-07-13 06:44:29 -0700517 1. Check public connectivity before updating
518 admin_state_up attribute of router to False
519 2. Check public connectivity after updating
520 admin_state_up attribute of router to False
521 3. Check public connectivity after updating
522 admin_state_up attribute of router to True
523 """
524 self._setup_network_and_servers()
525 self.check_public_network_connectivity(
526 should_connect=True, msg="before updating "
527 "admin_state_up of router to False")
528 self._update_router_admin_state(self.router, False)
529 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
530 # once bug 1396310 is fixed
531
532 self.check_public_network_connectivity(
533 should_connect=False, msg="after updating "
534 "admin_state_up of router to False",
535 should_check_floating_ip_status=False)
536 self._update_router_admin_state(self.router, True)
537 self.check_public_network_connectivity(
538 should_connect=True, msg="after updating "
539 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200540
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800541 @decorators.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Thiago Paiva66cded22016-08-15 14:55:58 -0300542 @testtools.skipIf(CONF.network.shared_physical_network,
543 'network isolation not available')
Yair Fried413bf2d2014-11-19 17:07:11 +0200544 @testtools.skipUnless(CONF.scenario.dhcp_client,
545 "DHCP client is not available.")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200546 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100547 @utils.services('compute', 'network')
Yair Fried413bf2d2014-11-19 17:07:11 +0200548 def test_subnet_details(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000549 """Tests that subnet's extra configuration details are affecting VMs.
550
551 This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200552
553 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
554 update in subnet requires server to actively renew its DHCP lease.
555
556 1. Configure subnet with dns nameserver
557 2. retrieve the VM's configured dns and verify it matches the one
558 configured for the subnet.
559 3. update subnet's dns
560 4. retrieve the VM's configured dns and verify it matches the new one
561 configured for the subnet.
562
563 TODO(yfried): add host_routes
564
565 any resolution check would be testing either:
566 * l3 forwarding (tested in test_network_basic_ops)
567 * Name resolution of an external DNS nameserver - out of scope for
568 Tempest
569 """
570 # this test check only updates (no actual resolution) so using
571 # arbitrary ip addresses as nameservers, instead of parsing CONF
572 initial_dns_server = '1.2.3.4'
573 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000574
575 # renewal should be immediate.
576 # Timeouts are suggested by salvatore-orlando in
577 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
578 renew_delay = CONF.network.build_interval
579 renew_timeout = CONF.network.build_timeout
580
Yair Fried413bf2d2014-11-19 17:07:11 +0200581 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
582 self.check_public_network_connectivity(should_connect=True)
583
584 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500585 ip_address = floating_ip['floating_ip_address']
Yair Fried413bf2d2014-11-19 17:07:11 +0200586 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100587 ssh_client = self.get_remote_client(
zhuflf52c7592017-05-25 13:55:24 +0800588 ip_address, private_key=private_key, server=server)
Yair Fried413bf2d2014-11-19 17:07:11 +0200589
armando-migliaccio424aa412015-02-22 17:55:17 -0800590 dns_servers = [initial_dns_server]
591 servers = ssh_client.get_dns_servers()
592 self.assertEqual(set(dns_servers), set(servers),
593 'Looking for servers: {trgt_serv}. '
594 'Retrieved DNS nameservers: {act_serv} '
595 'From host: {host}.'
596 .format(host=ssh_client.ssh_client.host,
597 act_serv=servers,
598 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200599
Steve Heyman33735f22016-05-24 09:28:08 -0500600 self.subnet = self.subnets_client.update_subnet(
601 self.subnet['id'], dns_nameservers=[alt_dns_server])['subnet']
602
Yair Fried413bf2d2014-11-19 17:07:11 +0200603 # asserts that Neutron DB has updated the nameservers
Steve Heyman33735f22016-05-24 09:28:08 -0500604 self.assertEqual([alt_dns_server], self.subnet['dns_nameservers'],
Yair Fried413bf2d2014-11-19 17:07:11 +0200605 "Failed to update subnet's nameservers")
606
Yair Friedbb0ea392015-01-19 07:26:08 +0000607 def check_new_dns_server():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000608 # NOTE: Server needs to renew its dhcp lease in order to get new
609 # definitions from subnet
610 # NOTE(amuller): we are renewing the lease as part of the retry
611 # because Neutron updates dnsmasq asynchronously after the
612 # subnet-update API call returns.
Ken'ichi Ohmichi4e337852017-03-01 12:04:23 -0800613 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'],
614 dhcp_client=CONF.scenario.dhcp_client)
armando-migliaccio424aa412015-02-22 17:55:17 -0800615 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000616 LOG.debug("Failed to update DNS nameservers")
617 return False
618 return True
619
Jordan Pittier35a63752016-08-30 13:09:12 +0200620 self.assertTrue(test_utils.call_until_true(check_new_dns_server,
621 renew_timeout,
622 renew_delay),
Yair Friedbb0ea392015-01-19 07:26:08 +0000623 msg="DHCP renewal failed to fetch "
624 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800625
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800626 @decorators.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300627 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
628 "Changing a port's admin state is not supported "
629 "by the test environment")
Jordan Pittier3b46d272017-04-12 16:17:28 +0200630 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100631 @utils.services('compute', 'network')
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800632 def test_update_instance_port_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000633 """Test to update admin_state_up attribute of instance port
634
Carlos Goncalves539f8362016-11-04 14:55:02 +0100635 1. Check public and project connectivity before updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800636 admin_state_up attribute of instance port to False
Carlos Goncalves539f8362016-11-04 14:55:02 +0100637 2. Check public and project connectivity after updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800638 admin_state_up attribute of instance port to False
Carlos Goncalves539f8362016-11-04 14:55:02 +0100639 3. Check public and project connectivity after updating
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800640 admin_state_up attribute of instance port to True
641 """
642 self._setup_network_and_servers()
Ferenc Horváthbce1fcf2017-06-07 11:19:51 +0200643 _, server = self.floating_ip_tuple
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800644 server_id = server['id']
jeremy.zhang5870ff12017-05-25 11:24:23 +0800645 port_id = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100646 device_id=server_id)['ports'][0]['id']
Carlos Goncalves539f8362016-11-04 14:55:02 +0100647 server_pip = server['addresses'][self.network['name']][0]['addr']
648
649 server2 = self._create_server(self.network)
650 server2_fip = self.create_floating_ip(server2)
651
652 private_key = self._get_server_key(server2)
653 ssh_client = self.get_remote_client(server2_fip['floating_ip_address'],
zhuflf52c7592017-05-25 13:55:24 +0800654 private_key=private_key,
655 server=server2)
Carlos Goncalves539f8362016-11-04 14:55:02 +0100656
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800657 self.check_public_network_connectivity(
658 should_connect=True, msg="before updating "
659 "admin_state_up of instance port to False")
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900660 self.check_remote_connectivity(ssh_client, dest=server_pip,
661 should_succeed=True)
John Warren49c0fe52015-10-22 12:35:54 -0400662 self.ports_client.update_port(port_id, admin_state_up=False)
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800663 self.check_public_network_connectivity(
664 should_connect=False, msg="after updating "
665 "admin_state_up of instance port to False",
666 should_check_floating_ip_status=False)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900667 self.check_remote_connectivity(ssh_client, dest=server_pip,
668 should_succeed=False)
John Warren49c0fe52015-10-22 12:35:54 -0400669 self.ports_client.update_port(port_id, admin_state_up=True)
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800670 self.check_public_network_connectivity(
671 should_connect=True, msg="after updating "
672 "admin_state_up of instance port to True")
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900673 self.check_remote_connectivity(ssh_client, dest=server_pip,
674 should_succeed=True)
Matt Riedemann17940732015-03-13 14:18:19 +0000675
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800676 @decorators.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200677 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100678 @utils.services('compute', 'network')
Matt Riedemann17940732015-03-13 14:18:19 +0000679 def test_preserve_preexisting_port(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000680 """Test preserve pre-existing port
681
682 Tests that a pre-existing port provided on server boot is not deleted
683 if the server is deleted.
Matt Riedemann17940732015-03-13 14:18:19 +0000684
685 Nova should unbind the port from the instance on delete if the port was
686 not created by Nova as part of the boot request.
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400687
688 We should also be able to boot another server with the same port.
Matt Riedemann17940732015-03-13 14:18:19 +0000689 """
690 # Setup the network, create a port and boot the server from that port.
691 self._setup_network_and_servers(boot_with_port=True)
692 _, server = self.floating_ip_tuple
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000693 self.assertEqual(1, len(self.ports),
694 'There should only be one port created for '
695 'server %s.' % server['id'])
696 port_id = self.ports[0]['port']
697 self.assertIsNotNone(port_id,
Matt Riedemann17940732015-03-13 14:18:19 +0000698 'Server should have been created from a '
699 'pre-existing port.')
700 # Assert the port is bound to the server.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800701 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100702 device_id=server['id'], network_id=self.network['id'])['ports']
Matt Riedemann17940732015-03-13 14:18:19 +0000703 self.assertEqual(1, len(port_list),
704 'There should only be one port created for '
705 'server %s.' % server['id'])
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000706 self.assertEqual(port_id, port_list[0]['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000707 # Delete the server.
708 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000709 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000710 # Assert the port still exists on the network but is unbound from
711 # the deleted server.
John Warren49c0fe52015-10-22 12:35:54 -0400712 port = self.ports_client.show_port(port_id)['port']
Matt Riedemann17940732015-03-13 14:18:19 +0000713 self.assertEqual(self.network['id'], port['network_id'])
714 self.assertEqual('', port['device_id'])
715 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300716
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400717 # Boot another server with the same port to make sure nothing was
718 # left around that could cause issues.
zhufl24208c22016-10-25 15:23:48 +0800719 server = self._create_server(self.network, port['id'])
jeremy.zhang5870ff12017-05-25 11:24:23 +0800720 port_list = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100721 device_id=server['id'], network_id=self.network['id'])['ports']
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400722 self.assertEqual(1, len(port_list),
723 'There should only be one port created for '
724 'server %s.' % server['id'])
725 self.assertEqual(port['id'], port_list[0]['id'])
726
Andrea Frittolicd368412017-08-14 21:37:56 +0100727 @utils.requires_ext(service='network', extension='l3_agent_scheduler')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800728 @decorators.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200729 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100730 @utils.services('compute', 'network')
Yair Fried564d89d2015-08-06 17:02:12 +0300731 def test_router_rescheduling(self):
732 """Tests that router can be removed from agent and add to a new agent.
733
734 1. Verify connectivity
735 2. Remove router from all l3-agents
736 3. Verify connectivity is down
737 4. Assign router to new l3-agent (or old one if no new agent is
738 available)
739 5. Verify connectivity
740 """
741
742 # TODO(yfried): refactor this test to be used for other agents (dhcp)
743 # as well
744
jeremy.zhang5870ff12017-05-25 11:24:23 +0800745 list_hosts = (self.os_admin.routers_client.
Yair Fried564d89d2015-08-06 17:02:12 +0300746 list_l3_agents_hosting_router)
jeremy.zhang5870ff12017-05-25 11:24:23 +0800747 schedule_router = (self.os_admin.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000748 create_router_on_l3_agent)
jeremy.zhang5870ff12017-05-25 11:24:23 +0800749 unschedule_router = (self.os_admin.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000750 delete_router_from_l3_agent)
Yair Fried564d89d2015-08-06 17:02:12 +0300751
Jordan Pittier64e6b442017-02-20 19:29:02 +0100752 agent_list_alive = set(
753 a["id"] for a in
jeremy.zhang5870ff12017-05-25 11:24:23 +0800754 self.os_admin.network_agents_client.list_agents(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100755 agent_type="L3 agent")['agents'] if a["alive"] is True
756 )
Yair Fried564d89d2015-08-06 17:02:12 +0300757 self._setup_network_and_servers()
Kevin Benton3b63aa12015-08-27 17:15:44 -0700758
759 # NOTE(kevinbenton): we have to use the admin credentials to check
Sean Dagueed6e5862016-04-04 10:49:13 -0400760 # for the distributed flag because self.router only has a project view.
jeremy.zhang5870ff12017-05-25 11:24:23 +0800761 admin = self.os_admin.routers_client.show_router(
Steve Heyman33735f22016-05-24 09:28:08 -0500762 self.router['id'])
Kevin Benton3b63aa12015-08-27 17:15:44 -0700763 if admin['router'].get('distributed', False):
764 msg = "Rescheduling test does not apply to distributed routers."
765 raise self.skipException(msg)
766
Yair Fried564d89d2015-08-06 17:02:12 +0300767 self.check_public_network_connectivity(should_connect=True)
768
769 # remove resource from agents
770 hosting_agents = set(a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500771 list_hosts(self.router['id'])['agents'])
shipeiqic9a4a102016-04-20 17:39:03 +0800772 no_migration = agent_list_alive == hosting_agents
Yair Fried564d89d2015-08-06 17:02:12 +0300773 LOG.info("Router will be assigned to {mig} hosting agent".
774 format(mig="the same" if no_migration else "a new"))
775
776 for hosting_agent in hosting_agents:
Steve Heyman33735f22016-05-24 09:28:08 -0500777 unschedule_router(hosting_agent, self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300778 self.assertNotIn(hosting_agent,
779 [a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500780 list_hosts(self.router['id'])['agents']],
Yair Fried564d89d2015-08-06 17:02:12 +0300781 'unscheduling router failed')
782
783 # verify resource is un-functional
784 self.check_public_network_connectivity(
785 should_connect=False,
786 msg='after router unscheduling',
Yair Fried564d89d2015-08-06 17:02:12 +0300787 )
788
789 # schedule resource to new agent
790 target_agent = list(hosting_agents if no_migration else
shipeiqic9a4a102016-04-20 17:39:03 +0800791 agent_list_alive - hosting_agents)[0]
Yair Fried564d89d2015-08-06 17:02:12 +0300792 schedule_router(target_agent,
piyush110786bc0faa62015-12-03 14:54:48 +0530793 router_id=self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300794 self.assertEqual(
795 target_agent,
Steve Heyman33735f22016-05-24 09:28:08 -0500796 list_hosts(self.router['id'])['agents'][0]['id'],
Yair Fried564d89d2015-08-06 17:02:12 +0300797 "Router failed to reschedule. Hosting agent doesn't match "
798 "target agent")
799
800 # verify resource is functional
801 self.check_public_network_connectivity(
802 should_connect=True,
803 msg='After router rescheduling')
Yair Friedbc46f592015-11-18 16:29:34 +0200804
Andrea Frittolicd368412017-08-14 21:37:56 +0100805 @utils.requires_ext(service='network', extension='port-security')
Evgeny Antyshevaaf3fc92016-02-15 11:49:22 +0000806 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
807 'NIC hotplug not available')
Ken'ichi Ohmichic85a9512017-01-27 18:34:24 -0800808 @decorators.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
Jordan Pittier3b46d272017-04-12 16:17:28 +0200809 @decorators.attr(type='slow')
Andrea Frittolicd368412017-08-14 21:37:56 +0100810 @utils.services('compute', 'network')
Yair Friedbc46f592015-11-18 16:29:34 +0200811 def test_port_security_macspoofing_port(self):
812 """Tests port_security extension enforces mac spoofing
813
Eran Kuris7969e802015-12-15 13:43:46 +0200814 Neutron security groups always apply anti-spoof rules on the VMs. This
815 allows traffic to originate and terminate at the VM as expected, but
816 prevents traffic to pass through the VM. Anti-spoof rules are not
817 required in cases where the VM routes traffic through it.
818
819 The test steps are :
820 1. Create a new network.
821 2. Connect (hotplug) the VM to a new network.
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900822 3. Check the VM can ping a server on the new network ("peer")
Eran Kuris7969e802015-12-15 13:43:46 +0200823 4. Spoof the mac address of the new VM interface.
824 5. Check the Security Group enforces mac spoofing and blocks pings via
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900825 spoofed interface (VM cannot ping the peer).
Eran Kuris7969e802015-12-15 13:43:46 +0200826 6. Disable port-security of the spoofed port- set the flag to false.
827 7. Retest 3rd step and check that the Security Group allows pings via
828 the spoofed interface.
Yair Friedbc46f592015-11-18 16:29:34 +0200829 """
Eran Kuris7969e802015-12-15 13:43:46 +0200830
Yair Friedbc46f592015-11-18 16:29:34 +0200831 spoof_mac = "00:00:00:00:00:01"
832
833 # Create server
834 self._setup_network_and_servers()
YAMAMOTO Takashic368dde2015-11-30 23:04:14 +0900835 self.check_public_network_connectivity(should_connect=True)
Yair Friedbc46f592015-11-18 16:29:34 +0200836 self._create_new_network()
837 self._hotplug_server()
838 fip, server = self.floating_ip_tuple
jeremy.zhang5870ff12017-05-25 11:24:23 +0800839 new_ports = self.os_admin.ports_client.list_ports(
Jordan Pittier64e6b442017-02-20 19:29:02 +0100840 device_id=server["id"], network_id=self.new_net["id"])['ports']
Yair Friedbc46f592015-11-18 16:29:34 +0200841 spoof_port = new_ports[0]
842 private_key = self._get_server_key(server)
Steve Heyman33735f22016-05-24 09:28:08 -0500843 ssh_client = self.get_remote_client(fip['floating_ip_address'],
zhuflf52c7592017-05-25 13:55:24 +0800844 private_key=private_key,
845 server=server)
Evgeny Antyshev9b77ae52016-02-16 09:48:57 +0000846 spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
zhufl24208c22016-10-25 15:23:48 +0800847 peer = self._create_server(self.new_net)
Steve Heyman33735f22016-05-24 09:28:08 -0500848 peer_address = peer['addresses'][self.new_net['name']][0]['addr']
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900849 self.check_remote_connectivity(ssh_client, dest=peer_address,
850 nic=spoof_nic, should_succeed=True)
Ken'ichi Ohmichi5129c622017-03-22 11:18:42 -0700851 # Set a mac address by making nic down temporary
852 cmd = ("sudo ip link set {nic} down;"
853 "sudo ip link set dev {nic} address {mac};"
854 "sudo ip link set {nic} up").format(nic=spoof_nic,
855 mac=spoof_mac)
856 ssh_client.exec_command(cmd)
857
Yair Friedbc46f592015-11-18 16:29:34 +0200858 new_mac = ssh_client.get_mac_address(nic=spoof_nic)
859 self.assertEqual(spoof_mac, new_mac)
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900860 self.check_remote_connectivity(ssh_client, dest=peer_address,
861 nic=spoof_nic, should_succeed=False)
Yair Friedbc46f592015-11-18 16:29:34 +0200862 self.ports_client.update_port(spoof_port["id"],
863 port_security_enabled=False,
864 security_groups=[])
YAMAMOTO Takashi4c3ebb02017-01-25 16:04:30 +0900865 self.check_remote_connectivity(ssh_client, dest=peer_address,
866 nic=spoof_nic, should_succeed=True)