blob: 51e101f7734f7f8fbd7daa0ca2dbadf114a555b2 [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
Matthew Treinishcb569942013-08-09 16:33:44 -040023from tempest import config
Attila Fazekasa8bb3942014-08-19 09:06:30 +020024from tempest import exceptions
Sean Dague6dbc6da2013-05-08 17:49:46 -040025from tempest.scenario import manager
Yair Fried1fc32a12014-08-04 09:11:30 +030026from tempest.services.network import resources as net_resources
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090027from tempest import test
Maru Newby81f07a02012-09-05 20:21:19 -070028
Sean Dague86bd8422013-12-20 09:56:44 -050029CONF = config.CONF
Matthew Treinish2b59f842013-09-09 20:32:51 +000030LOG = logging.getLogger(__name__)
31
Yair Fried2d2f3fe2014-02-24 16:19:20 +020032Floating_IP_tuple = collections.namedtuple('Floating_IP_tuple',
33 ['floating_ip', 'server'])
34
Maru Newby81f07a02012-09-05 20:21:19 -070035
Andrea Frittoli4971fc82014-09-25 10:22:20 +010036class TestNetworkBasicOps(manager.NetworkScenarioTest):
Maru Newby81f07a02012-09-05 20:21:19 -070037
38 """
39 This smoke test suite assumes that Nova has been configured to
Mark McClainf2982e82013-07-06 17:48:03 -040040 boot VM's with Neutron-managed networking, and attempts to
Maru Newby81f07a02012-09-05 20:21:19 -070041 verify network connectivity as follows:
42
Maru Newby81f07a02012-09-05 20:21:19 -070043 There are presumed to be two types of networks: tenant and
44 public. A tenant network may or may not be reachable from the
45 Tempest host. A public network is assumed to be reachable from
46 the Tempest host, and it should be possible to associate a public
47 ('floating') IP address with a tenant ('fixed') IP address to
Chang Bo Guocc1623c2013-09-13 20:11:27 -070048 facilitate external connectivity to a potentially unroutable
Maru Newby81f07a02012-09-05 20:21:19 -070049 tenant IP address.
50
51 This test suite can be configured to test network connectivity to
52 a VM via a tenant network, a public network, or both. If both
53 networking types are to be evaluated, tests that need to be
54 executed remotely on the VM (via ssh) will only be run against
55 one of the networks (to minimize test execution time).
56
57 Determine which types of networks to test as follows:
58
59 * Configure tenant network checks (via the
60 'tenant_networks_reachable' key) if the Tempest host should
61 have direct connectivity to tenant networks. This is likely to
62 be the case if Tempest is running on the same host as a
63 single-node devstack installation with IP namespaces disabled.
64
65 * Configure checks for a public network if a public network has
66 been configured prior to the test suite being run and if the
67 Tempest host should have connectivity to that public network.
68 Checking connectivity for a public network requires that a
69 value be provided for 'public_network_id'. A value can
70 optionally be provided for 'public_router_id' if tenants will
71 use a shared router to access a public network (as is likely to
72 be the case when IP namespaces are not enabled). If a value is
73 not provided for 'public_router_id', a router will be created
74 for each tenant and use the network identified by
75 'public_network_id' as its gateway.
76
77 """
78
79 @classmethod
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000080 def skip_checks(cls):
81 super(TestNetworkBasicOps, cls).skip_checks()
Matthew Treinish6c072292014-01-29 19:15:52 +000082 if not (CONF.network.tenant_networks_reachable
83 or CONF.network.public_network_id):
Maru Newby81f07a02012-09-05 20:21:19 -070084 msg = ('Either tenant_networks_reachable must be "true", or '
85 'public_network_id must be defined.')
ivan-zhu1feeb382013-01-24 10:14:39 +080086 raise cls.skipException(msg)
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090087 for ext in ['router', 'security-group']:
88 if not test.is_extension_enabled(ext, 'network'):
89 msg = "%s extension not enabled." % ext
90 raise cls.skipException(msg)
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000091
92 @classmethod
93 def setup_credentials(cls):
Masayuki Igawa60ea6c52014-10-15 17:32:14 +090094 # Create no network resources for these tests.
95 cls.set_network_resources()
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000096 super(TestNetworkBasicOps, cls).setup_credentials()
Maru Newby81f07a02012-09-05 20:21:19 -070097
Yair Frieded8392f2014-01-15 17:21:35 +020098 def setUp(self):
99 super(TestNetworkBasicOps, self).setUp()
Yair Fried1fc32a12014-08-04 09:11:30 +0300100 self.keypairs = {}
101 self.servers = []
David Shrewsbury9bac3662014-08-07 15:07:01 -0400102
Yair Fried413bf2d2014-11-19 17:07:11 +0200103 def _setup_network_and_servers(self, **kwargs):
Matt Riedemann17940732015-03-13 14:18:19 +0000104 boot_with_port = kwargs.pop('boot_with_port', False)
David Shrewsbury9bac3662014-08-07 15:07:01 -0400105 self.security_group = \
106 self._create_security_group(tenant_id=self.tenant_id)
Yair Fried413bf2d2014-11-19 17:07:11 +0200107 self.network, self.subnet, self.router = self.create_networks(**kwargs)
David Shrewsbury9bac3662014-08-07 15:07:01 -0400108 self.check_networks()
109
Matt Riedemann17940732015-03-13 14:18:19 +0000110 self.port_id = None
Jordan Pittierf72a1dc2015-08-04 12:50:33 +0000111 if boot_with_port:
Matt Riedemann17940732015-03-13 14:18:19 +0000112 # create a port on the network and boot with that
113 self.port_id = self._create_port(self.network['id']).id
114
Yair Frieded8392f2014-01-15 17:21:35 +0200115 name = data_utils.rand_name('server-smoke')
Matt Riedemann17940732015-03-13 14:18:19 +0000116 server = self._create_server(name, self.network, self.port_id)
Yair Frieded8392f2014-01-15 17:21:35 +0200117 self._check_tenant_network_connectivity()
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200118
Yair Friedae0e73d2014-11-24 11:56:26 +0200119 floating_ip = self.create_floating_ip(server)
120 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Maru Newby81f07a02012-09-05 20:21:19 -0700121
Yair Frieded8392f2014-01-15 17:21:35 +0200122 def check_networks(self):
123 """
124 Checks that we see the newly created network/subnet/router via
125 checking the result of list_[networks,routers,subnets]
126 """
127
Gavin Brebner851c3502013-01-18 13:14:10 +0000128 seen_nets = self._list_networks()
129 seen_names = [n['name'] for n in seen_nets]
130 seen_ids = [n['id'] for n in seen_nets]
Yair Frieded8392f2014-01-15 17:21:35 +0200131 self.assertIn(self.network.name, seen_names)
132 self.assertIn(self.network.id, seen_ids)
133
David Shrewsbury9bac3662014-08-07 15:07:01 -0400134 if self.subnet:
135 seen_subnets = self._list_subnets()
136 seen_net_ids = [n['network_id'] for n in seen_subnets]
137 seen_subnet_ids = [n['id'] for n in seen_subnets]
138 self.assertIn(self.network.id, seen_net_ids)
139 self.assertIn(self.subnet.id, seen_subnet_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200140
David Shrewsbury9bac3662014-08-07 15:07:01 -0400141 if self.router:
142 seen_routers = self._list_routers()
143 seen_router_ids = [n['id'] for n in seen_routers]
144 seen_router_names = [n['name'] for n in seen_routers]
145 self.assertIn(self.router.name,
146 seen_router_names)
147 self.assertIn(self.router.id,
148 seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000149
Matt Riedemann17940732015-03-13 14:18:19 +0000150 def _create_server(self, name, network, port_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +0300151 keypair = self.create_keypair()
152 self.keypairs[keypair['name']] = keypair
Ken'ichi Ohmichi1b3461e2014-12-02 03:41:07 +0000153 security_groups = [{'name': self.security_group['name']}]
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700154 create_kwargs = {
Dirk Mueller8cf79722014-09-12 17:37:15 +0200155 'networks': [
156 {'uuid': network.id},
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700157 ],
Yair Fried1fc32a12014-08-04 09:11:30 +0300158 'key_name': keypair['name'],
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700159 'security_groups': security_groups,
160 }
Matt Riedemann17940732015-03-13 14:18:19 +0000161 if port_id is not None:
162 create_kwargs['networks'][0]['port'] = port_id
Giulio Fidente61cadca2013-09-24 18:33:37 +0200163 server = self.create_server(name=name, create_kwargs=create_kwargs)
Yair Fried1fc32a12014-08-04 09:11:30 +0300164 self.servers.append(server)
165 return server
166
167 def _get_server_key(self, server):
168 return self.keypairs[server['key_name']]['private_key']
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700169
Matthew Treinish2b59f842013-09-09 20:32:51 +0000170 def _check_tenant_network_connectivity(self):
Sean Dague86bd8422013-12-20 09:56:44 -0500171 ssh_login = CONF.compute.image_ssh_user
Yair Fried1fc32a12014-08-04 09:11:30 +0300172 for server in self.servers:
Matt Riedemann2d005be2014-05-27 10:52:35 -0700173 # call the common method in the parent class
174 super(TestNetworkBasicOps, self).\
175 _check_tenant_network_connectivity(
Yair Fried1fc32a12014-08-04 09:11:30 +0300176 server, ssh_login, self._get_server_key(server),
177 servers_for_debug=self.servers)
Brent Eaglesc26d4522013-12-02 13:28:49 -0500178
Alok Maurya6384bbb2014-07-13 06:44:29 -0700179 def check_public_network_connectivity(
180 self, should_connect=True, msg=None,
181 should_check_floating_ip_status=True):
Yair Fried45f92952014-06-26 05:19:19 +0300182 """Verifies connectivty to a VM via public network and floating IP,
183 and verifies floating IP has resource status is correct.
184
Yair Fried45f92952014-06-26 05:19:19 +0300185 :param should_connect: bool. determines if connectivity check is
186 negative or positive.
187 :param msg: Failure message to add to Error message. Should describe
188 the place in the test scenario where the method was called,
189 to indicate the context of the failure
Alok Maurya6384bbb2014-07-13 06:44:29 -0700190 :param should_check_floating_ip_status: bool. should status of
191 floating_ip be checked or not
Yair Fried45f92952014-06-26 05:19:19 +0300192 """
Sean Dague86bd8422013-12-20 09:56:44 -0500193 ssh_login = CONF.compute.image_ssh_user
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200194 floating_ip, server = self.floating_ip_tuple
195 ip_address = floating_ip.floating_ip_address
196 private_key = None
Yair Fried45f92952014-06-26 05:19:19 +0300197 floatingip_status = 'DOWN'
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200198 if should_connect:
Yair Fried1fc32a12014-08-04 09:11:30 +0300199 private_key = self._get_server_key(server)
Yair Fried45f92952014-06-26 05:19:19 +0300200 floatingip_status = 'ACTIVE'
Swaminathan Vasudevandc8bcdb2015-02-28 12:47:21 -0800201 # Check FloatingIP Status before initiating a connection
202 if should_check_floating_ip_status:
203 self.check_floating_ip_status(floating_ip, floatingip_status)
Matt Riedemann343305f2014-05-27 09:55:03 -0700204 # call the common method in the parent class
Yair Friedae0e73d2014-11-24 11:56:26 +0200205 super(TestNetworkBasicOps, self).check_public_network_connectivity(
Matt Riedemann343305f2014-05-27 09:55:03 -0700206 ip_address, ssh_login, private_key, should_connect, msg,
Yair Fried1fc32a12014-08-04 09:11:30 +0300207 self.servers)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000208
Yair Fried9a551c42013-12-15 14:59:34 +0200209 def _disassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200210 floating_ip, server = self.floating_ip_tuple
211 self._disassociate_floating_ip(floating_ip)
212 self.floating_ip_tuple = Floating_IP_tuple(
213 floating_ip, None)
Yair Fried9a551c42013-12-15 14:59:34 +0200214
Yair Fried05db2522013-11-18 11:02:10 +0200215 def _reassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200216 floating_ip, server = self.floating_ip_tuple
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000217 name = data_utils.rand_name('new_server-smoke')
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200218 # create a new server for the floating ip
Yair Fried1fc32a12014-08-04 09:11:30 +0300219 server = self._create_server(name, self.network)
220 self._associate_floating_ip(floating_ip, server)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200221 self.floating_ip_tuple = Floating_IP_tuple(
Yair Fried1fc32a12014-08-04 09:11:30 +0300222 floating_ip, server)
Yair Fried05db2522013-11-18 11:02:10 +0200223
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300224 def _create_new_network(self, create_gateway=False):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300225 self.new_net = self._create_network(tenant_id=self.tenant_id)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300226 if create_gateway:
227 self.new_subnet = self._create_subnet(
228 network=self.new_net)
229 else:
230 self.new_subnet = self._create_subnet(
231 network=self.new_net,
232 gateway_ip=None)
Yair Fried3097dc12014-01-26 08:46:43 +0200233
234 def _hotplug_server(self):
235 old_floating_ip, server = self.floating_ip_tuple
236 ip_address = old_floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300237 private_key = self._get_server_key(server)
Yair Fried3097dc12014-01-26 08:46:43 +0200238 ssh_client = self.get_remote_client(ip_address,
239 private_key=private_key)
240 old_nic_list = self._get_server_nics(ssh_client)
241 # get a port from a list of one item
Yair Fried1fc32a12014-08-04 09:11:30 +0300242 port_list = self._list_ports(device_id=server['id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200243 self.assertEqual(1, len(port_list))
244 old_port = port_list[0]
David Kranzb2b0c182015-02-18 13:28:19 -0500245 interface = self.interface_client.create_interface(
Ken'ichi Ohmichi9509b962015-07-07 05:30:15 +0000246 server_id=server['id'],
Ken'ichi Ohmichi12e76a12015-07-17 10:11:23 +0000247 net_id=self.new_net.id)
Yair Fried1fc32a12014-08-04 09:11:30 +0300248 self.addCleanup(self.network_client.wait_for_resource_deletion,
249 'port',
250 interface['port_id'])
251 self.addCleanup(self.delete_wrapper,
252 self.interface_client.delete_interface,
253 server['id'], interface['port_id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200254
255 def check_ports():
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200256 self.new_port_list = [port for port in
Yair Fried1fc32a12014-08-04 09:11:30 +0300257 self._list_ports(device_id=server['id'])
armando-migliaccio3820a062015-02-12 19:31:54 -0800258 if port['id'] != old_port['id']]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200259 return len(self.new_port_list) == 1
Yair Fried3097dc12014-01-26 08:46:43 +0200260
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200261 if not test.call_until_true(check_ports, CONF.network.build_timeout,
262 CONF.network.build_interval):
Matt Riedemann892094e2015-02-05 07:24:02 -0800263 raise exceptions.TimeoutException(
264 "No new port attached to the server in time (%s sec)! "
265 "Old port: %s. Number of new ports: %d" % (
266 CONF.network.build_timeout, old_port,
267 len(self.new_port_list)))
Yair Fried1fc32a12014-08-04 09:11:30 +0300268 new_port = net_resources.DeletablePort(client=self.network_client,
269 **self.new_port_list[0])
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200270
271 def check_new_nic():
272 new_nic_list = self._get_server_nics(ssh_client)
273 self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
274 return len(self.diff_list) == 1
275
276 if not test.call_until_true(check_new_nic, CONF.network.build_timeout,
277 CONF.network.build_interval):
278 raise exceptions.TimeoutException("Interface not visible on the "
279 "guest after %s sec"
280 % CONF.network.build_timeout)
281
282 num, new_nic = self.diff_list[0]
Yair Fried3097dc12014-01-26 08:46:43 +0200283 ssh_client.assign_static_ip(nic=new_nic,
284 addr=new_port.fixed_ips[0]['ip_address'])
285 ssh_client.turn_nic_on(nic=new_nic)
286
287 def _get_server_nics(self, ssh_client):
288 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
289 ipatxt = ssh_client.get_ip_list()
290 return reg.findall(ipatxt)
291
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300292 def _check_network_internal_connectivity(self, network,
293 should_connect=True):
Yair Fried3097dc12014-01-26 08:46:43 +0200294 """
295 via ssh check VM internal connectivity:
Yair Fried06552292013-11-11 12:10:09 +0200296 - ping internal gateway and DHCP port, implying in-tenant connectivity
297 pinging both, because L3 and DHCP agents might be on different nodes
Yair Fried3097dc12014-01-26 08:46:43 +0200298 """
299 floating_ip, server = self.floating_ip_tuple
300 # get internal ports' ips:
301 # get all network ports in the new network
302 internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
Yair Fried1fc32a12014-08-04 09:11:30 +0300303 self._list_ports(tenant_id=server['tenant_id'],
Yair Fried06552292013-11-11 12:10:09 +0200304 network_id=network.id)
Yair Fried3097dc12014-01-26 08:46:43 +0200305 if p['device_owner'].startswith('network'))
306
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300307 self._check_server_connectivity(floating_ip,
308 internal_ips,
309 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200310
311 def _check_network_external_connectivity(self):
312 """
313 ping public network default gateway to imply external connectivity
314
315 """
316 if not CONF.network.public_network_id:
317 msg = 'public network not defined.'
318 LOG.info(msg)
319 return
320
Andrew Boik4a3daf12015-03-27 01:59:31 -0400321 # We ping the external IP from the instance using its floating IP
322 # which is always IPv4, so we must only test connectivity to
323 # external IPv4 IPs if the external network is dualstack.
324 v4_subnets = [s for s in self._list_subnets(
325 network_id=CONF.network.public_network_id) if s['ip_version'] == 4]
326 self.assertEqual(1, len(v4_subnets),
327 "Found %d IPv4 subnets" % len(v4_subnets))
Yair Fried06552292013-11-11 12:10:09 +0200328
Andrew Boik4a3daf12015-03-27 01:59:31 -0400329 external_ips = [v4_subnets[0]['gateway_ip']]
Yair Fried06552292013-11-11 12:10:09 +0200330 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
331 external_ips)
332
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300333 def _check_server_connectivity(self, floating_ip, address_list,
334 should_connect=True):
Yair Fried3097dc12014-01-26 08:46:43 +0200335 ip_address = floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300336 private_key = self._get_server_key(self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200337 ssh_source = self._ssh_to_server(ip_address, private_key)
338
Yair Fried06552292013-11-11 12:10:09 +0200339 for remote_ip in address_list:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300340 if should_connect:
341 msg = "Timed out waiting for "
342 "%s to become reachable" % remote_ip
343 else:
344 msg = "ip address %s is reachable" % remote_ip
Yair Fried3097dc12014-01-26 08:46:43 +0200345 try:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300346 self.assertTrue(self._check_remote_connectivity
347 (ssh_source, remote_ip, should_connect),
348 msg)
Yair Fried3097dc12014-01-26 08:46:43 +0200349 except Exception:
350 LOG.exception("Unable to access {dest} via ssh to "
351 "floating-ip {src}".format(dest=remote_ip,
352 src=floating_ip))
Yair Fried3097dc12014-01-26 08:46:43 +0200353 raise
354
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900355 @test.attr(type='smoke')
Chris Hoge7579c1a2015-02-26 14:12:15 -0800356 @test.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900357 @test.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000358 def test_network_basic_ops(self):
Yair Fried3097dc12014-01-26 08:46:43 +0200359 """
360 For a freshly-booted VM with an IP address ("port") on a given
361 network:
362
363 - the Tempest host can ping the IP address. This implies, but
364 does not guarantee (see the ssh check that follows), that the
365 VM has been assigned the correct IP address and has
366 connectivity to the Tempest host.
367
368 - the Tempest host can perform key-based authentication to an
369 ssh server hosted at the IP address. This check guarantees
370 that the IP address is associated with the target VM.
371
Yair Fried3097dc12014-01-26 08:46:43 +0200372 - the Tempest host can ssh into the VM via the IP address and
373 successfully execute the following:
374
375 - ping an external IP address, implying external connectivity.
376
377 - ping an external hostname, implying that dns is correctly
378 configured.
379
380 - ping an internal IP address, implying connectivity to another
381 VM on the same network.
382
Yair Fried06552292013-11-11 12:10:09 +0200383 - detach the floating-ip from the VM and verify that it becomes
384 unreachable
385
386 - associate detached floating ip to a new VM and verify connectivity.
387 VMs are created with unique keypair so connectivity also asserts that
388 floating IP is associated with the new VM instead of the old one
389
Yair Fried45f92952014-06-26 05:19:19 +0300390 Verifies that floating IP status is updated correctly after each change
391
Yair Fried06552292013-11-11 12:10:09 +0200392
Yair Fried3097dc12014-01-26 08:46:43 +0200393 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400394 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200395 self.check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200396 self._check_network_internal_connectivity(network=self.network)
397 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200398 self._disassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200399 self.check_public_network_connectivity(should_connect=False,
400 msg="after disassociate "
401 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200402 self._reassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200403 self.check_public_network_connectivity(should_connect=True,
404 msg="after re-associate "
405 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200406
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300407 @test.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
Adam Gandelman36b71fc2015-03-12 12:24:08 -0700408 @testtools.skipIf(CONF.baremetal.driver_enabled,
409 'Baremetal relies on a shared physical network.')
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300410 @test.services('compute', 'network')
411 def test_connectivity_between_vms_on_different_networks(self):
412 """
413 For a freshly-booted VM with an IP address ("port") on a given
414 network:
415
416 - the Tempest host can ping the IP address.
417
418 - the Tempest host can ssh into the VM via the IP address and
419 successfully execute the following:
420
421 - ping an external IP address, implying external connectivity.
422
423 - ping an external hostname, implying that dns is correctly
424 configured.
425
426 - ping an internal IP address, implying connectivity to another
427 VM on the same network.
428
429 - Create another network on the same tenant with subnet, create
430 an VM on the new network.
431
432 - Ping the new VM from previous VM failed since the new network
433 was not attached to router yet.
434
435 - Attach the new network to the router, Ping the new VM from
436 previous VM succeed.
437
438 """
439 self._setup_network_and_servers()
440 self.check_public_network_connectivity(should_connect=True)
441 self._check_network_internal_connectivity(network=self.network)
442 self._check_network_external_connectivity()
443 self._create_new_network(create_gateway=True)
444 name = data_utils.rand_name('server-smoke')
445 self._create_server(name, self.new_net)
446 self._check_network_internal_connectivity(network=self.new_net,
447 should_connect=False)
448 self.new_subnet.add_to_router(self.router.id)
449 self._check_network_internal_connectivity(network=self.new_net,
450 should_connect=True)
451
Chris Hoge7579c1a2015-02-26 14:12:15 -0800452 @test.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400453 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
454 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200455 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
456 'NIC hotplug not supported for '
457 'vnic_type direct or macvtap')
Yair Fried3097dc12014-01-26 08:46:43 +0200458 @test.services('compute', 'network')
459 def test_hotplug_nic(self):
460 """
461 1. create a new network, with no gateway (to prevent overwriting VM's
462 gateway)
463 2. connect VM to new network
464 3. set static ip and bring new nic up
465 4. check VM can ping new network dhcp port
466
467 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400468 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200469 self.check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200470 self._create_new_network()
471 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200472 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700473
Chris Hoge7579c1a2015-02-26 14:12:15 -0800474 @test.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Adam Gandelmancf611212014-12-09 14:13:28 -0800475 @testtools.skipIf(CONF.baremetal.driver_enabled,
476 'Router state cannot be altered on a shared baremetal '
477 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700478 @test.services('compute', 'network')
479 def test_update_router_admin_state(self):
480 """
481 1. Check public connectivity before updating
482 admin_state_up attribute of router to False
483 2. Check public connectivity after updating
484 admin_state_up attribute of router to False
485 3. Check public connectivity after updating
486 admin_state_up attribute of router to True
487 """
488 self._setup_network_and_servers()
489 self.check_public_network_connectivity(
490 should_connect=True, msg="before updating "
491 "admin_state_up of router to False")
492 self._update_router_admin_state(self.router, False)
493 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
494 # once bug 1396310 is fixed
495
496 self.check_public_network_connectivity(
497 should_connect=False, msg="after updating "
498 "admin_state_up of router to False",
499 should_check_floating_ip_status=False)
500 self._update_router_admin_state(self.router, True)
501 self.check_public_network_connectivity(
502 should_connect=True, msg="after updating "
503 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200504
Chris Hoge7579c1a2015-02-26 14:12:15 -0800505 @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Adam Gandelman40371682015-03-03 11:27:03 -0800506 @testtools.skipIf(CONF.baremetal.driver_enabled,
507 'network isolation not available for baremetal nodes')
Yair Fried413bf2d2014-11-19 17:07:11 +0200508 @testtools.skipUnless(CONF.scenario.dhcp_client,
509 "DHCP client is not available.")
Yair Fried413bf2d2014-11-19 17:07:11 +0200510 @test.services('compute', 'network')
511 def test_subnet_details(self):
512 """Tests that subnet's extra configuration details are affecting
Adam Gandelman40371682015-03-03 11:27:03 -0800513 the VMs. This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200514
515 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
516 update in subnet requires server to actively renew its DHCP lease.
517
518 1. Configure subnet with dns nameserver
519 2. retrieve the VM's configured dns and verify it matches the one
520 configured for the subnet.
521 3. update subnet's dns
522 4. retrieve the VM's configured dns and verify it matches the new one
523 configured for the subnet.
524
525 TODO(yfried): add host_routes
526
527 any resolution check would be testing either:
528 * l3 forwarding (tested in test_network_basic_ops)
529 * Name resolution of an external DNS nameserver - out of scope for
530 Tempest
531 """
532 # this test check only updates (no actual resolution) so using
533 # arbitrary ip addresses as nameservers, instead of parsing CONF
534 initial_dns_server = '1.2.3.4'
535 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000536
537 # renewal should be immediate.
538 # Timeouts are suggested by salvatore-orlando in
539 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
540 renew_delay = CONF.network.build_interval
541 renew_timeout = CONF.network.build_timeout
542
Yair Fried413bf2d2014-11-19 17:07:11 +0200543 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
544 self.check_public_network_connectivity(should_connect=True)
545
546 floating_ip, server = self.floating_ip_tuple
547 ip_address = floating_ip.floating_ip_address
548 private_key = self._get_server_key(server)
549 ssh_client = self._ssh_to_server(ip_address, private_key)
550
armando-migliaccio424aa412015-02-22 17:55:17 -0800551 dns_servers = [initial_dns_server]
552 servers = ssh_client.get_dns_servers()
553 self.assertEqual(set(dns_servers), set(servers),
554 'Looking for servers: {trgt_serv}. '
555 'Retrieved DNS nameservers: {act_serv} '
556 'From host: {host}.'
557 .format(host=ssh_client.ssh_client.host,
558 act_serv=servers,
559 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200560
561 self.subnet.update(dns_nameservers=[alt_dns_server])
562 # asserts that Neutron DB has updated the nameservers
563 self.assertEqual([alt_dns_server], self.subnet.dns_nameservers,
564 "Failed to update subnet's nameservers")
565
Yair Friedbb0ea392015-01-19 07:26:08 +0000566 def check_new_dns_server():
567 """Server needs to renew its dhcp lease in order to get the new dns
568 definitions from subnet
569 NOTE(amuller): we are renewing the lease as part of the retry
570 because Neutron updates dnsmasq asynchronously after the
571 subnet-update API call returns.
572 """
573 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
armando-migliaccio424aa412015-02-22 17:55:17 -0800574 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000575 LOG.debug("Failed to update DNS nameservers")
576 return False
577 return True
578
579 self.assertTrue(test.call_until_true(check_new_dns_server,
580 renew_timeout,
581 renew_delay),
582 msg="DHCP renewal failed to fetch "
583 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800584
Chris Hoge7579c1a2015-02-26 14:12:15 -0800585 @test.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Adam Gandelman0a7948e2015-02-16 15:13:50 -0800586 @testtools.skipIf(CONF.baremetal.driver_enabled,
587 'admin_state of instance ports cannot be altered '
588 'for baremetal nodes')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300589 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
590 "Changing a port's admin state is not supported "
591 "by the test environment")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800592 @test.services('compute', 'network')
593 def test_update_instance_port_admin_state(self):
594 """
595 1. Check public connectivity before updating
596 admin_state_up attribute of instance port to False
597 2. Check public connectivity after updating
598 admin_state_up attribute of instance port to False
599 3. Check public connectivity after updating
600 admin_state_up attribute of instance port to True
601 """
602 self._setup_network_and_servers()
603 floating_ip, server = self.floating_ip_tuple
604 server_id = server['id']
605 port_id = self._list_ports(device_id=server_id)[0]['id']
606 self.check_public_network_connectivity(
607 should_connect=True, msg="before updating "
608 "admin_state_up of instance port to False")
609 self.network_client.update_port(port_id, admin_state_up=False)
610 self.check_public_network_connectivity(
611 should_connect=False, msg="after updating "
612 "admin_state_up of instance port to False",
613 should_check_floating_ip_status=False)
614 self.network_client.update_port(port_id, admin_state_up=True)
615 self.check_public_network_connectivity(
616 should_connect=True, msg="after updating "
617 "admin_state_up of instance port to True")
Matt Riedemann17940732015-03-13 14:18:19 +0000618
619 @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
620 @testtools.skipUnless(CONF.compute_feature_enabled.preserve_ports,
621 'Preserving ports on instance delete may not be '
622 'supported in the version of Nova being tested.')
Matt Riedemann17940732015-03-13 14:18:19 +0000623 @test.services('compute', 'network')
624 def test_preserve_preexisting_port(self):
625 """Tests that a pre-existing port provided on server boot is not
626 deleted if the server is deleted.
627
628 Nova should unbind the port from the instance on delete if the port was
629 not created by Nova as part of the boot request.
630 """
631 # Setup the network, create a port and boot the server from that port.
632 self._setup_network_and_servers(boot_with_port=True)
633 _, server = self.floating_ip_tuple
634 self.assertIsNotNone(self.port_id,
635 'Server should have been created from a '
636 'pre-existing port.')
637 # Assert the port is bound to the server.
638 port_list = self._list_ports(device_id=server['id'],
639 network_id=self.network['id'])
640 self.assertEqual(1, len(port_list),
641 'There should only be one port created for '
642 'server %s.' % server['id'])
643 self.assertEqual(self.port_id, port_list[0]['id'])
644 # Delete the server.
645 self.servers_client.delete_server(server['id'])
646 self.servers_client.wait_for_server_termination(server['id'])
647 # Assert the port still exists on the network but is unbound from
648 # the deleted server.
649 port = self.network_client.show_port(self.port_id)['port']
650 self.assertEqual(self.network['id'], port['network_id'])
651 self.assertEqual('', port['device_id'])
652 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300653
654 @test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
655 @testtools.skipIf("dvr" in CONF.network_feature_enabled.api_extensions,
656 "Router rescheduling not supported on DVR")
657 @test.services('compute', 'network')
658 def test_router_rescheduling(self):
659 """Tests that router can be removed from agent and add to a new agent.
660
661 1. Verify connectivity
662 2. Remove router from all l3-agents
663 3. Verify connectivity is down
664 4. Assign router to new l3-agent (or old one if no new agent is
665 available)
666 5. Verify connectivity
667 """
668
669 # TODO(yfried): refactor this test to be used for other agents (dhcp)
670 # as well
671
672 list_hosts = (self.admin_manager.network_client.
673 list_l3_agents_hosting_router)
674 schedule_router = (self.admin_manager.network_client.
675 add_router_to_l3_agent)
676 unschedule_router = (self.admin_manager.network_client.
677 remove_router_from_l3_agent)
678
679 agent_list = set(a["id"] for a in
680 self._list_agents(agent_type="L3 agent"))
681 self._setup_network_and_servers()
682 self.check_public_network_connectivity(should_connect=True)
683
684 # remove resource from agents
685 hosting_agents = set(a["id"] for a in
686 list_hosts(self.router.id)['agents'])
687 no_migration = agent_list == hosting_agents
688 LOG.info("Router will be assigned to {mig} hosting agent".
689 format(mig="the same" if no_migration else "a new"))
690
691 for hosting_agent in hosting_agents:
692 unschedule_router(hosting_agent, self.router.id)
693 self.assertNotIn(hosting_agent,
694 [a["id"] for a in
695 list_hosts(self.router.id)['agents']],
696 'unscheduling router failed')
697
698 # verify resource is un-functional
699 self.check_public_network_connectivity(
700 should_connect=False,
701 msg='after router unscheduling',
702 should_check_floating_ip_status=False
703 )
704
705 # schedule resource to new agent
706 target_agent = list(hosting_agents if no_migration else
707 agent_list - hosting_agents)[0]
708 schedule_router(target_agent,
709 self.router['id'])
710 self.assertEqual(
711 target_agent,
712 list_hosts(self.router.id)['agents'][0]['id'],
713 "Router failed to reschedule. Hosting agent doesn't match "
714 "target agent")
715
716 # verify resource is functional
717 self.check_public_network_connectivity(
718 should_connect=True,
719 msg='After router rescheduling')