blob: 31ccd5beaaa530564961f815903d7847e3989cab [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
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
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000081 def skip_checks(cls):
82 super(TestNetworkBasicOps, cls).skip_checks()
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.')
ivan-zhu1feeb382013-01-24 10:14:39 +080087 raise cls.skipException(msg)
Yoshihiro Kaneko05670262014-01-18 19:22:44 +090088 for ext in ['router', 'security-group']:
89 if not test.is_extension_enabled(ext, 'network'):
90 msg = "%s extension not enabled." % ext
91 raise cls.skipException(msg)
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000092
93 @classmethod
94 def setup_credentials(cls):
Masayuki Igawa60ea6c52014-10-15 17:32:14 +090095 # Create no network resources for these tests.
96 cls.set_network_resources()
Emily Hugenbruch5e2d2a22015-02-25 21:35:45 +000097 super(TestNetworkBasicOps, cls).setup_credentials()
Maru Newby81f07a02012-09-05 20:21:19 -070098
Yair Frieded8392f2014-01-15 17:21:35 +020099 def setUp(self):
100 super(TestNetworkBasicOps, self).setUp()
Yair Fried1fc32a12014-08-04 09:11:30 +0300101 self.keypairs = {}
102 self.servers = []
David Shrewsbury9bac3662014-08-07 15:07:01 -0400103
Yair Fried413bf2d2014-11-19 17:07:11 +0200104 def _setup_network_and_servers(self, **kwargs):
Matt Riedemann17940732015-03-13 14:18:19 +0000105 boot_with_port = kwargs.pop('boot_with_port', False)
David Shrewsbury9bac3662014-08-07 15:07:01 -0400106 self.security_group = \
107 self._create_security_group(tenant_id=self.tenant_id)
Yair Fried413bf2d2014-11-19 17:07:11 +0200108 self.network, self.subnet, self.router = self.create_networks(**kwargs)
David Shrewsbury9bac3662014-08-07 15:07:01 -0400109 self.check_networks()
110
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000111 self.ports = []
Matt Riedemann17940732015-03-13 14:18:19 +0000112 self.port_id = None
Jordan Pittierf72a1dc2015-08-04 12:50:33 +0000113 if boot_with_port:
Matt Riedemann17940732015-03-13 14:18:19 +0000114 # create a port on the network and boot with that
115 self.port_id = self._create_port(self.network['id']).id
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000116 self.ports.append({'port': self.port_id})
Matt Riedemann17940732015-03-13 14:18:19 +0000117
Yair Frieded8392f2014-01-15 17:21:35 +0200118 name = data_utils.rand_name('server-smoke')
Matt Riedemann17940732015-03-13 14:18:19 +0000119 server = self._create_server(name, self.network, self.port_id)
Yair Frieded8392f2014-01-15 17:21:35 +0200120 self._check_tenant_network_connectivity()
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200121
Yair Friedae0e73d2014-11-24 11:56:26 +0200122 floating_ip = self.create_floating_ip(server)
123 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Maru Newby81f07a02012-09-05 20:21:19 -0700124
Yair Frieded8392f2014-01-15 17:21:35 +0200125 def check_networks(self):
126 """
127 Checks that we see the newly created network/subnet/router via
128 checking the result of list_[networks,routers,subnets]
129 """
130
Gavin Brebner851c3502013-01-18 13:14:10 +0000131 seen_nets = self._list_networks()
132 seen_names = [n['name'] for n in seen_nets]
133 seen_ids = [n['id'] for n in seen_nets]
Yair Frieded8392f2014-01-15 17:21:35 +0200134 self.assertIn(self.network.name, seen_names)
135 self.assertIn(self.network.id, seen_ids)
136
David Shrewsbury9bac3662014-08-07 15:07:01 -0400137 if self.subnet:
138 seen_subnets = self._list_subnets()
139 seen_net_ids = [n['network_id'] for n in seen_subnets]
140 seen_subnet_ids = [n['id'] for n in seen_subnets]
141 self.assertIn(self.network.id, seen_net_ids)
142 self.assertIn(self.subnet.id, seen_subnet_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200143
David Shrewsbury9bac3662014-08-07 15:07:01 -0400144 if self.router:
145 seen_routers = self._list_routers()
146 seen_router_ids = [n['id'] for n in seen_routers]
147 seen_router_names = [n['name'] for n in seen_routers]
148 self.assertIn(self.router.name,
149 seen_router_names)
150 self.assertIn(self.router.id,
151 seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000152
Matt Riedemann17940732015-03-13 14:18:19 +0000153 def _create_server(self, name, network, port_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +0300154 keypair = self.create_keypair()
155 self.keypairs[keypair['name']] = keypair
Ken'ichi Ohmichi1b3461e2014-12-02 03:41:07 +0000156 security_groups = [{'name': self.security_group['name']}]
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700157 create_kwargs = {
Dirk Mueller8cf79722014-09-12 17:37:15 +0200158 'networks': [
159 {'uuid': network.id},
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700160 ],
Yair Fried1fc32a12014-08-04 09:11:30 +0300161 'key_name': keypair['name'],
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700162 'security_groups': security_groups,
163 }
Matt Riedemann17940732015-03-13 14:18:19 +0000164 if port_id is not None:
165 create_kwargs['networks'][0]['port'] = port_id
Giulio Fidente61cadca2013-09-24 18:33:37 +0200166 server = self.create_server(name=name, create_kwargs=create_kwargs)
Yair Fried1fc32a12014-08-04 09:11:30 +0300167 self.servers.append(server)
168 return server
169
170 def _get_server_key(self, server):
171 return self.keypairs[server['key_name']]['private_key']
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700172
Matthew Treinish2b59f842013-09-09 20:32:51 +0000173 def _check_tenant_network_connectivity(self):
Sean Dague86bd8422013-12-20 09:56:44 -0500174 ssh_login = CONF.compute.image_ssh_user
Yair Fried1fc32a12014-08-04 09:11:30 +0300175 for server in self.servers:
Matt Riedemann2d005be2014-05-27 10:52:35 -0700176 # call the common method in the parent class
177 super(TestNetworkBasicOps, self).\
178 _check_tenant_network_connectivity(
Yair Fried1fc32a12014-08-04 09:11:30 +0300179 server, ssh_login, self._get_server_key(server),
180 servers_for_debug=self.servers)
Brent Eaglesc26d4522013-12-02 13:28:49 -0500181
Alok Maurya6384bbb2014-07-13 06:44:29 -0700182 def check_public_network_connectivity(
183 self, should_connect=True, msg=None,
184 should_check_floating_ip_status=True):
Yair Fried45f92952014-06-26 05:19:19 +0300185 """Verifies connectivty to a VM via public network and floating IP,
186 and verifies floating IP has resource status is correct.
187
Yair Fried45f92952014-06-26 05:19:19 +0300188 :param should_connect: bool. determines if connectivity check is
189 negative or positive.
190 :param msg: Failure message to add to Error message. Should describe
191 the place in the test scenario where the method was called,
192 to indicate the context of the failure
Alok Maurya6384bbb2014-07-13 06:44:29 -0700193 :param should_check_floating_ip_status: bool. should status of
194 floating_ip be checked or not
Yair Fried45f92952014-06-26 05:19:19 +0300195 """
Sean Dague86bd8422013-12-20 09:56:44 -0500196 ssh_login = CONF.compute.image_ssh_user
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200197 floating_ip, server = self.floating_ip_tuple
198 ip_address = floating_ip.floating_ip_address
199 private_key = None
Yair Fried45f92952014-06-26 05:19:19 +0300200 floatingip_status = 'DOWN'
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200201 if should_connect:
Yair Fried1fc32a12014-08-04 09:11:30 +0300202 private_key = self._get_server_key(server)
Yair Fried45f92952014-06-26 05:19:19 +0300203 floatingip_status = 'ACTIVE'
Swaminathan Vasudevandc8bcdb2015-02-28 12:47:21 -0800204 # Check FloatingIP Status before initiating a connection
205 if should_check_floating_ip_status:
206 self.check_floating_ip_status(floating_ip, floatingip_status)
Matt Riedemann343305f2014-05-27 09:55:03 -0700207 # call the common method in the parent class
Yair Friedae0e73d2014-11-24 11:56:26 +0200208 super(TestNetworkBasicOps, self).check_public_network_connectivity(
Matt Riedemann343305f2014-05-27 09:55:03 -0700209 ip_address, ssh_login, private_key, should_connect, msg,
Yair Fried1fc32a12014-08-04 09:11:30 +0300210 self.servers)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000211
Yair Fried9a551c42013-12-15 14:59:34 +0200212 def _disassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200213 floating_ip, server = self.floating_ip_tuple
214 self._disassociate_floating_ip(floating_ip)
215 self.floating_ip_tuple = Floating_IP_tuple(
216 floating_ip, None)
Yair Fried9a551c42013-12-15 14:59:34 +0200217
Yair Fried05db2522013-11-18 11:02:10 +0200218 def _reassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200219 floating_ip, server = self.floating_ip_tuple
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000220 name = data_utils.rand_name('new_server-smoke')
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200221 # create a new server for the floating ip
Yair Fried1fc32a12014-08-04 09:11:30 +0300222 server = self._create_server(name, self.network)
223 self._associate_floating_ip(floating_ip, server)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200224 self.floating_ip_tuple = Floating_IP_tuple(
Yair Fried1fc32a12014-08-04 09:11:30 +0300225 floating_ip, server)
Yair Fried05db2522013-11-18 11:02:10 +0200226
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300227 def _create_new_network(self, create_gateway=False):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300228 self.new_net = self._create_network(tenant_id=self.tenant_id)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300229 if create_gateway:
230 self.new_subnet = self._create_subnet(
231 network=self.new_net)
232 else:
233 self.new_subnet = self._create_subnet(
234 network=self.new_net,
235 gateway_ip=None)
Yair Fried3097dc12014-01-26 08:46:43 +0200236
237 def _hotplug_server(self):
238 old_floating_ip, server = self.floating_ip_tuple
239 ip_address = old_floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300240 private_key = self._get_server_key(server)
Yair Fried3097dc12014-01-26 08:46:43 +0200241 ssh_client = self.get_remote_client(ip_address,
242 private_key=private_key)
243 old_nic_list = self._get_server_nics(ssh_client)
244 # get a port from a list of one item
Yair Fried1fc32a12014-08-04 09:11:30 +0300245 port_list = self._list_ports(device_id=server['id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200246 self.assertEqual(1, len(port_list))
247 old_port = port_list[0]
David Kranzb2b0c182015-02-18 13:28:19 -0500248 interface = self.interface_client.create_interface(
Ken'ichi Ohmichi9509b962015-07-07 05:30:15 +0000249 server_id=server['id'],
ghanshyama2364f12015-08-24 15:45:37 +0900250 net_id=self.new_net.id)['interfaceAttachment']
Yair Fried1fc32a12014-08-04 09:11:30 +0300251 self.addCleanup(self.network_client.wait_for_resource_deletion,
252 'port',
253 interface['port_id'])
254 self.addCleanup(self.delete_wrapper,
255 self.interface_client.delete_interface,
256 server['id'], interface['port_id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200257
258 def check_ports():
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200259 self.new_port_list = [port for port in
Yair Fried1fc32a12014-08-04 09:11:30 +0300260 self._list_ports(device_id=server['id'])
armando-migliaccio3820a062015-02-12 19:31:54 -0800261 if port['id'] != old_port['id']]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200262 return len(self.new_port_list) == 1
Yair Fried3097dc12014-01-26 08:46:43 +0200263
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200264 if not test.call_until_true(check_ports, CONF.network.build_timeout,
265 CONF.network.build_interval):
Matt Riedemann892094e2015-02-05 07:24:02 -0800266 raise exceptions.TimeoutException(
267 "No new port attached to the server in time (%s sec)! "
268 "Old port: %s. Number of new ports: %d" % (
269 CONF.network.build_timeout, old_port,
270 len(self.new_port_list)))
Yair Fried1fc32a12014-08-04 09:11:30 +0300271 new_port = net_resources.DeletablePort(client=self.network_client,
272 **self.new_port_list[0])
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200273
274 def check_new_nic():
275 new_nic_list = self._get_server_nics(ssh_client)
276 self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
277 return len(self.diff_list) == 1
278
279 if not test.call_until_true(check_new_nic, CONF.network.build_timeout,
280 CONF.network.build_interval):
281 raise exceptions.TimeoutException("Interface not visible on the "
282 "guest after %s sec"
283 % CONF.network.build_timeout)
284
285 num, new_nic = self.diff_list[0]
Yair Fried3097dc12014-01-26 08:46:43 +0200286 ssh_client.assign_static_ip(nic=new_nic,
287 addr=new_port.fixed_ips[0]['ip_address'])
288 ssh_client.turn_nic_on(nic=new_nic)
289
290 def _get_server_nics(self, ssh_client):
291 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
292 ipatxt = ssh_client.get_ip_list()
293 return reg.findall(ipatxt)
294
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300295 def _check_network_internal_connectivity(self, network,
296 should_connect=True):
Yair Fried3097dc12014-01-26 08:46:43 +0200297 """
298 via ssh check VM internal connectivity:
Yair Fried06552292013-11-11 12:10:09 +0200299 - ping internal gateway and DHCP port, implying in-tenant connectivity
300 pinging both, because L3 and DHCP agents might be on different nodes
Yair Fried3097dc12014-01-26 08:46:43 +0200301 """
302 floating_ip, server = self.floating_ip_tuple
303 # get internal ports' ips:
304 # get all network ports in the new network
305 internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
Yair Fried1fc32a12014-08-04 09:11:30 +0300306 self._list_ports(tenant_id=server['tenant_id'],
Yair Fried06552292013-11-11 12:10:09 +0200307 network_id=network.id)
Yair Fried3097dc12014-01-26 08:46:43 +0200308 if p['device_owner'].startswith('network'))
309
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300310 self._check_server_connectivity(floating_ip,
311 internal_ips,
312 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200313
314 def _check_network_external_connectivity(self):
315 """
316 ping public network default gateway to imply external connectivity
317
318 """
319 if not CONF.network.public_network_id:
320 msg = 'public network not defined.'
321 LOG.info(msg)
322 return
323
Andrew Boik4a3daf12015-03-27 01:59:31 -0400324 # We ping the external IP from the instance using its floating IP
325 # which is always IPv4, so we must only test connectivity to
326 # external IPv4 IPs if the external network is dualstack.
327 v4_subnets = [s for s in self._list_subnets(
328 network_id=CONF.network.public_network_id) if s['ip_version'] == 4]
329 self.assertEqual(1, len(v4_subnets),
330 "Found %d IPv4 subnets" % len(v4_subnets))
Yair Fried06552292013-11-11 12:10:09 +0200331
Andrew Boik4a3daf12015-03-27 01:59:31 -0400332 external_ips = [v4_subnets[0]['gateway_ip']]
Yair Fried06552292013-11-11 12:10:09 +0200333 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
334 external_ips)
335
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300336 def _check_server_connectivity(self, floating_ip, address_list,
337 should_connect=True):
Yair Fried3097dc12014-01-26 08:46:43 +0200338 ip_address = floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300339 private_key = self._get_server_key(self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200340 ssh_source = self._ssh_to_server(ip_address, private_key)
341
Yair Fried06552292013-11-11 12:10:09 +0200342 for remote_ip in address_list:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300343 if should_connect:
PranaliDeoreb68b9472015-08-11 00:14:50 -0700344 msg = ("Timed out waiting for %s to become "
345 "reachable") % remote_ip
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300346 else:
347 msg = "ip address %s is reachable" % remote_ip
Yair Fried3097dc12014-01-26 08:46:43 +0200348 try:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300349 self.assertTrue(self._check_remote_connectivity
350 (ssh_source, remote_ip, should_connect),
351 msg)
Yair Fried3097dc12014-01-26 08:46:43 +0200352 except Exception:
353 LOG.exception("Unable to access {dest} via ssh to "
354 "floating-ip {src}".format(dest=remote_ip,
355 src=floating_ip))
Yair Fried3097dc12014-01-26 08:46:43 +0200356 raise
357
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900358 @test.attr(type='smoke')
Chris Hoge7579c1a2015-02-26 14:12:15 -0800359 @test.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900360 @test.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000361 def test_network_basic_ops(self):
Yair Fried3097dc12014-01-26 08:46:43 +0200362 """
363 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):
415 """
416 For a freshly-booted VM with an IP address ("port") on a given
417 network:
418
419 - the Tempest host can ping the IP address.
420
421 - the Tempest host can ssh into the VM via the IP address and
422 successfully execute the following:
423
424 - ping an external IP address, implying external connectivity.
425
426 - ping an external hostname, implying that dns is correctly
427 configured.
428
429 - ping an internal IP address, implying connectivity to another
430 VM on the same network.
431
432 - Create another network on the same tenant with subnet, create
433 an VM on the new network.
434
435 - Ping the new VM from previous VM failed since the new network
436 was not attached to router yet.
437
438 - Attach the new network to the router, Ping the new VM from
439 previous VM succeed.
440
441 """
442 self._setup_network_and_servers()
443 self.check_public_network_connectivity(should_connect=True)
444 self._check_network_internal_connectivity(network=self.network)
445 self._check_network_external_connectivity()
446 self._create_new_network(create_gateway=True)
447 name = data_utils.rand_name('server-smoke')
448 self._create_server(name, self.new_net)
449 self._check_network_internal_connectivity(network=self.new_net,
450 should_connect=False)
451 self.new_subnet.add_to_router(self.router.id)
452 self._check_network_internal_connectivity(network=self.new_net,
453 should_connect=True)
454
Chris Hoge7579c1a2015-02-26 14:12:15 -0800455 @test.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400456 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
457 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200458 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
459 'NIC hotplug not supported for '
460 'vnic_type direct or macvtap')
Yair Fried3097dc12014-01-26 08:46:43 +0200461 @test.services('compute', 'network')
462 def test_hotplug_nic(self):
463 """
464 1. create a new network, with no gateway (to prevent overwriting VM's
465 gateway)
466 2. connect VM to new network
467 3. set static ip and bring new nic up
468 4. check VM can ping new network dhcp port
469
470 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400471 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200472 self.check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200473 self._create_new_network()
474 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200475 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700476
Chris Hoge7579c1a2015-02-26 14:12:15 -0800477 @test.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Adam Gandelmancf611212014-12-09 14:13:28 -0800478 @testtools.skipIf(CONF.baremetal.driver_enabled,
479 'Router state cannot be altered on a shared baremetal '
480 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700481 @test.services('compute', 'network')
482 def test_update_router_admin_state(self):
483 """
484 1. Check public connectivity before updating
485 admin_state_up attribute of router to False
486 2. Check public connectivity after updating
487 admin_state_up attribute of router to False
488 3. Check public connectivity after updating
489 admin_state_up attribute of router to True
490 """
491 self._setup_network_and_servers()
492 self.check_public_network_connectivity(
493 should_connect=True, msg="before updating "
494 "admin_state_up of router to False")
495 self._update_router_admin_state(self.router, False)
496 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
497 # once bug 1396310 is fixed
498
499 self.check_public_network_connectivity(
500 should_connect=False, msg="after updating "
501 "admin_state_up of router to False",
502 should_check_floating_ip_status=False)
503 self._update_router_admin_state(self.router, True)
504 self.check_public_network_connectivity(
505 should_connect=True, msg="after updating "
506 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200507
Chris Hoge7579c1a2015-02-26 14:12:15 -0800508 @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Adam Gandelman40371682015-03-03 11:27:03 -0800509 @testtools.skipIf(CONF.baremetal.driver_enabled,
510 'network isolation not available for baremetal nodes')
Yair Fried413bf2d2014-11-19 17:07:11 +0200511 @testtools.skipUnless(CONF.scenario.dhcp_client,
512 "DHCP client is not available.")
Yair Fried413bf2d2014-11-19 17:07:11 +0200513 @test.services('compute', 'network')
514 def test_subnet_details(self):
515 """Tests that subnet's extra configuration details are affecting
Adam Gandelman40371682015-03-03 11:27:03 -0800516 the VMs. This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200517
518 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
519 update in subnet requires server to actively renew its DHCP lease.
520
521 1. Configure subnet with dns nameserver
522 2. retrieve the VM's configured dns and verify it matches the one
523 configured for the subnet.
524 3. update subnet's dns
525 4. retrieve the VM's configured dns and verify it matches the new one
526 configured for the subnet.
527
528 TODO(yfried): add host_routes
529
530 any resolution check would be testing either:
531 * l3 forwarding (tested in test_network_basic_ops)
532 * Name resolution of an external DNS nameserver - out of scope for
533 Tempest
534 """
535 # this test check only updates (no actual resolution) so using
536 # arbitrary ip addresses as nameservers, instead of parsing CONF
537 initial_dns_server = '1.2.3.4'
538 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000539
540 # renewal should be immediate.
541 # Timeouts are suggested by salvatore-orlando in
542 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
543 renew_delay = CONF.network.build_interval
544 renew_timeout = CONF.network.build_timeout
545
Yair Fried413bf2d2014-11-19 17:07:11 +0200546 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
547 self.check_public_network_connectivity(should_connect=True)
548
549 floating_ip, server = self.floating_ip_tuple
550 ip_address = floating_ip.floating_ip_address
551 private_key = self._get_server_key(server)
552 ssh_client = self._ssh_to_server(ip_address, private_key)
553
armando-migliaccio424aa412015-02-22 17:55:17 -0800554 dns_servers = [initial_dns_server]
555 servers = ssh_client.get_dns_servers()
556 self.assertEqual(set(dns_servers), set(servers),
557 'Looking for servers: {trgt_serv}. '
558 'Retrieved DNS nameservers: {act_serv} '
559 'From host: {host}.'
560 .format(host=ssh_client.ssh_client.host,
561 act_serv=servers,
562 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200563
564 self.subnet.update(dns_nameservers=[alt_dns_server])
565 # asserts that Neutron DB has updated the nameservers
566 self.assertEqual([alt_dns_server], self.subnet.dns_nameservers,
567 "Failed to update subnet's nameservers")
568
Yair Friedbb0ea392015-01-19 07:26:08 +0000569 def check_new_dns_server():
570 """Server needs to renew its dhcp lease in order to get the new dns
571 definitions from subnet
572 NOTE(amuller): we are renewing the lease as part of the retry
573 because Neutron updates dnsmasq asynchronously after the
574 subnet-update API call returns.
575 """
576 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
armando-migliaccio424aa412015-02-22 17:55:17 -0800577 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000578 LOG.debug("Failed to update DNS nameservers")
579 return False
580 return True
581
582 self.assertTrue(test.call_until_true(check_new_dns_server,
583 renew_timeout,
584 renew_delay),
585 msg="DHCP renewal failed to fetch "
586 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800587
Chris Hoge7579c1a2015-02-26 14:12:15 -0800588 @test.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Adam Gandelman0a7948e2015-02-16 15:13:50 -0800589 @testtools.skipIf(CONF.baremetal.driver_enabled,
590 'admin_state of instance ports cannot be altered '
591 'for baremetal nodes')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300592 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
593 "Changing a port's admin state is not supported "
594 "by the test environment")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800595 @test.services('compute', 'network')
596 def test_update_instance_port_admin_state(self):
597 """
598 1. Check public connectivity before updating
599 admin_state_up attribute of instance port to False
600 2. Check public connectivity after updating
601 admin_state_up attribute of instance port to False
602 3. Check public connectivity after updating
603 admin_state_up attribute of instance port to True
604 """
605 self._setup_network_and_servers()
606 floating_ip, server = self.floating_ip_tuple
607 server_id = server['id']
608 port_id = self._list_ports(device_id=server_id)[0]['id']
609 self.check_public_network_connectivity(
610 should_connect=True, msg="before updating "
611 "admin_state_up of instance port to False")
612 self.network_client.update_port(port_id, admin_state_up=False)
613 self.check_public_network_connectivity(
614 should_connect=False, msg="after updating "
615 "admin_state_up of instance port to False",
616 should_check_floating_ip_status=False)
617 self.network_client.update_port(port_id, admin_state_up=True)
618 self.check_public_network_connectivity(
619 should_connect=True, msg="after updating "
620 "admin_state_up of instance port to True")
Matt Riedemann17940732015-03-13 14:18:19 +0000621
622 @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
623 @testtools.skipUnless(CONF.compute_feature_enabled.preserve_ports,
624 'Preserving ports on instance delete may not be '
625 'supported in the version of Nova being tested.')
Matt Riedemann17940732015-03-13 14:18:19 +0000626 @test.services('compute', 'network')
627 def test_preserve_preexisting_port(self):
628 """Tests that a pre-existing port provided on server boot is not
629 deleted if the server is deleted.
630
631 Nova should unbind the port from the instance on delete if the port was
632 not created by Nova as part of the boot request.
633 """
634 # Setup the network, create a port and boot the server from that port.
635 self._setup_network_and_servers(boot_with_port=True)
636 _, server = self.floating_ip_tuple
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000637 self.assertEqual(1, len(self.ports),
638 'There should only be one port created for '
639 'server %s.' % server['id'])
640 port_id = self.ports[0]['port']
641 self.assertIsNotNone(port_id,
Matt Riedemann17940732015-03-13 14:18:19 +0000642 'Server should have been created from a '
643 'pre-existing port.')
644 # Assert the port is bound to the server.
645 port_list = self._list_ports(device_id=server['id'],
646 network_id=self.network['id'])
647 self.assertEqual(1, len(port_list),
648 'There should only be one port created for '
649 'server %s.' % server['id'])
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000650 self.assertEqual(port_id, port_list[0]['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000651 # Delete the server.
652 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000653 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000654 # Assert the port still exists on the network but is unbound from
655 # the deleted server.
Shuquan Huangb5c8beb2015-08-05 14:14:01 +0000656 port = self.network_client.show_port(port_id)['port']
Matt Riedemann17940732015-03-13 14:18:19 +0000657 self.assertEqual(self.network['id'], port['network_id'])
658 self.assertEqual('', port['device_id'])
659 self.assertEqual('', port['device_owner'])
Yair Fried564d89d2015-08-06 17:02:12 +0300660
YAMAMOTO Takashi56216312015-09-10 20:05:03 +0900661 @test.requires_ext(service='network', extension='l3_agent_scheduler')
Yair Fried564d89d2015-08-06 17:02:12 +0300662 @test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
Yair Fried564d89d2015-08-06 17:02:12 +0300663 @test.services('compute', 'network')
664 def test_router_rescheduling(self):
665 """Tests that router can be removed from agent and add to a new agent.
666
667 1. Verify connectivity
668 2. Remove router from all l3-agents
669 3. Verify connectivity is down
670 4. Assign router to new l3-agent (or old one if no new agent is
671 available)
672 5. Verify connectivity
673 """
674
675 # TODO(yfried): refactor this test to be used for other agents (dhcp)
676 # as well
677
678 list_hosts = (self.admin_manager.network_client.
679 list_l3_agents_hosting_router)
680 schedule_router = (self.admin_manager.network_client.
681 add_router_to_l3_agent)
682 unschedule_router = (self.admin_manager.network_client.
683 remove_router_from_l3_agent)
684
685 agent_list = set(a["id"] for a in
686 self._list_agents(agent_type="L3 agent"))
687 self._setup_network_and_servers()
Kevin Benton3b63aa12015-08-27 17:15:44 -0700688
689 # NOTE(kevinbenton): we have to use the admin credentials to check
690 # for the distributed flag because self.router only has a tenant view.
691 admin = self.admin_manager.network_client.show_router(self.router.id)
692 if admin['router'].get('distributed', False):
693 msg = "Rescheduling test does not apply to distributed routers."
694 raise self.skipException(msg)
695
Yair Fried564d89d2015-08-06 17:02:12 +0300696 self.check_public_network_connectivity(should_connect=True)
697
698 # remove resource from agents
699 hosting_agents = set(a["id"] for a in
700 list_hosts(self.router.id)['agents'])
701 no_migration = agent_list == hosting_agents
702 LOG.info("Router will be assigned to {mig} hosting agent".
703 format(mig="the same" if no_migration else "a new"))
704
705 for hosting_agent in hosting_agents:
706 unschedule_router(hosting_agent, self.router.id)
707 self.assertNotIn(hosting_agent,
708 [a["id"] for a in
709 list_hosts(self.router.id)['agents']],
710 'unscheduling router failed')
711
712 # verify resource is un-functional
713 self.check_public_network_connectivity(
714 should_connect=False,
715 msg='after router unscheduling',
716 should_check_floating_ip_status=False
717 )
718
719 # schedule resource to new agent
720 target_agent = list(hosting_agents if no_migration else
721 agent_list - hosting_agents)[0]
722 schedule_router(target_agent,
723 self.router['id'])
724 self.assertEqual(
725 target_agent,
726 list_hosts(self.router.id)['agents'][0]['id'],
727 "Router failed to reschedule. Hosting agent doesn't match "
728 "target agent")
729
730 # verify resource is functional
731 self.check_public_network_connectivity(
732 should_connect=True,
733 msg='After router rescheduling')