blob: 44942b010ac1f26af3c06b51935a3ed8e5522e68 [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
Sean Dague6dbc6da2013-05-08 17:49:46 -040026from tempest.scenario import manager
Yair Fried1fc32a12014-08-04 09:11:30 +030027from tempest.services.network import resources as net_resources
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
62 'tenant_networks_reachable' key) if the Tempest host should
63 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()
Matthew Treinish6c072292014-01-29 19:15:52 +000084 if not (CONF.network.tenant_networks_reachable
85 or CONF.network.public_network_id):
Maru Newby81f07a02012-09-05 20:21:19 -070086 msg = ('Either tenant_networks_reachable must be "true", or '
87 '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
116 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]
Yair Frieded8392f2014-01-15 17:21:35 +0200135 self.assertIn(self.network.name, seen_names)
136 self.assertIn(self.network.id, seen_ids)
137
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]
142 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]
149 self.assertIn(self.router.name,
150 seen_router_names)
151 self.assertIn(self.router.id,
152 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']}]
lanoux5fc14522015-09-21 08:17:35 +0000158 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
200 ip_address = floating_ip.floating_ip_address
201 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
241 ip_address = old_floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300242 private_key = self._get_server_key(server)
Yair Fried3097dc12014-01-26 08:46:43 +0200243 ssh_client = self.get_remote_client(ip_address,
244 private_key=private_key)
245 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'],
ghanshyama2364f12015-08-24 15:45:37 +0900252 net_id=self.new_net.id)['interfaceAttachment']
Yair Fried1fc32a12014-08-04 09:11:30 +0300253 self.addCleanup(self.network_client.wait_for_resource_deletion,
254 'port',
John Warren49c0fe52015-10-22 12:35:54 -0400255 interface['port_id'], client=self.ports_client)
Yair Fried1fc32a12014-08-04 09:11:30 +0300256 self.addCleanup(self.delete_wrapper,
257 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
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200266 if not test.call_until_true(check_ports, CONF.network.build_timeout,
267 CONF.network.build_interval):
Matt Riedemann892094e2015-02-05 07:24:02 -0800268 raise exceptions.TimeoutException(
269 "No new port attached to the server in time (%s sec)! "
270 "Old port: %s. Number of new ports: %d" % (
271 CONF.network.build_timeout, old_port,
272 len(self.new_port_list)))
John Warren49c0fe52015-10-22 12:35:54 -0400273 new_port = net_resources.DeletablePort(ports_client=self.ports_client,
Yair Fried1fc32a12014-08-04 09:11:30 +0300274 **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
281 if not test.call_until_true(check_new_nic, CONF.network.build_timeout,
282 CONF.network.build_interval):
283 raise exceptions.TimeoutException("Interface not visible on the "
284 "guest after %s sec"
285 % CONF.network.build_timeout)
286
287 num, new_nic = self.diff_list[0]
Yair Fried3097dc12014-01-26 08:46:43 +0200288 ssh_client.assign_static_ip(nic=new_nic,
289 addr=new_port.fixed_ips[0]['ip_address'])
Yair Friedbc46f592015-11-18 16:29:34 +0200290 ssh_client.set_nic_state(nic=new_nic)
Yair Fried3097dc12014-01-26 08:46:43 +0200291
292 def _get_server_nics(self, ssh_client):
293 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
294 ipatxt = ssh_client.get_ip_list()
295 return reg.findall(ipatxt)
296
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300297 def _check_network_internal_connectivity(self, network,
298 should_connect=True):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000299 """via ssh check VM internal connectivity:
300
Yair Fried06552292013-11-11 12:10:09 +0200301 - ping internal gateway and DHCP port, implying in-tenant connectivity
302 pinging both, because L3 and DHCP agents might be on different nodes
Yair Fried3097dc12014-01-26 08:46:43 +0200303 """
304 floating_ip, server = self.floating_ip_tuple
305 # get internal ports' ips:
306 # get all network ports in the new network
307 internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
Yair Fried1fc32a12014-08-04 09:11:30 +0300308 self._list_ports(tenant_id=server['tenant_id'],
Yair Fried06552292013-11-11 12:10:09 +0200309 network_id=network.id)
Yair Fried3097dc12014-01-26 08:46:43 +0200310 if p['device_owner'].startswith('network'))
311
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300312 self._check_server_connectivity(floating_ip,
313 internal_ips,
314 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200315
316 def _check_network_external_connectivity(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000317 """ping default gateway to imply external connectivity"""
Yair Fried06552292013-11-11 12:10:09 +0200318 if not CONF.network.public_network_id:
319 msg = 'public network not defined.'
320 LOG.info(msg)
321 return
322
Andrew Boik4a3daf12015-03-27 01:59:31 -0400323 # We ping the external IP from the instance using its floating IP
324 # which is always IPv4, so we must only test connectivity to
325 # external IPv4 IPs if the external network is dualstack.
326 v4_subnets = [s for s in self._list_subnets(
327 network_id=CONF.network.public_network_id) if s['ip_version'] == 4]
328 self.assertEqual(1, len(v4_subnets),
329 "Found %d IPv4 subnets" % len(v4_subnets))
Yair Fried06552292013-11-11 12:10:09 +0200330
Andrew Boik4a3daf12015-03-27 01:59:31 -0400331 external_ips = [v4_subnets[0]['gateway_ip']]
Yair Fried06552292013-11-11 12:10:09 +0200332 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
333 external_ips)
334
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300335 def _check_server_connectivity(self, floating_ip, address_list,
336 should_connect=True):
Yair Fried3097dc12014-01-26 08:46:43 +0200337 ip_address = floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300338 private_key = self._get_server_key(self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200339 ssh_source = self._ssh_to_server(ip_address, private_key)
340
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)
452 self.new_subnet.add_to_router(self.router.id)
453 self._check_network_internal_connectivity(network=self.new_net,
454 should_connect=True)
455
Chris Hoge7579c1a2015-02-26 14:12:15 -0800456 @test.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400457 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
458 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200459 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
460 'NIC hotplug not supported for '
461 'vnic_type direct or macvtap')
Yair Fried3097dc12014-01-26 08:46:43 +0200462 @test.services('compute', 'network')
463 def test_hotplug_nic(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000464 """Test hotplug network interface
465
Yair Fried3097dc12014-01-26 08:46:43 +0200466 1. create a new network, with no gateway (to prevent overwriting VM's
467 gateway)
468 2. connect VM to new network
469 3. set static ip and bring new nic up
470 4. check VM can ping new network dhcp port
471
472 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400473 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200474 self.check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200475 self._create_new_network()
476 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200477 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700478
Chris Hoge7579c1a2015-02-26 14:12:15 -0800479 @test.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Adam Gandelmancf611212014-12-09 14:13:28 -0800480 @testtools.skipIf(CONF.baremetal.driver_enabled,
481 'Router state cannot be altered on a shared baremetal '
482 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700483 @test.services('compute', 'network')
484 def test_update_router_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000485 """Test to update admin state up of router
486
Alok Maurya6384bbb2014-07-13 06:44:29 -0700487 1. Check public connectivity before updating
488 admin_state_up attribute of router to False
489 2. Check public connectivity after updating
490 admin_state_up attribute of router to False
491 3. Check public connectivity after updating
492 admin_state_up attribute of router to True
493 """
494 self._setup_network_and_servers()
495 self.check_public_network_connectivity(
496 should_connect=True, msg="before updating "
497 "admin_state_up of router to False")
498 self._update_router_admin_state(self.router, False)
499 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
500 # once bug 1396310 is fixed
501
502 self.check_public_network_connectivity(
503 should_connect=False, msg="after updating "
504 "admin_state_up of router to False",
505 should_check_floating_ip_status=False)
506 self._update_router_admin_state(self.router, True)
507 self.check_public_network_connectivity(
508 should_connect=True, msg="after updating "
509 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200510
Chris Hoge7579c1a2015-02-26 14:12:15 -0800511 @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Adam Gandelman40371682015-03-03 11:27:03 -0800512 @testtools.skipIf(CONF.baremetal.driver_enabled,
513 'network isolation not available for baremetal nodes')
Yair Fried413bf2d2014-11-19 17:07:11 +0200514 @testtools.skipUnless(CONF.scenario.dhcp_client,
515 "DHCP client is not available.")
Yair Fried413bf2d2014-11-19 17:07:11 +0200516 @test.services('compute', 'network')
517 def test_subnet_details(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000518 """Tests that subnet's extra configuration details are affecting VMs.
519
520 This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200521
522 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
523 update in subnet requires server to actively renew its DHCP lease.
524
525 1. Configure subnet with dns nameserver
526 2. retrieve the VM's configured dns and verify it matches the one
527 configured for the subnet.
528 3. update subnet's dns
529 4. retrieve the VM's configured dns and verify it matches the new one
530 configured for the subnet.
531
532 TODO(yfried): add host_routes
533
534 any resolution check would be testing either:
535 * l3 forwarding (tested in test_network_basic_ops)
536 * Name resolution of an external DNS nameserver - out of scope for
537 Tempest
538 """
539 # this test check only updates (no actual resolution) so using
540 # arbitrary ip addresses as nameservers, instead of parsing CONF
541 initial_dns_server = '1.2.3.4'
542 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000543
544 # renewal should be immediate.
545 # Timeouts are suggested by salvatore-orlando in
546 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
547 renew_delay = CONF.network.build_interval
548 renew_timeout = CONF.network.build_timeout
549
Yair Fried413bf2d2014-11-19 17:07:11 +0200550 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
551 self.check_public_network_connectivity(should_connect=True)
552
553 floating_ip, server = self.floating_ip_tuple
554 ip_address = floating_ip.floating_ip_address
555 private_key = self._get_server_key(server)
556 ssh_client = self._ssh_to_server(ip_address, private_key)
557
armando-migliaccio424aa412015-02-22 17:55:17 -0800558 dns_servers = [initial_dns_server]
559 servers = ssh_client.get_dns_servers()
560 self.assertEqual(set(dns_servers), set(servers),
561 'Looking for servers: {trgt_serv}. '
562 'Retrieved DNS nameservers: {act_serv} '
563 'From host: {host}.'
564 .format(host=ssh_client.ssh_client.host,
565 act_serv=servers,
566 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200567
568 self.subnet.update(dns_nameservers=[alt_dns_server])
569 # asserts that Neutron DB has updated the nameservers
570 self.assertEqual([alt_dns_server], self.subnet.dns_nameservers,
571 "Failed to update subnet's nameservers")
572
Yair Friedbb0ea392015-01-19 07:26:08 +0000573 def check_new_dns_server():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000574 # NOTE: Server needs to renew its dhcp lease in order to get new
575 # definitions from subnet
576 # NOTE(amuller): we are renewing the lease as part of the retry
577 # because Neutron updates dnsmasq asynchronously after the
578 # subnet-update API call returns.
Yair Friedbb0ea392015-01-19 07:26:08 +0000579 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
armando-migliaccio424aa412015-02-22 17:55:17 -0800580 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000581 LOG.debug("Failed to update DNS nameservers")
582 return False
583 return True
584
585 self.assertTrue(test.call_until_true(check_new_dns_server,
586 renew_timeout,
587 renew_delay),
588 msg="DHCP renewal failed to fetch "
589 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800590
Chris Hoge7579c1a2015-02-26 14:12:15 -0800591 @test.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Adam Gandelman0a7948e2015-02-16 15:13:50 -0800592 @testtools.skipIf(CONF.baremetal.driver_enabled,
593 'admin_state of instance ports cannot be altered '
594 'for baremetal nodes')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300595 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
596 "Changing a port's admin state is not supported "
597 "by the test environment")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800598 @test.services('compute', 'network')
599 def test_update_instance_port_admin_state(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000600 """Test to update admin_state_up attribute of instance port
601
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800602 1. Check public connectivity before updating
603 admin_state_up attribute of instance port to False
604 2. Check public connectivity after updating
605 admin_state_up attribute of instance port to False
606 3. Check public connectivity after updating
607 admin_state_up attribute of instance port to True
608 """
609 self._setup_network_and_servers()
610 floating_ip, server = self.floating_ip_tuple
611 server_id = server['id']
612 port_id = self._list_ports(device_id=server_id)[0]['id']
613 self.check_public_network_connectivity(
614 should_connect=True, msg="before updating "
615 "admin_state_up of instance port to False")
John Warren49c0fe52015-10-22 12:35:54 -0400616 self.ports_client.update_port(port_id, admin_state_up=False)
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800617 self.check_public_network_connectivity(
618 should_connect=False, msg="after updating "
619 "admin_state_up of instance port to False",
620 should_check_floating_ip_status=False)
John Warren49c0fe52015-10-22 12:35:54 -0400621 self.ports_client.update_port(port_id, admin_state_up=True)
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800622 self.check_public_network_connectivity(
623 should_connect=True, msg="after updating "
624 "admin_state_up of instance port to True")
Matt Riedemann17940732015-03-13 14:18:19 +0000625
626 @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
627 @testtools.skipUnless(CONF.compute_feature_enabled.preserve_ports,
628 'Preserving ports on instance delete may not be '
629 'supported in the version of Nova being tested.')
Matt Riedemann17940732015-03-13 14:18:19 +0000630 @test.services('compute', 'network')
631 def test_preserve_preexisting_port(self):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000632 """Test preserve pre-existing port
633
634 Tests that a pre-existing port provided on server boot is not deleted
635 if the server is deleted.
Matt Riedemann17940732015-03-13 14:18:19 +0000636
637 Nova should unbind the port from the instance on delete if the port was
638 not created by Nova as part of the boot request.
639 """
640 # Setup the network, create a port and boot the server from that port.
641 self._setup_network_and_servers(boot_with_port=True)
642 _, server = self.floating_ip_tuple
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000643 self.assertEqual(1, len(self.ports),
644 'There should only be one port created for '
645 'server %s.' % server['id'])
646 port_id = self.ports[0]['port']
647 self.assertIsNotNone(port_id,
Matt Riedemann17940732015-03-13 14:18:19 +0000648 'Server should have been created from a '
649 'pre-existing port.')
650 # Assert the port is bound to the server.
651 port_list = self._list_ports(device_id=server['id'],
652 network_id=self.network['id'])
653 self.assertEqual(1, len(port_list),
654 'There should only be one port created for '
655 'server %s.' % server['id'])
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000656 self.assertEqual(port_id, port_list[0]['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000657 # Delete the server.
658 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000659 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000660 # Assert the port still exists on the network but is unbound from
661 # the deleted server.
John Warren49c0fe52015-10-22 12:35:54 -0400662 port = self.ports_client.show_port(port_id)['port']
Matt Riedemann17940732015-03-13 14:18:19 +0000663 self.assertEqual(self.network['id'], port['network_id'])
664 self.assertEqual('', port['device_id'])
665 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300666
YAMAMOTO Takashi56216312015-09-10 20:05:03 +0900667 @test.requires_ext(service='network', extension='l3_agent_scheduler')
Yair Fried564d89d2015-08-06 17:02:12 +0300668 @test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
Yair Fried564d89d2015-08-06 17:02:12 +0300669 @test.services('compute', 'network')
670 def test_router_rescheduling(self):
671 """Tests that router can be removed from agent and add to a new agent.
672
673 1. Verify connectivity
674 2. Remove router from all l3-agents
675 3. Verify connectivity is down
676 4. Assign router to new l3-agent (or old one if no new agent is
677 available)
678 5. Verify connectivity
679 """
680
681 # TODO(yfried): refactor this test to be used for other agents (dhcp)
682 # as well
683
684 list_hosts = (self.admin_manager.network_client.
685 list_l3_agents_hosting_router)
686 schedule_router = (self.admin_manager.network_client.
687 add_router_to_l3_agent)
688 unschedule_router = (self.admin_manager.network_client.
689 remove_router_from_l3_agent)
690
691 agent_list = set(a["id"] for a in
692 self._list_agents(agent_type="L3 agent"))
693 self._setup_network_and_servers()
Kevin Benton3b63aa12015-08-27 17:15:44 -0700694
695 # NOTE(kevinbenton): we have to use the admin credentials to check
696 # for the distributed flag because self.router only has a tenant view.
697 admin = self.admin_manager.network_client.show_router(self.router.id)
698 if admin['router'].get('distributed', False):
699 msg = "Rescheduling test does not apply to distributed routers."
700 raise self.skipException(msg)
701
Yair Fried564d89d2015-08-06 17:02:12 +0300702 self.check_public_network_connectivity(should_connect=True)
703
704 # remove resource from agents
705 hosting_agents = set(a["id"] for a in
706 list_hosts(self.router.id)['agents'])
707 no_migration = agent_list == hosting_agents
708 LOG.info("Router will be assigned to {mig} hosting agent".
709 format(mig="the same" if no_migration else "a new"))
710
711 for hosting_agent in hosting_agents:
712 unschedule_router(hosting_agent, self.router.id)
713 self.assertNotIn(hosting_agent,
714 [a["id"] for a in
715 list_hosts(self.router.id)['agents']],
716 'unscheduling router failed')
717
718 # verify resource is un-functional
719 self.check_public_network_connectivity(
720 should_connect=False,
721 msg='after router unscheduling',
722 should_check_floating_ip_status=False
723 )
724
725 # schedule resource to new agent
726 target_agent = list(hosting_agents if no_migration else
727 agent_list - hosting_agents)[0]
728 schedule_router(target_agent,
piyush110786bc0faa62015-12-03 14:54:48 +0530729 router_id=self.router['id'])
Yair Fried564d89d2015-08-06 17:02:12 +0300730 self.assertEqual(
731 target_agent,
732 list_hosts(self.router.id)['agents'][0]['id'],
733 "Router failed to reschedule. Hosting agent doesn't match "
734 "target agent")
735
736 # verify resource is functional
737 self.check_public_network_connectivity(
738 should_connect=True,
739 msg='After router rescheduling')
Yair Friedbc46f592015-11-18 16:29:34 +0200740
741 @test.requires_ext(service='network', extension='port-security')
742 @test.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
743 @test.services('compute', 'network')
744 def test_port_security_macspoofing_port(self):
745 """Tests port_security extension enforces mac spoofing
746
Eran Kuris7969e802015-12-15 13:43:46 +0200747 Neutron security groups always apply anti-spoof rules on the VMs. This
748 allows traffic to originate and terminate at the VM as expected, but
749 prevents traffic to pass through the VM. Anti-spoof rules are not
750 required in cases where the VM routes traffic through it.
751
752 The test steps are :
753 1. Create a new network.
754 2. Connect (hotplug) the VM to a new network.
755 3. Check the VM can ping the DHCP interface of this network.
756 4. Spoof the mac address of the new VM interface.
757 5. Check the Security Group enforces mac spoofing and blocks pings via
758 spoofed interface (VM cannot ping the DHCP interface).
759 6. Disable port-security of the spoofed port- set the flag to false.
760 7. Retest 3rd step and check that the Security Group allows pings via
761 the spoofed interface.
Yair Friedbc46f592015-11-18 16:29:34 +0200762 """
Eran Kuris7969e802015-12-15 13:43:46 +0200763
Yair Friedbc46f592015-11-18 16:29:34 +0200764 spoof_mac = "00:00:00:00:00:01"
765
766 # Create server
767 self._setup_network_and_servers()
YAMAMOTO Takashic368dde2015-11-30 23:04:14 +0900768 self.check_public_network_connectivity(should_connect=True)
Yair Friedbc46f592015-11-18 16:29:34 +0200769 self._create_new_network()
770 self._hotplug_server()
771 fip, server = self.floating_ip_tuple
772 new_ports = self._list_ports(device_id=server["id"],
773 network_id=self.new_net["id"])
774 spoof_port = new_ports[0]
775 private_key = self._get_server_key(server)
776 ssh_client = self.get_remote_client(fip.floating_ip_address,
777 private_key=private_key)
778 spoof_nic = ssh_client.get_nic_name(spoof_port["mac_address"])
779 dhcp_ports = self._list_ports(device_owner="network:dhcp",
780 network_id=self.new_net["id"])
781 new_net_dhcp = dhcp_ports[0]["fixed_ips"][0]["ip_address"]
782 self._check_remote_connectivity(ssh_client, dest=new_net_dhcp,
783 nic=spoof_nic, should_succeed=True)
784 ssh_client.set_mac_address(spoof_nic, spoof_mac)
785 new_mac = ssh_client.get_mac_address(nic=spoof_nic)
786 self.assertEqual(spoof_mac, new_mac)
787 self._check_remote_connectivity(ssh_client, dest=new_net_dhcp,
788 nic=spoof_nic, should_succeed=False)
789 self.ports_client.update_port(spoof_port["id"],
790 port_security_enabled=False,
791 security_groups=[])
792 self._check_remote_connectivity(ssh_client, dest=new_net_dhcp,
793 nic=spoof_nic, should_succeed=True)