blob: a295b6adb7af83e28c0715b5ebd0ff1423ef8e52 [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
Fei Long Wangd39431f2015-05-14 11:30:48 +120022from tempest.common.utils import data_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
Attila Fazekasa8bb3942014-08-19 09:06:30 +020025from tempest import exceptions
Jordan Pittier9e227c52016-02-09 14:35:18 +010026from tempest.lib.common.utils import test_utils
Sean Dague17487fb2016-08-08 10:44:20 -040027from tempest.lib import decorators
Sean Dague6dbc6da2013-05-08 17:49:46 -040028from tempest.scenario import manager
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090029from tempest import test
Maru Newby81f07a02012-09-05 20:21:19 -070030
Sean Dague86bd8422013-12-20 09:56:44 -050031CONF = config.CONF
Matthew Treinish2b59f842013-09-09 20:32:51 +000032LOG = logging.getLogger(__name__)
33
Yair Fried2d2f3fe2014-02-24 16:19:20 +020034Floating_IP_tuple = collections.namedtuple('Floating_IP_tuple',
35 ['floating_ip', 'server'])
36
Maru Newby81f07a02012-09-05 20:21:19 -070037
Andrea Frittoli4971fc82014-09-25 10:22:20 +010038class TestNetworkBasicOps(manager.NetworkScenarioTest):
Maru Newby81f07a02012-09-05 20:21:19 -070039
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000040 """The test suite of network basic operations
41
Maru Newby81f07a02012-09-05 20:21:19 -070042 This smoke test suite assumes that Nova has been configured to
Mark McClainf2982e82013-07-06 17:48:03 -040043 boot VM's with Neutron-managed networking, and attempts to
Maru Newby81f07a02012-09-05 20:21:19 -070044 verify network connectivity as follows:
45
Maru Newby81f07a02012-09-05 20:21:19 -070046 There are presumed to be two types of networks: tenant and
47 public. A tenant network may or may not be reachable from the
48 Tempest host. A public network is assumed to be reachable from
49 the Tempest host, and it should be possible to associate a public
50 ('floating') IP address with a tenant ('fixed') IP address to
Chang Bo Guocc1623c2013-09-13 20:11:27 -070051 facilitate external connectivity to a potentially unroutable
Maru Newby81f07a02012-09-05 20:21:19 -070052 tenant IP address.
53
54 This test suite can be configured to test network connectivity to
55 a VM via a tenant network, a public network, or both. If both
56 networking types are to be evaluated, tests that need to be
57 executed remotely on the VM (via ssh) will only be run against
58 one of the networks (to minimize test execution time).
59
60 Determine which types of networks to test as follows:
61
62 * Configure tenant network checks (via the
Sean Dagueed6e5862016-04-04 10:49:13 -040063 'project_networks_reachable' key) if the Tempest host should
Maru Newby81f07a02012-09-05 20:21:19 -070064 have direct connectivity to tenant networks. This is likely to
65 be the case if Tempest is running on the same host as a
66 single-node devstack installation with IP namespaces disabled.
67
68 * Configure checks for a public network if a public network has
69 been configured prior to the test suite being run and if the
70 Tempest host should have connectivity to that public network.
71 Checking connectivity for a public network requires that a
72 value be provided for 'public_network_id'. A value can
73 optionally be provided for 'public_router_id' if tenants will
74 use a shared router to access a public network (as is likely to
75 be the case when IP namespaces are not enabled). If a value is
76 not provided for 'public_router_id', a router will be created
77 for each tenant and use the network identified by
78 'public_network_id' as its gateway.
79
80 """
81
82 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000083 def skip_checks(cls):
84 super(TestNetworkBasicOps, cls).skip_checks()
Sean Dagueed6e5862016-04-04 10:49:13 -040085 if not (CONF.network.project_networks_reachable
Matthew Treinish6c072292014-01-29 19:15:52 +000086 or CONF.network.public_network_id):
Sean Dagueed6e5862016-04-04 10:49:13 -040087 msg = ('Either project_networks_reachable must be "true", or '
Maru Newby81f07a02012-09-05 20:21:19 -070088 'public_network_id must be defined.')
ivan-zhu1feeb382013-01-24 10:14:39 +080089 raise cls.skipException(msg)
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090090 for ext in ['router', 'security-group']:
91 if not test.is_extension_enabled(ext, 'network'):
92 msg = "%s extension not enabled." % ext
93 raise cls.skipException(msg)
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000094
95 @classmethod
96 def setup_credentials(cls):
Masayuki Igawa60ea6c52014-10-15 17:32:14 +090097 # Create no network resources for these tests.
98 cls.set_network_resources()
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000099 super(TestNetworkBasicOps, cls).setup_credentials()
Maru Newby81f07a02012-09-05 20:21:19 -0700100
Yair Frieded8392f2014-01-15 17:21:35 +0200101 def setUp(self):
102 super(TestNetworkBasicOps, self).setUp()
Yair Fried1fc32a12014-08-04 09:11:30 +0300103 self.keypairs = {}
104 self.servers = []
David Shrewsbury9bac3662014-08-07 15:07:01 -0400105
Yair Fried413bf2d2014-11-19 17:07:11 +0200106 def _setup_network_and_servers(self, **kwargs):
Matt Riedemann17940732015-03-13 14:18:19 +0000107 boot_with_port = kwargs.pop('boot_with_port', False)
David Shrewsbury9bac3662014-08-07 15:07:01 -0400108 self.security_group = \
109 self._create_security_group(tenant_id=self.tenant_id)
Yair Fried413bf2d2014-11-19 17:07:11 +0200110 self.network, self.subnet, self.router = self.create_networks(**kwargs)
David Shrewsbury9bac3662014-08-07 15:07:01 -0400111 self.check_networks()
112
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000113 self.ports = []
Matt Riedemann17940732015-03-13 14:18:19 +0000114 self.port_id = None
Jordan Pittierf72a1dc2015-08-04 12:50:33 +0000115 if boot_with_port:
Matt Riedemann17940732015-03-13 14:18:19 +0000116 # create a port on the network and boot with that
Steve Heyman33735f22016-05-24 09:28:08 -0500117 self.port_id = self._create_port(self.network['id'])['id']
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000118 self.ports.append({'port': self.port_id})
Matt Riedemann17940732015-03-13 14:18:19 +0000119
Yair Frieded8392f2014-01-15 17:21:35 +0200120 name = data_utils.rand_name('server-smoke')
Matt Riedemann17940732015-03-13 14:18:19 +0000121 server = self._create_server(name, self.network, self.port_id)
Yair Frieded8392f2014-01-15 17:21:35 +0200122 self._check_tenant_network_connectivity()
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200123
Yair Friedae0e73d2014-11-24 11:56:26 +0200124 floating_ip = self.create_floating_ip(server)
125 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Maru Newby81f07a02012-09-05 20:21:19 -0700126
Yair Frieded8392f2014-01-15 17:21:35 +0200127 def check_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000128 """Checks that we see the newly created network/subnet/router
129
130 via checking the result of list_[networks,routers,subnets]
Yair Frieded8392f2014-01-15 17:21:35 +0200131 """
132
Gavin Brebner851c3502013-01-18 13:14:10 +0000133 seen_nets = self._list_networks()
134 seen_names = [n['name'] for n in seen_nets]
135 seen_ids = [n['id'] for n in seen_nets]
Steve Heyman33735f22016-05-24 09:28:08 -0500136 self.assertIn(self.network['name'], seen_names)
137 self.assertIn(self.network['id'], seen_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200138
David Shrewsbury9bac3662014-08-07 15:07:01 -0400139 if self.subnet:
140 seen_subnets = self._list_subnets()
141 seen_net_ids = [n['network_id'] for n in seen_subnets]
142 seen_subnet_ids = [n['id'] for n in seen_subnets]
Steve Heyman33735f22016-05-24 09:28:08 -0500143 self.assertIn(self.network['id'], seen_net_ids)
144 self.assertIn(self.subnet['id'], seen_subnet_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200145
David Shrewsbury9bac3662014-08-07 15:07:01 -0400146 if self.router:
147 seen_routers = self._list_routers()
148 seen_router_ids = [n['id'] for n in seen_routers]
149 seen_router_names = [n['name'] for n in seen_routers]
Steve Heyman33735f22016-05-24 09:28:08 -0500150 self.assertIn(self.router['name'],
David Shrewsbury9bac3662014-08-07 15:07:01 -0400151 seen_router_names)
Steve Heyman33735f22016-05-24 09:28:08 -0500152 self.assertIn(self.router['id'],
David Shrewsbury9bac3662014-08-07 15:07:01 -0400153 seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000154
Matt Riedemann17940732015-03-13 14:18:19 +0000155 def _create_server(self, name, network, port_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +0300156 keypair = self.create_keypair()
157 self.keypairs[keypair['name']] = keypair
Ken'ichi Ohmichi1b3461e2014-12-02 03:41:07 +0000158 security_groups = [{'name': self.security_group['name']}]
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(
164 name=name,
165 networks=[network],
166 key_name=keypair['name'],
167 security_groups=security_groups,
168 wait_until='ACTIVE')
Yair Fried1fc32a12014-08-04 09:11:30 +0300169 self.servers.append(server)
170 return server
171
172 def _get_server_key(self, server):
173 return self.keypairs[server['key_name']]['private_key']
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700174
Matthew Treinish2b59f842013-09-09 20:32:51 +0000175 def _check_tenant_network_connectivity(self):
lanoux283273b2015-12-04 03:01:54 -0800176 ssh_login = CONF.validation.image_ssh_user
Yair Fried1fc32a12014-08-04 09:11:30 +0300177 for server in self.servers:
Matt Riedemann2d005be2014-05-27 10:52:35 -0700178 # call the common method in the parent class
179 super(TestNetworkBasicOps, self).\
180 _check_tenant_network_connectivity(
Yair Fried1fc32a12014-08-04 09:11:30 +0300181 server, ssh_login, self._get_server_key(server),
182 servers_for_debug=self.servers)
Brent Eaglesc26d4522013-12-02 13:28:49 -0500183
Alok Maurya6384bbb2014-07-13 06:44:29 -0700184 def check_public_network_connectivity(
185 self, should_connect=True, msg=None,
186 should_check_floating_ip_status=True):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000187 """Verifies connectivty to a VM via public network and floating IP
188
Yair Fried45f92952014-06-26 05:19:19 +0300189 and verifies floating IP has resource status is correct.
190
Yair Fried45f92952014-06-26 05:19:19 +0300191 :param should_connect: bool. determines if connectivity check is
192 negative or positive.
193 :param msg: Failure message to add to Error message. Should describe
194 the place in the test scenario where the method was called,
195 to indicate the context of the failure
Alok Maurya6384bbb2014-07-13 06:44:29 -0700196 :param should_check_floating_ip_status: bool. should status of
197 floating_ip be checked or not
Yair Fried45f92952014-06-26 05:19:19 +0300198 """
lanoux283273b2015-12-04 03:01:54 -0800199 ssh_login = CONF.validation.image_ssh_user
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200200 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500201 ip_address = floating_ip['floating_ip_address']
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200202 private_key = None
Yair Fried45f92952014-06-26 05:19:19 +0300203 floatingip_status = 'DOWN'
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200204 if should_connect:
Yair Fried1fc32a12014-08-04 09:11:30 +0300205 private_key = self._get_server_key(server)
Yair Fried45f92952014-06-26 05:19:19 +0300206 floatingip_status = 'ACTIVE'
Swaminathan Vasudevandc8bcdb2015-02-28 12:47:21 -0800207 # Check FloatingIP Status before initiating a connection
208 if should_check_floating_ip_status:
209 self.check_floating_ip_status(floating_ip, floatingip_status)
Matt Riedemann343305f2014-05-27 09:55:03 -0700210 # call the common method in the parent class
Yair Friedae0e73d2014-11-24 11:56:26 +0200211 super(TestNetworkBasicOps, self).check_public_network_connectivity(
Matt Riedemann343305f2014-05-27 09:55:03 -0700212 ip_address, ssh_login, private_key, should_connect, msg,
Yair Fried1fc32a12014-08-04 09:11:30 +0300213 self.servers)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000214
Yair Fried9a551c42013-12-15 14:59:34 +0200215 def _disassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200216 floating_ip, server = self.floating_ip_tuple
217 self._disassociate_floating_ip(floating_ip)
218 self.floating_ip_tuple = Floating_IP_tuple(
219 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
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000223 name = data_utils.rand_name('new_server-smoke')
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200224 # create a new server for the floating ip
Yair Fried1fc32a12014-08-04 09:11:30 +0300225 server = self._create_server(name, self.network)
226 self._associate_floating_ip(floating_ip, server)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200227 self.floating_ip_tuple = Floating_IP_tuple(
Yair Fried1fc32a12014-08-04 09:11:30 +0300228 floating_ip, server)
Yair Fried05db2522013-11-18 11:02:10 +0200229
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300230 def _create_new_network(self, create_gateway=False):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300231 self.new_net = self._create_network(tenant_id=self.tenant_id)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300232 if create_gateway:
233 self.new_subnet = self._create_subnet(
234 network=self.new_net)
235 else:
236 self.new_subnet = self._create_subnet(
237 network=self.new_net,
238 gateway_ip=None)
Yair Fried3097dc12014-01-26 08:46:43 +0200239
240 def _hotplug_server(self):
241 old_floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500242 ip_address = old_floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300243 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100244 ssh_client = self.get_remote_client(
245 ip_address, private_key=private_key)
Yair Fried3097dc12014-01-26 08:46:43 +0200246 old_nic_list = self._get_server_nics(ssh_client)
247 # get a port from a list of one item
Yair Fried1fc32a12014-08-04 09:11:30 +0300248 port_list = self._list_ports(device_id=server['id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200249 self.assertEqual(1, len(port_list))
250 old_port = port_list[0]
David Kranzb2b0c182015-02-18 13:28:19 -0500251 interface = self.interface_client.create_interface(
Ken'ichi Ohmichi9509b962015-07-07 05:30:15 +0000252 server_id=server['id'],
Steve Heyman33735f22016-05-24 09:28:08 -0500253 net_id=self.new_net['id'])['interfaceAttachment']
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -0700254 self.addCleanup(self.ports_client.wait_for_resource_deletion,
255 interface['port_id'])
Jordan Pittier9e227c52016-02-09 14:35:18 +0100256 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Yair Fried1fc32a12014-08-04 09:11:30 +0300257 self.interface_client.delete_interface,
258 server['id'], interface['port_id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200259
260 def check_ports():
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200261 self.new_port_list = [port for port in
Yair Fried1fc32a12014-08-04 09:11:30 +0300262 self._list_ports(device_id=server['id'])
armando-migliaccio3820a062015-02-12 19:31:54 -0800263 if port['id'] != old_port['id']]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200264 return len(self.new_port_list) == 1
Yair Fried3097dc12014-01-26 08:46:43 +0200265
Jordan Pittier35a63752016-08-30 13:09:12 +0200266 if not test_utils.call_until_true(
267 check_ports, CONF.network.build_timeout,
268 CONF.network.build_interval):
Matt Riedemann892094e2015-02-05 07:24:02 -0800269 raise exceptions.TimeoutException(
270 "No new port attached to the server in time (%s sec)! "
271 "Old port: %s. Number of new ports: %d" % (
272 CONF.network.build_timeout, old_port,
273 len(self.new_port_list)))
Steve Heyman33735f22016-05-24 09:28:08 -0500274 new_port = self.new_port_list[0]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200275
276 def check_new_nic():
277 new_nic_list = self._get_server_nics(ssh_client)
278 self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
279 return len(self.diff_list) == 1
280
Jordan Pittier35a63752016-08-30 13:09:12 +0200281 if not test_utils.call_until_true(
282 check_new_nic, CONF.network.build_timeout,
283 CONF.network.build_interval):
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200284 raise exceptions.TimeoutException("Interface not visible on the "
285 "guest after %s sec"
286 % CONF.network.build_timeout)
287
288 num, new_nic = self.diff_list[0]
Yair Fried3097dc12014-01-26 08:46:43 +0200289 ssh_client.assign_static_ip(nic=new_nic,
Steve Heyman33735f22016-05-24 09:28:08 -0500290 addr=new_port['fixed_ips'][0][
291 'ip_address'])
Yair Friedbc46f592015-11-18 16:29:34 +0200292 ssh_client.set_nic_state(nic=new_nic)
Yair Fried3097dc12014-01-26 08:46:43 +0200293
294 def _get_server_nics(self, ssh_client):
295 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
296 ipatxt = ssh_client.get_ip_list()
297 return reg.findall(ipatxt)
298
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300299 def _check_network_internal_connectivity(self, network,
300 should_connect=True):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000301 """via ssh check VM internal connectivity:
302
Yair Fried06552292013-11-11 12:10:09 +0200303 - ping internal gateway and DHCP port, implying in-tenant connectivity
304 pinging both, because L3 and DHCP agents might be on different nodes
Yair Fried3097dc12014-01-26 08:46:43 +0200305 """
306 floating_ip, server = self.floating_ip_tuple
307 # get internal ports' ips:
308 # get all network ports in the new network
309 internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
Yair Fried1fc32a12014-08-04 09:11:30 +0300310 self._list_ports(tenant_id=server['tenant_id'],
Steve Heyman33735f22016-05-24 09:28:08 -0500311 network_id=network['id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200312 if p['device_owner'].startswith('network'))
313
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300314 self._check_server_connectivity(floating_ip,
315 internal_ips,
316 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200317
318 def _check_network_external_connectivity(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000319 """ping default gateway to imply external connectivity"""
Yair Fried06552292013-11-11 12:10:09 +0200320 if not CONF.network.public_network_id:
321 msg = 'public network not defined.'
322 LOG.info(msg)
323 return
324
Andrew Boik4a3daf12015-03-27 01:59:31 -0400325 # We ping the external IP from the instance using its floating IP
326 # which is always IPv4, so we must only test connectivity to
327 # external IPv4 IPs if the external network is dualstack.
328 v4_subnets = [s for s in self._list_subnets(
329 network_id=CONF.network.public_network_id) if s['ip_version'] == 4]
330 self.assertEqual(1, len(v4_subnets),
331 "Found %d IPv4 subnets" % len(v4_subnets))
Yair Fried06552292013-11-11 12:10:09 +0200332
Andrew Boik4a3daf12015-03-27 01:59:31 -0400333 external_ips = [v4_subnets[0]['gateway_ip']]
Yair Fried06552292013-11-11 12:10:09 +0200334 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
335 external_ips)
336
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300337 def _check_server_connectivity(self, floating_ip, address_list,
338 should_connect=True):
Steve Heyman33735f22016-05-24 09:28:08 -0500339 ip_address = floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300340 private_key = self._get_server_key(self.floating_ip_tuple.server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100341 ssh_source = self.get_remote_client(
342 ip_address, private_key=private_key)
Yair Fried3097dc12014-01-26 08:46:43 +0200343
Yair Fried06552292013-11-11 12:10:09 +0200344 for remote_ip in address_list:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300345 if should_connect:
PranaliDeoreb68b9472015-08-11 00:14:50 -0700346 msg = ("Timed out waiting for %s to become "
347 "reachable") % remote_ip
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300348 else:
349 msg = "ip address %s is reachable" % remote_ip
Yair Fried3097dc12014-01-26 08:46:43 +0200350 try:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300351 self.assertTrue(self._check_remote_connectivity
352 (ssh_source, remote_ip, should_connect),
353 msg)
Yair Fried3097dc12014-01-26 08:46:43 +0200354 except Exception:
355 LOG.exception("Unable to access {dest} via ssh to "
356 "floating-ip {src}".format(dest=remote_ip,
357 src=floating_ip))
Yair Fried3097dc12014-01-26 08:46:43 +0200358 raise
359
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900360 @test.attr(type='smoke')
Chris Hoge7579c1a2015-02-26 14:12:15 -0800361 @test.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900362 @test.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000363 def test_network_basic_ops(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000364 """Basic network operation test
365
Yair Fried3097dc12014-01-26 08:46:43 +0200366 For a freshly-booted VM with an IP address ("port") on a given
367 network:
368
369 - the Tempest host can ping the IP address. This implies, but
370 does not guarantee (see the ssh check that follows), that the
371 VM has been assigned the correct IP address and has
372 connectivity to the Tempest host.
373
374 - the Tempest host can perform key-based authentication to an
375 ssh server hosted at the IP address. This check guarantees
376 that the IP address is associated with the target VM.
377
Yair Fried3097dc12014-01-26 08:46:43 +0200378 - the Tempest host can ssh into the VM via the IP address and
379 successfully execute the following:
380
381 - ping an external IP address, implying external connectivity.
382
383 - ping an external hostname, implying that dns is correctly
384 configured.
385
386 - ping an internal IP address, implying connectivity to another
387 VM on the same network.
388
Yair Fried06552292013-11-11 12:10:09 +0200389 - detach the floating-ip from the VM and verify that it becomes
390 unreachable
391
392 - associate detached floating ip to a new VM and verify connectivity.
393 VMs are created with unique keypair so connectivity also asserts that
394 floating IP is associated with the new VM instead of the old one
395
Yair Fried45f92952014-06-26 05:19:19 +0300396 Verifies that floating IP status is updated correctly after each change
397
Yair Fried06552292013-11-11 12:10:09 +0200398
Yair Fried3097dc12014-01-26 08:46:43 +0200399 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400400 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200401 self.check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200402 self._check_network_internal_connectivity(network=self.network)
403 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200404 self._disassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200405 self.check_public_network_connectivity(should_connect=False,
406 msg="after disassociate "
407 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200408 self._reassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200409 self.check_public_network_connectivity(should_connect=True,
410 msg="after re-associate "
411 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200412
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300413 @test.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
Adam Gandelman36b71fc2015-03-12 12:24:08 -0700414 @testtools.skipIf(CONF.baremetal.driver_enabled,
415 'Baremetal relies on a shared physical network.')
Sean Dague17487fb2016-08-08 10:44:20 -0400416 @decorators.skip_because(bug="1610994")
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300417 @test.services('compute', 'network')
418 def test_connectivity_between_vms_on_different_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000419 """Test connectivity between VMs on different networks
420
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300421 For a freshly-booted VM with an IP address ("port") on a given
422 network:
423
424 - the Tempest host can ping the IP address.
425
426 - the Tempest host can ssh into the VM via the IP address and
427 successfully execute the following:
428
429 - ping an external IP address, implying external connectivity.
430
431 - ping an external hostname, implying that dns is correctly
432 configured.
433
434 - ping an internal IP address, implying connectivity to another
435 VM on the same network.
436
437 - Create another network on the same tenant with subnet, create
438 an VM on the new network.
439
440 - Ping the new VM from previous VM failed since the new network
441 was not attached to router yet.
442
443 - Attach the new network to the router, Ping the new VM from
444 previous VM succeed.
445
446 """
447 self._setup_network_and_servers()
448 self.check_public_network_connectivity(should_connect=True)
449 self._check_network_internal_connectivity(network=self.network)
450 self._check_network_external_connectivity()
451 self._create_new_network(create_gateway=True)
452 name = data_utils.rand_name('server-smoke')
453 self._create_server(name, self.new_net)
454 self._check_network_internal_connectivity(network=self.new_net,
455 should_connect=False)
Steve Heyman33735f22016-05-24 09:28:08 -0500456 router_id = self.router['id']
457 self.routers_client.add_router_interface(
458 router_id, subnet_id=self.new_subnet['id'])
459
460 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
461 self.routers_client.remove_router_interface,
462 router_id, subnet_id=self.new_subnet['id'])
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300463 self._check_network_internal_connectivity(network=self.new_net,
464 should_connect=True)
465
Chris Hoge7579c1a2015-02-26 14:12:15 -0800466 @test.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400467 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
468 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200469 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
470 'NIC hotplug not supported for '
471 'vnic_type direct or macvtap')
Yair Fried3097dc12014-01-26 08:46:43 +0200472 @test.services('compute', 'network')
473 def test_hotplug_nic(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000474 """Test hotplug network interface
475
Arief3f6e812016-09-28 16:48:20 +0300476 1. Create a network and a VM.
477 2. Check connectivity to the VM via a public network.
478 3. Create a new network, with no gateway.
479 4. Bring up a new interface
480 5. check the VM reach the new network
Yair Fried3097dc12014-01-26 08:46:43 +0200481
482 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400483 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200484 self.check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200485 self._create_new_network()
486 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200487 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700488
Chris Hoge7579c1a2015-02-26 14:12:15 -0800489 @test.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Adam Gandelmancf611212014-12-09 14:13:28 -0800490 @testtools.skipIf(CONF.baremetal.driver_enabled,
491 'Router state cannot be altered on a shared baremetal '
492 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700493 @test.services('compute', 'network')
494 def test_update_router_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000495 """Test to update admin state up of router
496
Alok Maurya6384bbb2014-07-13 06:44:29 -0700497 1. Check public connectivity before updating
498 admin_state_up attribute of router to False
499 2. Check public connectivity after updating
500 admin_state_up attribute of router to False
501 3. Check public connectivity after updating
502 admin_state_up attribute of router to True
503 """
504 self._setup_network_and_servers()
505 self.check_public_network_connectivity(
506 should_connect=True, msg="before updating "
507 "admin_state_up of router to False")
508 self._update_router_admin_state(self.router, False)
509 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
510 # once bug 1396310 is fixed
511
512 self.check_public_network_connectivity(
513 should_connect=False, msg="after updating "
514 "admin_state_up of router to False",
515 should_check_floating_ip_status=False)
516 self._update_router_admin_state(self.router, True)
517 self.check_public_network_connectivity(
518 should_connect=True, msg="after updating "
519 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200520
Chris Hoge7579c1a2015-02-26 14:12:15 -0800521 @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Adam Gandelman40371682015-03-03 11:27:03 -0800522 @testtools.skipIf(CONF.baremetal.driver_enabled,
523 'network isolation not available for baremetal nodes')
Yair Fried413bf2d2014-11-19 17:07:11 +0200524 @testtools.skipUnless(CONF.scenario.dhcp_client,
525 "DHCP client is not available.")
Yair Fried413bf2d2014-11-19 17:07:11 +0200526 @test.services('compute', 'network')
527 def test_subnet_details(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000528 """Tests that subnet's extra configuration details are affecting VMs.
529
530 This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200531
532 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
533 update in subnet requires server to actively renew its DHCP lease.
534
535 1. Configure subnet with dns nameserver
536 2. retrieve the VM's configured dns and verify it matches the one
537 configured for the subnet.
538 3. update subnet's dns
539 4. retrieve the VM's configured dns and verify it matches the new one
540 configured for the subnet.
541
542 TODO(yfried): add host_routes
543
544 any resolution check would be testing either:
545 * l3 forwarding (tested in test_network_basic_ops)
546 * Name resolution of an external DNS nameserver - out of scope for
547 Tempest
548 """
549 # this test check only updates (no actual resolution) so using
550 # arbitrary ip addresses as nameservers, instead of parsing CONF
551 initial_dns_server = '1.2.3.4'
552 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000553
554 # renewal should be immediate.
555 # Timeouts are suggested by salvatore-orlando in
556 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
557 renew_delay = CONF.network.build_interval
558 renew_timeout = CONF.network.build_timeout
559
Yair Fried413bf2d2014-11-19 17:07:11 +0200560 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
561 self.check_public_network_connectivity(should_connect=True)
562
563 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500564 ip_address = floating_ip['floating_ip_address']
Yair Fried413bf2d2014-11-19 17:07:11 +0200565 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100566 ssh_client = self.get_remote_client(
567 ip_address, private_key=private_key)
Yair Fried413bf2d2014-11-19 17:07:11 +0200568
armando-migliaccio424aa412015-02-22 17:55:17 -0800569 dns_servers = [initial_dns_server]
570 servers = ssh_client.get_dns_servers()
571 self.assertEqual(set(dns_servers), set(servers),
572 'Looking for servers: {trgt_serv}. '
573 'Retrieved DNS nameservers: {act_serv} '
574 'From host: {host}.'
575 .format(host=ssh_client.ssh_client.host,
576 act_serv=servers,
577 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200578
Steve Heyman33735f22016-05-24 09:28:08 -0500579 self.subnet = self.subnets_client.update_subnet(
580 self.subnet['id'], dns_nameservers=[alt_dns_server])['subnet']
581
Yair Fried413bf2d2014-11-19 17:07:11 +0200582 # asserts that Neutron DB has updated the nameservers
Steve Heyman33735f22016-05-24 09:28:08 -0500583 self.assertEqual([alt_dns_server], self.subnet['dns_nameservers'],
Yair Fried413bf2d2014-11-19 17:07:11 +0200584 "Failed to update subnet's nameservers")
585
Yair Friedbb0ea392015-01-19 07:26:08 +0000586 def check_new_dns_server():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000587 # NOTE: Server needs to renew its dhcp lease in order to get new
588 # definitions from subnet
589 # NOTE(amuller): we are renewing the lease as part of the retry
590 # because Neutron updates dnsmasq asynchronously after the
591 # subnet-update API call returns.
Yair Friedbb0ea392015-01-19 07:26:08 +0000592 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
armando-migliaccio424aa412015-02-22 17:55:17 -0800593 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000594 LOG.debug("Failed to update DNS nameservers")
595 return False
596 return True
597
Jordan Pittier35a63752016-08-30 13:09:12 +0200598 self.assertTrue(test_utils.call_until_true(check_new_dns_server,
599 renew_timeout,
600 renew_delay),
Yair Friedbb0ea392015-01-19 07:26:08 +0000601 msg="DHCP renewal failed to fetch "
602 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800603
Chris Hoge7579c1a2015-02-26 14:12:15 -0800604 @test.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Adam Gandelman0a7948e2015-02-16 15:13:50 -0800605 @testtools.skipIf(CONF.baremetal.driver_enabled,
606 'admin_state of instance ports cannot be altered '
607 'for baremetal nodes')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300608 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
609 "Changing a port's admin state is not supported "
610 "by the test environment")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800611 @test.services('compute', 'network')
612 def test_update_instance_port_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000613 """Test to update admin_state_up attribute of instance port
614
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800615 1. Check public connectivity before updating
616 admin_state_up attribute of instance port to False
617 2. Check public connectivity after updating
618 admin_state_up attribute of instance port to False
619 3. Check public connectivity after updating
620 admin_state_up attribute of instance port to True
621 """
622 self._setup_network_and_servers()
623 floating_ip, server = self.floating_ip_tuple
624 server_id = server['id']
625 port_id = self._list_ports(device_id=server_id)[0]['id']
626 self.check_public_network_connectivity(
627 should_connect=True, msg="before updating "
628 "admin_state_up of instance port to False")
John Warren49c0fe52015-10-22 12:35:54 -0400629 self.ports_client.update_port(port_id, admin_state_up=False)
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800630 self.check_public_network_connectivity(
631 should_connect=False, msg="after updating "
632 "admin_state_up of instance port to False",
633 should_check_floating_ip_status=False)
John Warren49c0fe52015-10-22 12:35:54 -0400634 self.ports_client.update_port(port_id, admin_state_up=True)
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800635 self.check_public_network_connectivity(
636 should_connect=True, msg="after updating "
637 "admin_state_up of instance port to True")
Matt Riedemann17940732015-03-13 14:18:19 +0000638
639 @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
Matt Riedemann17940732015-03-13 14:18:19 +0000640 @test.services('compute', 'network')
641 def test_preserve_preexisting_port(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000642 """Test preserve pre-existing port
643
644 Tests that a pre-existing port provided on server boot is not deleted
645 if the server is deleted.
Matt Riedemann17940732015-03-13 14:18:19 +0000646
647 Nova should unbind the port from the instance on delete if the port was
648 not created by Nova as part of the boot request.
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400649
650 We should also be able to boot another server with the same port.
Matt Riedemann17940732015-03-13 14:18:19 +0000651 """
652 # Setup the network, create a port and boot the server from that port.
653 self._setup_network_and_servers(boot_with_port=True)
654 _, server = self.floating_ip_tuple
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000655 self.assertEqual(1, len(self.ports),
656 'There should only be one port created for '
657 'server %s.' % server['id'])
658 port_id = self.ports[0]['port']
659 self.assertIsNotNone(port_id,
Matt Riedemann17940732015-03-13 14:18:19 +0000660 'Server should have been created from a '
661 'pre-existing port.')
662 # Assert the port is bound to the server.
663 port_list = self._list_ports(device_id=server['id'],
664 network_id=self.network['id'])
665 self.assertEqual(1, len(port_list),
666 'There should only be one port created for '
667 'server %s.' % server['id'])
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000668 self.assertEqual(port_id, port_list[0]['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000669 # Delete the server.
670 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000671 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000672 # Assert the port still exists on the network but is unbound from
673 # the deleted server.
John Warren49c0fe52015-10-22 12:35:54 -0400674 port = self.ports_client.show_port(port_id)['port']
Matt Riedemann17940732015-03-13 14:18:19 +0000675 self.assertEqual(self.network['id'], port['network_id'])
676 self.assertEqual('', port['device_id'])
677 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300678
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400679 # Boot another server with the same port to make sure nothing was
680 # left around that could cause issues.
681 name = data_utils.rand_name('reuse-port')
682 server = self._create_server(name, self.network, port['id'])
683 port_list = self._list_ports(device_id=server['id'],
684 network_id=self.network['id'])
685 self.assertEqual(1, len(port_list),
686 'There should only be one port created for '
687 'server %s.' % server['id'])
688 self.assertEqual(port['id'], port_list[0]['id'])
689
YAMAMOTO Takashi56216312015-09-10 20:05:03 +0900690 @test.requires_ext(service='network', extension='l3_agent_scheduler')
Yair Fried564d89d2015-08-06 17:02:12 +0300691 @test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
Yair Fried564d89d2015-08-06 17:02:12 +0300692 @test.services('compute', 'network')
693 def test_router_rescheduling(self):
694 """Tests that router can be removed from agent and add to a new agent.
695
696 1. Verify connectivity
697 2. Remove router from all l3-agents
698 3. Verify connectivity is down
699 4. Assign router to new l3-agent (or old one if no new agent is
700 available)
701 5. Verify connectivity
702 """
703
704 # TODO(yfried): refactor this test to be used for other agents (dhcp)
705 # as well
706
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000707 list_hosts = (self.admin_manager.routers_client.
Yair Fried564d89d2015-08-06 17:02:12 +0300708 list_l3_agents_hosting_router)
Ken'ichi Ohmichi71860062015-12-15 08:20:13 +0000709 schedule_router = (self.admin_manager.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000710 create_router_on_l3_agent)
Ken'ichi Ohmichi71860062015-12-15 08:20:13 +0000711 unschedule_router = (self.admin_manager.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000712 delete_router_from_l3_agent)
Yair Fried564d89d2015-08-06 17:02:12 +0300713
shipeiqic9a4a102016-04-20 17:39:03 +0800714 agent_list_alive = set(a["id"] for a in
715 self._list_agents(agent_type="L3 agent") if
716 a["alive"] is True)
Yair Fried564d89d2015-08-06 17:02:12 +0300717 self._setup_network_and_servers()
Kevin Benton3b63aa12015-08-27 17:15:44 -0700718
719 # NOTE(kevinbenton): we have to use the admin credentials to check
Sean Dagueed6e5862016-04-04 10:49:13 -0400720 # for the distributed flag because self.router only has a project view.
Steve Heyman33735f22016-05-24 09:28:08 -0500721 admin = self.admin_manager.routers_client.show_router(
722 self.router['id'])
Kevin Benton3b63aa12015-08-27 17:15:44 -0700723 if admin['router'].get('distributed', False):
724 msg = "Rescheduling test does not apply to distributed routers."
725 raise self.skipException(msg)
726
Yair Fried564d89d2015-08-06 17:02:12 +0300727 self.check_public_network_connectivity(should_connect=True)
728
729 # remove resource from agents
730 hosting_agents = set(a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500731 list_hosts(self.router['id'])['agents'])
shipeiqic9a4a102016-04-20 17:39:03 +0800732 no_migration = agent_list_alive == hosting_agents
Yair Fried564d89d2015-08-06 17:02:12 +0300733 LOG.info("Router will be assigned to {mig} hosting agent".
734 format(mig="the same" if no_migration else "a new"))
735
736 for hosting_agent in hosting_agents:
Steve Heyman33735f22016-05-24 09:28:08 -0500737 unschedule_router(hosting_agent, self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300738 self.assertNotIn(hosting_agent,
739 [a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500740 list_hosts(self.router['id'])['agents']],
Yair Fried564d89d2015-08-06 17:02:12 +0300741 'unscheduling router failed')
742
743 # verify resource is un-functional
744 self.check_public_network_connectivity(
745 should_connect=False,
746 msg='after router unscheduling',
747 should_check_floating_ip_status=False
748 )
749
750 # schedule resource to new agent
751 target_agent = list(hosting_agents if no_migration else
shipeiqic9a4a102016-04-20 17:39:03 +0800752 agent_list_alive - hosting_agents)[0]
Yair Fried564d89d2015-08-06 17:02:12 +0300753 schedule_router(target_agent,
piyush110786bc0faa62015-12-03 14:54:48 +0530754 router_id=self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300755 self.assertEqual(
756 target_agent,
Steve Heyman33735f22016-05-24 09:28:08 -0500757 list_hosts(self.router['id'])['agents'][0]['id'],
Yair Fried564d89d2015-08-06 17:02:12 +0300758 "Router failed to reschedule. Hosting agent doesn't match "
759 "target agent")
760
761 # verify resource is functional
762 self.check_public_network_connectivity(
763 should_connect=True,
764 msg='After router rescheduling')
Yair Friedbc46f592015-11-18 16:29:34 +0200765
766 @test.requires_ext(service='network', extension='port-security')
Evgeny Antyshevaaf3fc92016-02-15 11:49:22 +0000767 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
768 'NIC hotplug not available')
Yair Friedbc46f592015-11-18 16:29:34 +0200769 @test.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
770 @test.services('compute', 'network')
771 def test_port_security_macspoofing_port(self):
772 """Tests port_security extension enforces mac spoofing
773
Eran Kuris7969e802015-12-15 13:43:46 +0200774 Neutron security groups always apply anti-spoof rules on the VMs. This
775 allows traffic to originate and terminate at the VM as expected, but
776 prevents traffic to pass through the VM. Anti-spoof rules are not
777 required in cases where the VM routes traffic through it.
778
779 The test steps are :
780 1. Create a new network.
781 2. Connect (hotplug) the VM to a new network.
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900782 3. Check the VM can ping a server on the new network ("peer")
Eran Kuris7969e802015-12-15 13:43:46 +0200783 4. Spoof the mac address of the new VM interface.
784 5. Check the Security Group enforces mac spoofing and blocks pings via
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900785 spoofed interface (VM cannot ping the peer).
Eran Kuris7969e802015-12-15 13:43:46 +0200786 6. Disable port-security of the spoofed port- set the flag to false.
787 7. Retest 3rd step and check that the Security Group allows pings via
788 the spoofed interface.
Yair Friedbc46f592015-11-18 16:29:34 +0200789 """
Eran Kuris7969e802015-12-15 13:43:46 +0200790
Yair Friedbc46f592015-11-18 16:29:34 +0200791 spoof_mac = "00:00:00:00:00:01"
792
793 # Create server
794 self._setup_network_and_servers()
YAMAMOTO Takashic368dde2015-11-30 23:04:14 +0900795 self.check_public_network_connectivity(should_connect=True)
Yair Friedbc46f592015-11-18 16:29:34 +0200796 self._create_new_network()
797 self._hotplug_server()
798 fip, server = self.floating_ip_tuple
799 new_ports = self._list_ports(device_id=server["id"],
800 network_id=self.new_net["id"])
801 spoof_port = new_ports[0]
802 private_key = self._get_server_key(server)
Steve Heyman33735f22016-05-24 09:28:08 -0500803 ssh_client = self.get_remote_client(fip['floating_ip_address'],
Yair Friedbc46f592015-11-18 16:29:34 +0200804 private_key=private_key)
Evgeny Antyshev9b77ae52016-02-16 09:48:57 +0000805 spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900806 name = data_utils.rand_name('peer')
807 peer = self._create_server(name, self.new_net)
Steve Heyman33735f22016-05-24 09:28:08 -0500808 peer_address = peer['addresses'][self.new_net['name']][0]['addr']
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900809 self._check_remote_connectivity(ssh_client, dest=peer_address,
Yair Friedbc46f592015-11-18 16:29:34 +0200810 nic=spoof_nic, should_succeed=True)
811 ssh_client.set_mac_address(spoof_nic, spoof_mac)
812 new_mac = ssh_client.get_mac_address(nic=spoof_nic)
813 self.assertEqual(spoof_mac, new_mac)
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900814 self._check_remote_connectivity(ssh_client, dest=peer_address,
Yair Friedbc46f592015-11-18 16:29:34 +0200815 nic=spoof_nic, should_succeed=False)
816 self.ports_client.update_port(spoof_port["id"],
817 port_security_enabled=False,
818 security_groups=[])
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900819 self._check_remote_connectivity(ssh_client, dest=peer_address,
Yair Friedbc46f592015-11-18 16:29:34 +0200820 nic=spoof_nic, should_succeed=True)