blob: 10dfb66fc451a02592b3680fcff2da17ff0e511d [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
Adam Gandelman7186f7a2014-07-23 09:28:56 -040019import testtools
Yair Fried3097dc12014-01-26 08:46:43 +020020
Attila Fazekasaeeeefd2013-08-06 17:01:56 +020021from tempest.common import debug
Masayuki Igawa259c1132013-10-31 17:48:44 +090022from tempest.common.utils import data_utils
Matthew Treinishcb569942013-08-09 16:33:44 -040023from tempest import config
Attila Fazekasa8bb3942014-08-19 09:06:30 +020024from tempest import exceptions
Matthew Treinish2b59f842013-09-09 20:32:51 +000025from tempest.openstack.common import log as logging
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
Yair Fried1fc32a12014-08-04 09:11:30 +030037class TestNetworkBasicOps(manager.NeutronScenarioTest):
Maru Newby81f07a02012-09-05 20:21:19 -070038
39 """
40 This smoke test suite assumes that Nova has been configured to
Mark McClainf2982e82013-07-06 17:48:03 -040041 boot VM's with Neutron-managed networking, and attempts to
Maru Newby81f07a02012-09-05 20:21:19 -070042 verify network connectivity as follows:
43
Maru Newby81f07a02012-09-05 20:21:19 -070044 There are presumed to be two types of networks: tenant and
45 public. A tenant network may or may not be reachable from the
46 Tempest host. A public network is assumed to be reachable from
47 the Tempest host, and it should be possible to associate a public
48 ('floating') IP address with a tenant ('fixed') IP address to
Chang Bo Guocc1623c2013-09-13 20:11:27 -070049 facilitate external connectivity to a potentially unroutable
Maru Newby81f07a02012-09-05 20:21:19 -070050 tenant IP address.
51
52 This test suite can be configured to test network connectivity to
53 a VM via a tenant network, a public network, or both. If both
54 networking types are to be evaluated, tests that need to be
55 executed remotely on the VM (via ssh) will only be run against
56 one of the networks (to minimize test execution time).
57
58 Determine which types of networks to test as follows:
59
60 * Configure tenant network checks (via the
61 'tenant_networks_reachable' key) if the Tempest host should
62 have direct connectivity to tenant networks. This is likely to
63 be the case if Tempest is running on the same host as a
64 single-node devstack installation with IP namespaces disabled.
65
66 * Configure checks for a public network if a public network has
67 been configured prior to the test suite being run and if the
68 Tempest host should have connectivity to that public network.
69 Checking connectivity for a public network requires that a
70 value be provided for 'public_network_id'. A value can
71 optionally be provided for 'public_router_id' if tenants will
72 use a shared router to access a public network (as is likely to
73 be the case when IP namespaces are not enabled). If a value is
74 not provided for 'public_router_id', a router will be created
75 for each tenant and use the network identified by
76 'public_network_id' as its gateway.
77
78 """
79
80 @classmethod
81 def check_preconditions(cls):
Gavin Brebner0f465a32013-03-14 13:26:09 +000082 super(TestNetworkBasicOps, cls).check_preconditions()
Matthew Treinish6c072292014-01-29 19:15:52 +000083 if not (CONF.network.tenant_networks_reachable
84 or CONF.network.public_network_id):
Maru Newby81f07a02012-09-05 20:21:19 -070085 msg = ('Either tenant_networks_reachable must be "true", or '
86 'public_network_id must be defined.')
Gavin Brebner0f465a32013-03-14 13:26:09 +000087 cls.enabled = False
ivan-zhu1feeb382013-01-24 10:14:39 +080088 raise cls.skipException(msg)
Maru Newby81f07a02012-09-05 20:21:19 -070089
90 @classmethod
91 def setUpClass(cls):
Yair Fried764610a2014-04-07 12:17:05 +030092 # Create no network resources for these tests.
93 cls.set_network_resources()
Maru Newby81f07a02012-09-05 20:21:19 -070094 super(TestNetworkBasicOps, cls).setUpClass()
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090095 for ext in ['router', 'security-group']:
96 if not test.is_extension_enabled(ext, 'network'):
97 msg = "%s extension not enabled." % ext
98 raise cls.skipException(msg)
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
105 def _setup_network_and_servers(self):
106 self.security_group = \
107 self._create_security_group(tenant_id=self.tenant_id)
108 self.network, self.subnet, self.router = self.create_networks()
109 self.check_networks()
110
Yair Frieded8392f2014-01-15 17:21:35 +0200111 name = data_utils.rand_name('server-smoke')
Yair Fried1fc32a12014-08-04 09:11:30 +0300112 server = self._create_server(name, self.network)
Yair Frieded8392f2014-01-15 17:21:35 +0200113 self._check_tenant_network_connectivity()
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200114
Yair Fried1fc32a12014-08-04 09:11:30 +0300115 self._create_and_associate_floating_ips(server)
Maru Newby81f07a02012-09-05 20:21:19 -0700116
Yair Frieded8392f2014-01-15 17:21:35 +0200117 def check_networks(self):
118 """
119 Checks that we see the newly created network/subnet/router via
120 checking the result of list_[networks,routers,subnets]
121 """
122
Gavin Brebner851c3502013-01-18 13:14:10 +0000123 seen_nets = self._list_networks()
124 seen_names = [n['name'] for n in seen_nets]
125 seen_ids = [n['id'] for n in seen_nets]
Yair Frieded8392f2014-01-15 17:21:35 +0200126 self.assertIn(self.network.name, seen_names)
127 self.assertIn(self.network.id, seen_ids)
128
David Shrewsbury9bac3662014-08-07 15:07:01 -0400129 if self.subnet:
130 seen_subnets = self._list_subnets()
131 seen_net_ids = [n['network_id'] for n in seen_subnets]
132 seen_subnet_ids = [n['id'] for n in seen_subnets]
133 self.assertIn(self.network.id, seen_net_ids)
134 self.assertIn(self.subnet.id, seen_subnet_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200135
David Shrewsbury9bac3662014-08-07 15:07:01 -0400136 if self.router:
137 seen_routers = self._list_routers()
138 seen_router_ids = [n['id'] for n in seen_routers]
139 seen_router_names = [n['name'] for n in seen_routers]
140 self.assertIn(self.router.name,
141 seen_router_names)
142 self.assertIn(self.router.id,
143 seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000144
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700145 def _create_server(self, name, network):
Yair Fried1fc32a12014-08-04 09:11:30 +0300146 keypair = self.create_keypair()
147 self.keypairs[keypair['name']] = keypair
148 security_groups = [self.security_group]
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700149 create_kwargs = {
Dirk Mueller8cf79722014-09-12 17:37:15 +0200150 'networks': [
151 {'uuid': network.id},
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700152 ],
Yair Fried1fc32a12014-08-04 09:11:30 +0300153 'key_name': keypair['name'],
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700154 'security_groups': security_groups,
155 }
Giulio Fidente61cadca2013-09-24 18:33:37 +0200156 server = self.create_server(name=name, create_kwargs=create_kwargs)
Yair Fried1fc32a12014-08-04 09:11:30 +0300157 self.servers.append(server)
158 return server
159
160 def _get_server_key(self, server):
161 return self.keypairs[server['key_name']]['private_key']
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700162
Matthew Treinish2b59f842013-09-09 20:32:51 +0000163 def _check_tenant_network_connectivity(self):
Sean Dague86bd8422013-12-20 09:56:44 -0500164 ssh_login = CONF.compute.image_ssh_user
Yair Fried1fc32a12014-08-04 09:11:30 +0300165 for server in self.servers:
Matt Riedemann2d005be2014-05-27 10:52:35 -0700166 # call the common method in the parent class
167 super(TestNetworkBasicOps, self).\
168 _check_tenant_network_connectivity(
Yair Fried1fc32a12014-08-04 09:11:30 +0300169 server, ssh_login, self._get_server_key(server),
170 servers_for_debug=self.servers)
Brent Eaglesc26d4522013-12-02 13:28:49 -0500171
Yair Fried1fc32a12014-08-04 09:11:30 +0300172 def _create_and_associate_floating_ips(self, server):
Sean Dague86bd8422013-12-20 09:56:44 -0500173 public_network_id = CONF.network.public_network_id
Yair Fried1fc32a12014-08-04 09:11:30 +0300174 floating_ip = self._create_floating_ip(server, public_network_id)
175 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Maru Newby81f07a02012-09-05 20:21:19 -0700176
Yair Frieda4b0d1d2014-01-26 13:59:54 +0200177 def _check_public_network_connectivity(self, should_connect=True,
178 msg=None):
Sean Dague86bd8422013-12-20 09:56:44 -0500179 ssh_login = CONF.compute.image_ssh_user
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200180 floating_ip, server = self.floating_ip_tuple
181 ip_address = floating_ip.floating_ip_address
182 private_key = None
183 if should_connect:
Yair Fried1fc32a12014-08-04 09:11:30 +0300184 private_key = self._get_server_key(server)
Matt Riedemann343305f2014-05-27 09:55:03 -0700185 # call the common method in the parent class
186 super(TestNetworkBasicOps, self)._check_public_network_connectivity(
187 ip_address, ssh_login, private_key, should_connect, msg,
Yair Fried1fc32a12014-08-04 09:11:30 +0300188 self.servers)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000189
Yair Fried9a551c42013-12-15 14:59:34 +0200190 def _disassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200191 floating_ip, server = self.floating_ip_tuple
192 self._disassociate_floating_ip(floating_ip)
193 self.floating_ip_tuple = Floating_IP_tuple(
194 floating_ip, None)
Yair Fried9a551c42013-12-15 14:59:34 +0200195
Yair Fried05db2522013-11-18 11:02:10 +0200196 def _reassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200197 floating_ip, server = self.floating_ip_tuple
198 name = data_utils.rand_name('new_server-smoke-')
199 # create a new server for the floating ip
Yair Fried1fc32a12014-08-04 09:11:30 +0300200 server = self._create_server(name, self.network)
201 self._associate_floating_ip(floating_ip, server)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200202 self.floating_ip_tuple = Floating_IP_tuple(
Yair Fried1fc32a12014-08-04 09:11:30 +0300203 floating_ip, server)
Yair Fried05db2522013-11-18 11:02:10 +0200204
Yair Fried3097dc12014-01-26 08:46:43 +0200205 def _create_new_network(self):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300206 self.new_net = self._create_network(tenant_id=self.tenant_id)
Yair Fried3097dc12014-01-26 08:46:43 +0200207 self.new_subnet = self._create_subnet(
208 network=self.new_net,
209 gateway_ip=None)
Yair Fried3097dc12014-01-26 08:46:43 +0200210
211 def _hotplug_server(self):
212 old_floating_ip, server = self.floating_ip_tuple
213 ip_address = old_floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300214 private_key = self._get_server_key(server)
Yair Fried3097dc12014-01-26 08:46:43 +0200215 ssh_client = self.get_remote_client(ip_address,
216 private_key=private_key)
217 old_nic_list = self._get_server_nics(ssh_client)
218 # get a port from a list of one item
Yair Fried1fc32a12014-08-04 09:11:30 +0300219 port_list = self._list_ports(device_id=server['id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200220 self.assertEqual(1, len(port_list))
221 old_port = port_list[0]
Yair Fried1fc32a12014-08-04 09:11:30 +0300222 _, interface = self.interface_client.create_interface(
223 server=server['id'],
224 network_id=self.new_net.id)
225 self.addCleanup(self.network_client.wait_for_resource_deletion,
226 'port',
227 interface['port_id'])
228 self.addCleanup(self.delete_wrapper,
229 self.interface_client.delete_interface,
230 server['id'], interface['port_id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200231
232 def check_ports():
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200233 self.new_port_list = [port for port in
Yair Fried1fc32a12014-08-04 09:11:30 +0300234 self._list_ports(device_id=server['id'])
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200235 if port != old_port]
236 return len(self.new_port_list) == 1
Yair Fried3097dc12014-01-26 08:46:43 +0200237
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200238 if not test.call_until_true(check_ports, CONF.network.build_timeout,
239 CONF.network.build_interval):
240 raise exceptions.TimeoutException("No new port attached to the "
241 "server in time (%s sec) !"
242 % CONF.network.build_timeout)
Yair Fried1fc32a12014-08-04 09:11:30 +0300243 new_port = net_resources.DeletablePort(client=self.network_client,
244 **self.new_port_list[0])
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200245
246 def check_new_nic():
247 new_nic_list = self._get_server_nics(ssh_client)
248 self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
249 return len(self.diff_list) == 1
250
251 if not test.call_until_true(check_new_nic, CONF.network.build_timeout,
252 CONF.network.build_interval):
253 raise exceptions.TimeoutException("Interface not visible on the "
254 "guest after %s sec"
255 % CONF.network.build_timeout)
256
257 num, new_nic = self.diff_list[0]
Yair Fried3097dc12014-01-26 08:46:43 +0200258 ssh_client.assign_static_ip(nic=new_nic,
259 addr=new_port.fixed_ips[0]['ip_address'])
260 ssh_client.turn_nic_on(nic=new_nic)
261
262 def _get_server_nics(self, ssh_client):
263 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
264 ipatxt = ssh_client.get_ip_list()
265 return reg.findall(ipatxt)
266
Yair Fried06552292013-11-11 12:10:09 +0200267 def _check_network_internal_connectivity(self, network):
Yair Fried3097dc12014-01-26 08:46:43 +0200268 """
269 via ssh check VM internal connectivity:
Yair Fried06552292013-11-11 12:10:09 +0200270 - ping internal gateway and DHCP port, implying in-tenant connectivity
271 pinging both, because L3 and DHCP agents might be on different nodes
Yair Fried3097dc12014-01-26 08:46:43 +0200272 """
273 floating_ip, server = self.floating_ip_tuple
274 # get internal ports' ips:
275 # get all network ports in the new network
276 internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
Yair Fried1fc32a12014-08-04 09:11:30 +0300277 self._list_ports(tenant_id=server['tenant_id'],
Yair Fried06552292013-11-11 12:10:09 +0200278 network_id=network.id)
Yair Fried3097dc12014-01-26 08:46:43 +0200279 if p['device_owner'].startswith('network'))
280
Yair Fried06552292013-11-11 12:10:09 +0200281 self._check_server_connectivity(floating_ip, internal_ips)
282
283 def _check_network_external_connectivity(self):
284 """
285 ping public network default gateway to imply external connectivity
286
287 """
288 if not CONF.network.public_network_id:
289 msg = 'public network not defined.'
290 LOG.info(msg)
291 return
292
Yair Fried1fc32a12014-08-04 09:11:30 +0300293 subnet = self._list_subnets(
294 network_id=CONF.network.public_network_id)
Yair Fried06552292013-11-11 12:10:09 +0200295 self.assertEqual(1, len(subnet), "Found %d subnets" % len(subnet))
296
297 external_ips = [subnet[0]['gateway_ip']]
298 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
299 external_ips)
300
301 def _check_server_connectivity(self, floating_ip, address_list):
Yair Fried3097dc12014-01-26 08:46:43 +0200302 ip_address = floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300303 private_key = self._get_server_key(self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200304 ssh_source = self._ssh_to_server(ip_address, private_key)
305
Yair Fried06552292013-11-11 12:10:09 +0200306 for remote_ip in address_list:
Yair Fried3097dc12014-01-26 08:46:43 +0200307 try:
308 self.assertTrue(self._check_remote_connectivity(ssh_source,
309 remote_ip),
310 "Timed out waiting for %s to become "
311 "reachable" % remote_ip)
312 except Exception:
313 LOG.exception("Unable to access {dest} via ssh to "
314 "floating-ip {src}".format(dest=remote_ip,
315 src=floating_ip))
316 debug.log_ip_ns()
317 raise
318
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900319 @test.attr(type='smoke')
320 @test.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000321 def test_network_basic_ops(self):
Yair Fried3097dc12014-01-26 08:46:43 +0200322 """
323 For a freshly-booted VM with an IP address ("port") on a given
324 network:
325
326 - the Tempest host can ping the IP address. This implies, but
327 does not guarantee (see the ssh check that follows), that the
328 VM has been assigned the correct IP address and has
329 connectivity to the Tempest host.
330
331 - the Tempest host can perform key-based authentication to an
332 ssh server hosted at the IP address. This check guarantees
333 that the IP address is associated with the target VM.
334
Yair Fried3097dc12014-01-26 08:46:43 +0200335 - the Tempest host can ssh into the VM via the IP address and
336 successfully execute the following:
337
338 - ping an external IP address, implying external connectivity.
339
340 - ping an external hostname, implying that dns is correctly
341 configured.
342
343 - ping an internal IP address, implying connectivity to another
344 VM on the same network.
345
Yair Fried06552292013-11-11 12:10:09 +0200346 - detach the floating-ip from the VM and verify that it becomes
347 unreachable
348
349 - associate detached floating ip to a new VM and verify connectivity.
350 VMs are created with unique keypair so connectivity also asserts that
351 floating IP is associated with the new VM instead of the old one
352
353
Yair Fried3097dc12014-01-26 08:46:43 +0200354 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400355 self._setup_network_and_servers()
Yair Fried9a551c42013-12-15 14:59:34 +0200356 self._check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200357 self._check_network_internal_connectivity(network=self.network)
358 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200359 self._disassociate_floating_ips()
Yair Frieda4b0d1d2014-01-26 13:59:54 +0200360 self._check_public_network_connectivity(should_connect=False,
361 msg="after disassociate "
362 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200363 self._reassociate_floating_ips()
Yair Frieda4b0d1d2014-01-26 13:59:54 +0200364 self._check_public_network_connectivity(should_connect=True,
365 msg="after re-associate "
366 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200367
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400368 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
369 'NIC hotplug not available')
Yair Fried3097dc12014-01-26 08:46:43 +0200370 @test.attr(type='smoke')
371 @test.services('compute', 'network')
372 def test_hotplug_nic(self):
373 """
374 1. create a new network, with no gateway (to prevent overwriting VM's
375 gateway)
376 2. connect VM to new network
377 3. set static ip and bring new nic up
378 4. check VM can ping new network dhcp port
379
380 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400381 self._setup_network_and_servers()
Yair Fried3097dc12014-01-26 08:46:43 +0200382 self._check_public_network_connectivity(should_connect=True)
383 self._create_new_network()
384 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200385 self._check_network_internal_connectivity(network=self.new_net)