blob: 9c4808037d11dae7c83b13db7ea6537208f61a11 [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 Dague6dbc6da2013-05-08 17:49:46 -040027from tempest.scenario import manager
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090028from tempest import test
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']:
90 if not test.is_extension_enabled(ext, 'network'):
91 msg = "%s extension not enabled." % ext
92 raise cls.skipException(msg)
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000093
94 @classmethod
95 def setup_credentials(cls):
Masayuki Igawa60ea6c52014-10-15 17:32:14 +090096 # Create no network resources for these tests.
97 cls.set_network_resources()
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000098 super(TestNetworkBasicOps, cls).setup_credentials()
Maru Newby81f07a02012-09-05 20:21:19 -070099
Yair Frieded8392f2014-01-15 17:21:35 +0200100 def setUp(self):
101 super(TestNetworkBasicOps, self).setUp()
Yair Fried1fc32a12014-08-04 09:11:30 +0300102 self.keypairs = {}
103 self.servers = []
David Shrewsbury9bac3662014-08-07 15:07:01 -0400104
Yair Fried413bf2d2014-11-19 17:07:11 +0200105 def _setup_network_and_servers(self, **kwargs):
Matt Riedemann17940732015-03-13 14:18:19 +0000106 boot_with_port = kwargs.pop('boot_with_port', False)
David Shrewsbury9bac3662014-08-07 15:07:01 -0400107 self.security_group = \
108 self._create_security_group(tenant_id=self.tenant_id)
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 = []
Matt Riedemann17940732015-03-13 14:18:19 +0000113 self.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
Steve Heyman33735f22016-05-24 09:28:08 -0500116 self.port_id = self._create_port(self.network['id'])['id']
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000117 self.ports.append({'port': self.port_id})
Matt Riedemann17940732015-03-13 14:18:19 +0000118
Yair Frieded8392f2014-01-15 17:21:35 +0200119 name = data_utils.rand_name('server-smoke')
Matt Riedemann17940732015-03-13 14:18:19 +0000120 server = self._create_server(name, self.network, self.port_id)
Yair Frieded8392f2014-01-15 17:21:35 +0200121 self._check_tenant_network_connectivity()
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200122
Yair Friedae0e73d2014-11-24 11:56:26 +0200123 floating_ip = self.create_floating_ip(server)
124 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Maru Newby81f07a02012-09-05 20:21:19 -0700125
Yair Frieded8392f2014-01-15 17:21:35 +0200126 def check_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000127 """Checks that we see the newly created network/subnet/router
128
129 via checking the result of list_[networks,routers,subnets]
Yair Frieded8392f2014-01-15 17:21:35 +0200130 """
131
Gavin Brebner851c3502013-01-18 13:14:10 +0000132 seen_nets = self._list_networks()
133 seen_names = [n['name'] for n in seen_nets]
134 seen_ids = [n['id'] for n in seen_nets]
Steve Heyman33735f22016-05-24 09:28:08 -0500135 self.assertIn(self.network['name'], seen_names)
136 self.assertIn(self.network['id'], seen_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200137
David Shrewsbury9bac3662014-08-07 15:07:01 -0400138 if self.subnet:
139 seen_subnets = self._list_subnets()
140 seen_net_ids = [n['network_id'] for n in seen_subnets]
141 seen_subnet_ids = [n['id'] for n in seen_subnets]
Steve Heyman33735f22016-05-24 09:28:08 -0500142 self.assertIn(self.network['id'], seen_net_ids)
143 self.assertIn(self.subnet['id'], seen_subnet_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200144
David Shrewsbury9bac3662014-08-07 15:07:01 -0400145 if self.router:
146 seen_routers = self._list_routers()
147 seen_router_ids = [n['id'] for n in seen_routers]
148 seen_router_names = [n['name'] for n in seen_routers]
Steve Heyman33735f22016-05-24 09:28:08 -0500149 self.assertIn(self.router['name'],
David Shrewsbury9bac3662014-08-07 15:07:01 -0400150 seen_router_names)
Steve Heyman33735f22016-05-24 09:28:08 -0500151 self.assertIn(self.router['id'],
David Shrewsbury9bac3662014-08-07 15:07:01 -0400152 seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000153
Matt Riedemann17940732015-03-13 14:18:19 +0000154 def _create_server(self, name, network, port_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +0300155 keypair = self.create_keypair()
156 self.keypairs[keypair['name']] = keypair
Ken'ichi Ohmichi1b3461e2014-12-02 03:41:07 +0000157 security_groups = [{'name': self.security_group['name']}]
Steve Heyman33735f22016-05-24 09:28:08 -0500158 network = {'uuid': network['id']}
Matt Riedemann17940732015-03-13 14:18:19 +0000159 if port_id is not None:
lanoux5fc14522015-09-21 08:17:35 +0000160 network['port'] = port_id
161
162 server = self.create_server(
163 name=name,
164 networks=[network],
165 key_name=keypair['name'],
166 security_groups=security_groups,
167 wait_until='ACTIVE')
Yair Fried1fc32a12014-08-04 09:11:30 +0300168 self.servers.append(server)
169 return server
170
171 def _get_server_key(self, server):
172 return self.keypairs[server['key_name']]['private_key']
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700173
Matthew Treinish2b59f842013-09-09 20:32:51 +0000174 def _check_tenant_network_connectivity(self):
lanoux283273b2015-12-04 03:01:54 -0800175 ssh_login = CONF.validation.image_ssh_user
Yair Fried1fc32a12014-08-04 09:11:30 +0300176 for server in self.servers:
Matt Riedemann2d005be2014-05-27 10:52:35 -0700177 # call the common method in the parent class
178 super(TestNetworkBasicOps, self).\
179 _check_tenant_network_connectivity(
Yair Fried1fc32a12014-08-04 09:11:30 +0300180 server, ssh_login, self._get_server_key(server),
181 servers_for_debug=self.servers)
Brent Eaglesc26d4522013-12-02 13:28:49 -0500182
Alok Maurya6384bbb2014-07-13 06:44:29 -0700183 def check_public_network_connectivity(
184 self, should_connect=True, msg=None,
185 should_check_floating_ip_status=True):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000186 """Verifies connectivty to a VM via public network and floating IP
187
Yair Fried45f92952014-06-26 05:19:19 +0300188 and verifies floating IP has resource status is correct.
189
Yair Fried45f92952014-06-26 05:19:19 +0300190 :param should_connect: bool. determines if connectivity check is
191 negative or positive.
192 :param msg: Failure message to add to Error message. Should describe
193 the place in the test scenario where the method was called,
194 to indicate the context of the failure
Alok Maurya6384bbb2014-07-13 06:44:29 -0700195 :param should_check_floating_ip_status: bool. should status of
196 floating_ip be checked or not
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,
Yair Fried1fc32a12014-08-04 09:11:30 +0300212 self.servers)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000213
Yair Fried9a551c42013-12-15 14:59:34 +0200214 def _disassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200215 floating_ip, server = self.floating_ip_tuple
216 self._disassociate_floating_ip(floating_ip)
217 self.floating_ip_tuple = Floating_IP_tuple(
218 floating_ip, None)
Yair Fried9a551c42013-12-15 14:59:34 +0200219
Yair Fried05db2522013-11-18 11:02:10 +0200220 def _reassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200221 floating_ip, server = self.floating_ip_tuple
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000222 name = data_utils.rand_name('new_server-smoke')
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200223 # create a new server for the floating ip
Yair Fried1fc32a12014-08-04 09:11:30 +0300224 server = self._create_server(name, self.network)
225 self._associate_floating_ip(floating_ip, server)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200226 self.floating_ip_tuple = Floating_IP_tuple(
Yair Fried1fc32a12014-08-04 09:11:30 +0300227 floating_ip, server)
Yair Fried05db2522013-11-18 11:02:10 +0200228
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300229 def _create_new_network(self, create_gateway=False):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300230 self.new_net = self._create_network(tenant_id=self.tenant_id)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300231 if create_gateway:
232 self.new_subnet = self._create_subnet(
233 network=self.new_net)
234 else:
235 self.new_subnet = self._create_subnet(
236 network=self.new_net,
237 gateway_ip=None)
Yair Fried3097dc12014-01-26 08:46:43 +0200238
239 def _hotplug_server(self):
240 old_floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500241 ip_address = old_floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300242 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100243 ssh_client = self.get_remote_client(
244 ip_address, private_key=private_key)
Yair Fried3097dc12014-01-26 08:46:43 +0200245 old_nic_list = self._get_server_nics(ssh_client)
246 # get a port from a list of one item
Yair Fried1fc32a12014-08-04 09:11:30 +0300247 port_list = self._list_ports(device_id=server['id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200248 self.assertEqual(1, len(port_list))
249 old_port = port_list[0]
David Kranzb2b0c182015-02-18 13:28:19 -0500250 interface = self.interface_client.create_interface(
Ken'ichi Ohmichi9509b962015-07-07 05:30:15 +0000251 server_id=server['id'],
Steve Heyman33735f22016-05-24 09:28:08 -0500252 net_id=self.new_net['id'])['interfaceAttachment']
Ken'ichi Ohmichi43e7fcf2016-04-04 11:59:13 -0700253 self.addCleanup(self.ports_client.wait_for_resource_deletion,
254 interface['port_id'])
Jordan Pittier9e227c52016-02-09 14:35:18 +0100255 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
Yair Fried1fc32a12014-08-04 09:11:30 +0300256 self.interface_client.delete_interface,
257 server['id'], interface['port_id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200258
259 def check_ports():
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200260 self.new_port_list = [port for port in
Yair Fried1fc32a12014-08-04 09:11:30 +0300261 self._list_ports(device_id=server['id'])
armando-migliaccio3820a062015-02-12 19:31:54 -0800262 if port['id'] != old_port['id']]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200263 return len(self.new_port_list) == 1
Yair Fried3097dc12014-01-26 08:46:43 +0200264
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200265 if not test.call_until_true(check_ports, CONF.network.build_timeout,
266 CONF.network.build_interval):
Matt Riedemann892094e2015-02-05 07:24:02 -0800267 raise exceptions.TimeoutException(
268 "No new port attached to the server in time (%s sec)! "
269 "Old port: %s. Number of new ports: %d" % (
270 CONF.network.build_timeout, old_port,
271 len(self.new_port_list)))
Steve Heyman33735f22016-05-24 09:28:08 -0500272 new_port = self.new_port_list[0]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200273
274 def check_new_nic():
275 new_nic_list = self._get_server_nics(ssh_client)
276 self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
277 return len(self.diff_list) == 1
278
279 if not test.call_until_true(check_new_nic, CONF.network.build_timeout,
280 CONF.network.build_interval):
281 raise exceptions.TimeoutException("Interface not visible on the "
282 "guest after %s sec"
283 % CONF.network.build_timeout)
284
285 num, new_nic = self.diff_list[0]
Yair Fried3097dc12014-01-26 08:46:43 +0200286 ssh_client.assign_static_ip(nic=new_nic,
Steve Heyman33735f22016-05-24 09:28:08 -0500287 addr=new_port['fixed_ips'][0][
288 'ip_address'])
Yair Friedbc46f592015-11-18 16:29:34 +0200289 ssh_client.set_nic_state(nic=new_nic)
Yair Fried3097dc12014-01-26 08:46:43 +0200290
291 def _get_server_nics(self, ssh_client):
292 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
293 ipatxt = ssh_client.get_ip_list()
294 return reg.findall(ipatxt)
295
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300296 def _check_network_internal_connectivity(self, network,
297 should_connect=True):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000298 """via ssh check VM internal connectivity:
299
Yair Fried06552292013-11-11 12:10:09 +0200300 - ping internal gateway and DHCP port, implying in-tenant connectivity
301 pinging both, because L3 and DHCP agents might be on different nodes
Yair Fried3097dc12014-01-26 08:46:43 +0200302 """
303 floating_ip, server = self.floating_ip_tuple
304 # get internal ports' ips:
305 # get all network ports in the new network
306 internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
Yair Fried1fc32a12014-08-04 09:11:30 +0300307 self._list_ports(tenant_id=server['tenant_id'],
Steve Heyman33735f22016-05-24 09:28:08 -0500308 network_id=network['id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200309 if p['device_owner'].startswith('network'))
310
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300311 self._check_server_connectivity(floating_ip,
312 internal_ips,
313 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200314
315 def _check_network_external_connectivity(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000316 """ping default gateway to imply external connectivity"""
Yair Fried06552292013-11-11 12:10:09 +0200317 if not CONF.network.public_network_id:
318 msg = 'public network not defined.'
319 LOG.info(msg)
320 return
321
Andrew Boik4a3daf12015-03-27 01:59:31 -0400322 # We ping the external IP from the instance using its floating IP
323 # which is always IPv4, so we must only test connectivity to
324 # external IPv4 IPs if the external network is dualstack.
325 v4_subnets = [s for s in self._list_subnets(
326 network_id=CONF.network.public_network_id) if s['ip_version'] == 4]
327 self.assertEqual(1, len(v4_subnets),
328 "Found %d IPv4 subnets" % len(v4_subnets))
Yair Fried06552292013-11-11 12:10:09 +0200329
Andrew Boik4a3daf12015-03-27 01:59:31 -0400330 external_ips = [v4_subnets[0]['gateway_ip']]
Yair Fried06552292013-11-11 12:10:09 +0200331 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
332 external_ips)
333
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300334 def _check_server_connectivity(self, floating_ip, address_list,
335 should_connect=True):
Steve Heyman33735f22016-05-24 09:28:08 -0500336 ip_address = floating_ip['floating_ip_address']
Yair Fried1fc32a12014-08-04 09:11:30 +0300337 private_key = self._get_server_key(self.floating_ip_tuple.server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100338 ssh_source = self.get_remote_client(
339 ip_address, private_key=private_key)
Yair Fried3097dc12014-01-26 08:46:43 +0200340
Yair Fried06552292013-11-11 12:10:09 +0200341 for remote_ip in address_list:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300342 if should_connect:
PranaliDeoreb68b9472015-08-11 00:14:50 -0700343 msg = ("Timed out waiting for %s to become "
344 "reachable") % remote_ip
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300345 else:
346 msg = "ip address %s is reachable" % remote_ip
Yair Fried3097dc12014-01-26 08:46:43 +0200347 try:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300348 self.assertTrue(self._check_remote_connectivity
349 (ssh_source, remote_ip, should_connect),
350 msg)
Yair Fried3097dc12014-01-26 08:46:43 +0200351 except Exception:
352 LOG.exception("Unable to access {dest} via ssh to "
353 "floating-ip {src}".format(dest=remote_ip,
354 src=floating_ip))
Yair Fried3097dc12014-01-26 08:46:43 +0200355 raise
356
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900357 @test.attr(type='smoke')
Chris Hoge7579c1a2015-02-26 14:12:15 -0800358 @test.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900359 @test.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000360 def test_network_basic_ops(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000361 """Basic network operation test
362
Yair Fried3097dc12014-01-26 08:46:43 +0200363 For a freshly-booted VM with an IP address ("port") on a given
364 network:
365
366 - the Tempest host can ping the IP address. This implies, but
367 does not guarantee (see the ssh check that follows), that the
368 VM has been assigned the correct IP address and has
369 connectivity to the Tempest host.
370
371 - the Tempest host can perform key-based authentication to an
372 ssh server hosted at the IP address. This check guarantees
373 that the IP address is associated with the target VM.
374
Yair Fried3097dc12014-01-26 08:46:43 +0200375 - the Tempest host can ssh into the VM via the IP address and
376 successfully execute the following:
377
378 - ping an external IP address, implying external connectivity.
379
380 - ping an external hostname, implying that dns is correctly
381 configured.
382
383 - ping an internal IP address, implying connectivity to another
384 VM on the same network.
385
Yair Fried06552292013-11-11 12:10:09 +0200386 - detach the floating-ip from the VM and verify that it becomes
387 unreachable
388
389 - associate detached floating ip to a new VM and verify connectivity.
390 VMs are created with unique keypair so connectivity also asserts that
391 floating IP is associated with the new VM instead of the old one
392
Yair Fried45f92952014-06-26 05:19:19 +0300393 Verifies that floating IP status is updated correctly after each change
394
Yair Fried06552292013-11-11 12:10:09 +0200395
Yair Fried3097dc12014-01-26 08:46:43 +0200396 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400397 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200398 self.check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200399 self._check_network_internal_connectivity(network=self.network)
400 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200401 self._disassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200402 self.check_public_network_connectivity(should_connect=False,
403 msg="after disassociate "
404 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200405 self._reassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200406 self.check_public_network_connectivity(should_connect=True,
407 msg="after re-associate "
408 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200409
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300410 @test.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
Adam Gandelman36b71fc2015-03-12 12:24:08 -0700411 @testtools.skipIf(CONF.baremetal.driver_enabled,
412 'Baremetal relies on a shared physical network.')
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300413 @test.services('compute', 'network')
414 def test_connectivity_between_vms_on_different_networks(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000415 """Test connectivity between VMs on different networks
416
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300417 For a freshly-booted VM with an IP address ("port") on a given
418 network:
419
420 - the Tempest host can ping the IP address.
421
422 - the Tempest host can ssh into the VM via the IP address and
423 successfully execute the following:
424
425 - ping an external IP address, implying external connectivity.
426
427 - ping an external hostname, implying that dns is correctly
428 configured.
429
430 - ping an internal IP address, implying connectivity to another
431 VM on the same network.
432
433 - Create another network on the same tenant with subnet, create
434 an VM on the new network.
435
436 - Ping the new VM from previous VM failed since the new network
437 was not attached to router yet.
438
439 - Attach the new network to the router, Ping the new VM from
440 previous VM succeed.
441
442 """
443 self._setup_network_and_servers()
444 self.check_public_network_connectivity(should_connect=True)
445 self._check_network_internal_connectivity(network=self.network)
446 self._check_network_external_connectivity()
447 self._create_new_network(create_gateway=True)
448 name = data_utils.rand_name('server-smoke')
449 self._create_server(name, self.new_net)
450 self._check_network_internal_connectivity(network=self.new_net,
451 should_connect=False)
Steve Heyman33735f22016-05-24 09:28:08 -0500452 router_id = self.router['id']
453 self.routers_client.add_router_interface(
454 router_id, subnet_id=self.new_subnet['id'])
455
456 self.addCleanup(test_utils.call_and_ignore_notfound_exc,
457 self.routers_client.remove_router_interface,
458 router_id, subnet_id=self.new_subnet['id'])
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300459 self._check_network_internal_connectivity(network=self.new_net,
460 should_connect=True)
461
Chris Hoge7579c1a2015-02-26 14:12:15 -0800462 @test.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400463 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
464 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200465 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
466 'NIC hotplug not supported for '
467 'vnic_type direct or macvtap')
Yair Fried3097dc12014-01-26 08:46:43 +0200468 @test.services('compute', 'network')
469 def test_hotplug_nic(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000470 """Test hotplug network interface
471
Yair Fried3097dc12014-01-26 08:46:43 +0200472 1. create a new network, with no gateway (to prevent overwriting VM's
473 gateway)
474 2. connect VM to new network
475 3. set static ip and bring new nic up
476 4. check VM can ping new network dhcp port
477
478 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400479 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200480 self.check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200481 self._create_new_network()
482 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200483 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700484
Chris Hoge7579c1a2015-02-26 14:12:15 -0800485 @test.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Adam Gandelmancf611212014-12-09 14:13:28 -0800486 @testtools.skipIf(CONF.baremetal.driver_enabled,
487 'Router state cannot be altered on a shared baremetal '
488 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700489 @test.services('compute', 'network')
490 def test_update_router_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000491 """Test to update admin state up of router
492
Alok Maurya6384bbb2014-07-13 06:44:29 -0700493 1. Check public connectivity before updating
494 admin_state_up attribute of router to False
495 2. Check public connectivity after updating
496 admin_state_up attribute of router to False
497 3. Check public connectivity after updating
498 admin_state_up attribute of router to True
499 """
500 self._setup_network_and_servers()
501 self.check_public_network_connectivity(
502 should_connect=True, msg="before updating "
503 "admin_state_up of router to False")
504 self._update_router_admin_state(self.router, False)
505 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
506 # once bug 1396310 is fixed
507
508 self.check_public_network_connectivity(
509 should_connect=False, msg="after updating "
510 "admin_state_up of router to False",
511 should_check_floating_ip_status=False)
512 self._update_router_admin_state(self.router, True)
513 self.check_public_network_connectivity(
514 should_connect=True, msg="after updating "
515 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200516
Chris Hoge7579c1a2015-02-26 14:12:15 -0800517 @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Adam Gandelman40371682015-03-03 11:27:03 -0800518 @testtools.skipIf(CONF.baremetal.driver_enabled,
519 'network isolation not available for baremetal nodes')
Yair Fried413bf2d2014-11-19 17:07:11 +0200520 @testtools.skipUnless(CONF.scenario.dhcp_client,
521 "DHCP client is not available.")
Yair Fried413bf2d2014-11-19 17:07:11 +0200522 @test.services('compute', 'network')
523 def test_subnet_details(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000524 """Tests that subnet's extra configuration details are affecting VMs.
525
526 This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200527
528 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
529 update in subnet requires server to actively renew its DHCP lease.
530
531 1. Configure subnet with dns nameserver
532 2. retrieve the VM's configured dns and verify it matches the one
533 configured for the subnet.
534 3. update subnet's dns
535 4. retrieve the VM's configured dns and verify it matches the new one
536 configured for the subnet.
537
538 TODO(yfried): add host_routes
539
540 any resolution check would be testing either:
541 * l3 forwarding (tested in test_network_basic_ops)
542 * Name resolution of an external DNS nameserver - out of scope for
543 Tempest
544 """
545 # this test check only updates (no actual resolution) so using
546 # arbitrary ip addresses as nameservers, instead of parsing CONF
547 initial_dns_server = '1.2.3.4'
548 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000549
550 # renewal should be immediate.
551 # Timeouts are suggested by salvatore-orlando in
552 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
553 renew_delay = CONF.network.build_interval
554 renew_timeout = CONF.network.build_timeout
555
Yair Fried413bf2d2014-11-19 17:07:11 +0200556 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
557 self.check_public_network_connectivity(should_connect=True)
558
559 floating_ip, server = self.floating_ip_tuple
Steve Heyman33735f22016-05-24 09:28:08 -0500560 ip_address = floating_ip['floating_ip_address']
Yair Fried413bf2d2014-11-19 17:07:11 +0200561 private_key = self._get_server_key(server)
Jordan Pittierbbb17122016-01-26 17:10:55 +0100562 ssh_client = self.get_remote_client(
563 ip_address, private_key=private_key)
Yair Fried413bf2d2014-11-19 17:07:11 +0200564
armando-migliaccio424aa412015-02-22 17:55:17 -0800565 dns_servers = [initial_dns_server]
566 servers = ssh_client.get_dns_servers()
567 self.assertEqual(set(dns_servers), set(servers),
568 'Looking for servers: {trgt_serv}. '
569 'Retrieved DNS nameservers: {act_serv} '
570 'From host: {host}.'
571 .format(host=ssh_client.ssh_client.host,
572 act_serv=servers,
573 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200574
Steve Heyman33735f22016-05-24 09:28:08 -0500575 self.subnet = self.subnets_client.update_subnet(
576 self.subnet['id'], dns_nameservers=[alt_dns_server])['subnet']
577
Yair Fried413bf2d2014-11-19 17:07:11 +0200578 # asserts that Neutron DB has updated the nameservers
Steve Heyman33735f22016-05-24 09:28:08 -0500579 self.assertEqual([alt_dns_server], self.subnet['dns_nameservers'],
Yair Fried413bf2d2014-11-19 17:07:11 +0200580 "Failed to update subnet's nameservers")
581
Yair Friedbb0ea392015-01-19 07:26:08 +0000582 def check_new_dns_server():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000583 # NOTE: Server needs to renew its dhcp lease in order to get new
584 # definitions from subnet
585 # NOTE(amuller): we are renewing the lease as part of the retry
586 # because Neutron updates dnsmasq asynchronously after the
587 # subnet-update API call returns.
Yair Friedbb0ea392015-01-19 07:26:08 +0000588 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
armando-migliaccio424aa412015-02-22 17:55:17 -0800589 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000590 LOG.debug("Failed to update DNS nameservers")
591 return False
592 return True
593
594 self.assertTrue(test.call_until_true(check_new_dns_server,
595 renew_timeout,
596 renew_delay),
597 msg="DHCP renewal failed to fetch "
598 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800599
Chris Hoge7579c1a2015-02-26 14:12:15 -0800600 @test.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Adam Gandelman0a7948e2015-02-16 15:13:50 -0800601 @testtools.skipIf(CONF.baremetal.driver_enabled,
602 'admin_state of instance ports cannot be altered '
603 'for baremetal nodes')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300604 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
605 "Changing a port's admin state is not supported "
606 "by the test environment")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800607 @test.services('compute', 'network')
608 def test_update_instance_port_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000609 """Test to update admin_state_up attribute of instance port
610
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800611 1. Check public connectivity before updating
612 admin_state_up attribute of instance port to False
613 2. Check public connectivity after updating
614 admin_state_up attribute of instance port to False
615 3. Check public connectivity after updating
616 admin_state_up attribute of instance port to True
617 """
618 self._setup_network_and_servers()
619 floating_ip, server = self.floating_ip_tuple
620 server_id = server['id']
621 port_id = self._list_ports(device_id=server_id)[0]['id']
622 self.check_public_network_connectivity(
623 should_connect=True, msg="before updating "
624 "admin_state_up of instance port to False")
John Warren49c0fe52015-10-22 12:35:54 -0400625 self.ports_client.update_port(port_id, admin_state_up=False)
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800626 self.check_public_network_connectivity(
627 should_connect=False, msg="after updating "
628 "admin_state_up of instance port to False",
629 should_check_floating_ip_status=False)
John Warren49c0fe52015-10-22 12:35:54 -0400630 self.ports_client.update_port(port_id, admin_state_up=True)
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800631 self.check_public_network_connectivity(
632 should_connect=True, msg="after updating "
633 "admin_state_up of instance port to True")
Matt Riedemann17940732015-03-13 14:18:19 +0000634
635 @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
Matt Riedemann17940732015-03-13 14:18:19 +0000636 @test.services('compute', 'network')
637 def test_preserve_preexisting_port(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000638 """Test preserve pre-existing port
639
640 Tests that a pre-existing port provided on server boot is not deleted
641 if the server is deleted.
Matt Riedemann17940732015-03-13 14:18:19 +0000642
643 Nova should unbind the port from the instance on delete if the port was
644 not created by Nova as part of the boot request.
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400645
646 We should also be able to boot another server with the same port.
Matt Riedemann17940732015-03-13 14:18:19 +0000647 """
648 # Setup the network, create a port and boot the server from that port.
649 self._setup_network_and_servers(boot_with_port=True)
650 _, server = self.floating_ip_tuple
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000651 self.assertEqual(1, len(self.ports),
652 'There should only be one port created for '
653 'server %s.' % server['id'])
654 port_id = self.ports[0]['port']
655 self.assertIsNotNone(port_id,
Matt Riedemann17940732015-03-13 14:18:19 +0000656 'Server should have been created from a '
657 'pre-existing port.')
658 # Assert the port is bound to the server.
659 port_list = self._list_ports(device_id=server['id'],
660 network_id=self.network['id'])
661 self.assertEqual(1, len(port_list),
662 'There should only be one port created for '
663 'server %s.' % server['id'])
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000664 self.assertEqual(port_id, port_list[0]['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000665 # Delete the server.
666 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000667 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000668 # Assert the port still exists on the network but is unbound from
669 # the deleted server.
John Warren49c0fe52015-10-22 12:35:54 -0400670 port = self.ports_client.show_port(port_id)['port']
Matt Riedemann17940732015-03-13 14:18:19 +0000671 self.assertEqual(self.network['id'], port['network_id'])
672 self.assertEqual('', port['device_id'])
673 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300674
Matt Riedemanna8c641a2016-07-12 17:07:33 -0400675 # Boot another server with the same port to make sure nothing was
676 # left around that could cause issues.
677 name = data_utils.rand_name('reuse-port')
678 server = self._create_server(name, self.network, port['id'])
679 port_list = self._list_ports(device_id=server['id'],
680 network_id=self.network['id'])
681 self.assertEqual(1, len(port_list),
682 'There should only be one port created for '
683 'server %s.' % server['id'])
684 self.assertEqual(port['id'], port_list[0]['id'])
685
YAMAMOTO Takashi56216312015-09-10 20:05:03 +0900686 @test.requires_ext(service='network', extension='l3_agent_scheduler')
Yair Fried564d89d2015-08-06 17:02:12 +0300687 @test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
Yair Fried564d89d2015-08-06 17:02:12 +0300688 @test.services('compute', 'network')
689 def test_router_rescheduling(self):
690 """Tests that router can be removed from agent and add to a new agent.
691
692 1. Verify connectivity
693 2. Remove router from all l3-agents
694 3. Verify connectivity is down
695 4. Assign router to new l3-agent (or old one if no new agent is
696 available)
697 5. Verify connectivity
698 """
699
700 # TODO(yfried): refactor this test to be used for other agents (dhcp)
701 # as well
702
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000703 list_hosts = (self.admin_manager.routers_client.
Yair Fried564d89d2015-08-06 17:02:12 +0300704 list_l3_agents_hosting_router)
Ken'ichi Ohmichi71860062015-12-15 08:20:13 +0000705 schedule_router = (self.admin_manager.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000706 create_router_on_l3_agent)
Ken'ichi Ohmichi71860062015-12-15 08:20:13 +0000707 unschedule_router = (self.admin_manager.network_agents_client.
Ken'ichi Ohmichi70a24e92016-01-06 01:08:27 +0000708 delete_router_from_l3_agent)
Yair Fried564d89d2015-08-06 17:02:12 +0300709
shipeiqic9a4a102016-04-20 17:39:03 +0800710 agent_list_alive = set(a["id"] for a in
711 self._list_agents(agent_type="L3 agent") if
712 a["alive"] is True)
Yair Fried564d89d2015-08-06 17:02:12 +0300713 self._setup_network_and_servers()
Kevin Benton3b63aa12015-08-27 17:15:44 -0700714
715 # NOTE(kevinbenton): we have to use the admin credentials to check
Sean Dagueed6e5862016-04-04 10:49:13 -0400716 # for the distributed flag because self.router only has a project view.
Steve Heyman33735f22016-05-24 09:28:08 -0500717 admin = self.admin_manager.routers_client.show_router(
718 self.router['id'])
Kevin Benton3b63aa12015-08-27 17:15:44 -0700719 if admin['router'].get('distributed', False):
720 msg = "Rescheduling test does not apply to distributed routers."
721 raise self.skipException(msg)
722
Yair Fried564d89d2015-08-06 17:02:12 +0300723 self.check_public_network_connectivity(should_connect=True)
724
725 # remove resource from agents
726 hosting_agents = set(a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500727 list_hosts(self.router['id'])['agents'])
shipeiqic9a4a102016-04-20 17:39:03 +0800728 no_migration = agent_list_alive == hosting_agents
Yair Fried564d89d2015-08-06 17:02:12 +0300729 LOG.info("Router will be assigned to {mig} hosting agent".
730 format(mig="the same" if no_migration else "a new"))
731
732 for hosting_agent in hosting_agents:
Steve Heyman33735f22016-05-24 09:28:08 -0500733 unschedule_router(hosting_agent, self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300734 self.assertNotIn(hosting_agent,
735 [a["id"] for a in
Steve Heyman33735f22016-05-24 09:28:08 -0500736 list_hosts(self.router['id'])['agents']],
Yair Fried564d89d2015-08-06 17:02:12 +0300737 'unscheduling router failed')
738
739 # verify resource is un-functional
740 self.check_public_network_connectivity(
741 should_connect=False,
742 msg='after router unscheduling',
743 should_check_floating_ip_status=False
744 )
745
746 # schedule resource to new agent
747 target_agent = list(hosting_agents if no_migration else
shipeiqic9a4a102016-04-20 17:39:03 +0800748 agent_list_alive - hosting_agents)[0]
Yair Fried564d89d2015-08-06 17:02:12 +0300749 schedule_router(target_agent,
piyush110786bc0faa62015-12-03 14:54:48 +0530750 router_id=self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300751 self.assertEqual(
752 target_agent,
Steve Heyman33735f22016-05-24 09:28:08 -0500753 list_hosts(self.router['id'])['agents'][0]['id'],
Yair Fried564d89d2015-08-06 17:02:12 +0300754 "Router failed to reschedule. Hosting agent doesn't match "
755 "target agent")
756
757 # verify resource is functional
758 self.check_public_network_connectivity(
759 should_connect=True,
760 msg='After router rescheduling')
Yair Friedbc46f592015-11-18 16:29:34 +0200761
762 @test.requires_ext(service='network', extension='port-security')
Evgeny Antyshevaaf3fc92016-02-15 11:49:22 +0000763 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
764 'NIC hotplug not available')
Yair Friedbc46f592015-11-18 16:29:34 +0200765 @test.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
766 @test.services('compute', 'network')
767 def test_port_security_macspoofing_port(self):
768 """Tests port_security extension enforces mac spoofing
769
Eran Kuris7969e802015-12-15 13:43:46 +0200770 Neutron security groups always apply anti-spoof rules on the VMs. This
771 allows traffic to originate and terminate at the VM as expected, but
772 prevents traffic to pass through the VM. Anti-spoof rules are not
773 required in cases where the VM routes traffic through it.
774
775 The test steps are :
776 1. Create a new network.
777 2. Connect (hotplug) the VM to a new network.
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900778 3. Check the VM can ping a server on the new network ("peer")
Eran Kuris7969e802015-12-15 13:43:46 +0200779 4. Spoof the mac address of the new VM interface.
780 5. Check the Security Group enforces mac spoofing and blocks pings via
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900781 spoofed interface (VM cannot ping the peer).
Eran Kuris7969e802015-12-15 13:43:46 +0200782 6. Disable port-security of the spoofed port- set the flag to false.
783 7. Retest 3rd step and check that the Security Group allows pings via
784 the spoofed interface.
Yair Friedbc46f592015-11-18 16:29:34 +0200785 """
Eran Kuris7969e802015-12-15 13:43:46 +0200786
Yair Friedbc46f592015-11-18 16:29:34 +0200787 spoof_mac = "00:00:00:00:00:01"
788
789 # Create server
790 self._setup_network_and_servers()
YAMAMOTO Takashic368dde2015-11-30 23:04:14 +0900791 self.check_public_network_connectivity(should_connect=True)
Yair Friedbc46f592015-11-18 16:29:34 +0200792 self._create_new_network()
793 self._hotplug_server()
794 fip, server = self.floating_ip_tuple
795 new_ports = self._list_ports(device_id=server["id"],
796 network_id=self.new_net["id"])
797 spoof_port = new_ports[0]
798 private_key = self._get_server_key(server)
Steve Heyman33735f22016-05-24 09:28:08 -0500799 ssh_client = self.get_remote_client(fip['floating_ip_address'],
Yair Friedbc46f592015-11-18 16:29:34 +0200800 private_key=private_key)
Evgeny Antyshev9b77ae52016-02-16 09:48:57 +0000801 spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900802 name = data_utils.rand_name('peer')
803 peer = self._create_server(name, self.new_net)
Steve Heyman33735f22016-05-24 09:28:08 -0500804 peer_address = peer['addresses'][self.new_net['name']][0]['addr']
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900805 self._check_remote_connectivity(ssh_client, dest=peer_address,
Yair Friedbc46f592015-11-18 16:29:34 +0200806 nic=spoof_nic, should_succeed=True)
807 ssh_client.set_mac_address(spoof_nic, spoof_mac)
808 new_mac = ssh_client.get_mac_address(nic=spoof_nic)
809 self.assertEqual(spoof_mac, new_mac)
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900810 self._check_remote_connectivity(ssh_client, dest=peer_address,
Yair Friedbc46f592015-11-18 16:29:34 +0200811 nic=spoof_nic, should_succeed=False)
812 self.ports_client.update_port(spoof_port["id"],
813 port_security_enabled=False,
814 security_groups=[])
YAMAMOTO Takashic3978412015-11-30 23:55:56 +0900815 self._check_remote_connectivity(ssh_client, dest=peer_address,
Yair Friedbc46f592015-11-18 16:29:34 +0200816 nic=spoof_nic, should_succeed=True)