blob: c19410304c8ce9fe44c9ad564c75bf39615f2335 [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
Matt Riedemann17940732015-03-13 14:18:19 +0000111 self.port_id = None
Jordan Pittierf72a1dc2015-08-04 12:50:33 +0000112 if boot_with_port:
Matt Riedemann17940732015-03-13 14:18:19 +0000113 # create a port on the network and boot with that
114 self.port_id = self._create_port(self.network['id']).id
115
Yair Frieded8392f2014-01-15 17:21:35 +0200116 name = data_utils.rand_name('server-smoke')
Matt Riedemann17940732015-03-13 14:18:19 +0000117 server = self._create_server(name, self.network, self.port_id)
Yair Frieded8392f2014-01-15 17:21:35 +0200118 self._check_tenant_network_connectivity()
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200119
Yair Friedae0e73d2014-11-24 11:56:26 +0200120 floating_ip = self.create_floating_ip(server)
121 self.floating_ip_tuple = Floating_IP_tuple(floating_ip, server)
Maru Newby81f07a02012-09-05 20:21:19 -0700122
Yair Frieded8392f2014-01-15 17:21:35 +0200123 def check_networks(self):
124 """
125 Checks that we see the newly created network/subnet/router via
126 checking the result of list_[networks,routers,subnets]
127 """
128
Gavin Brebner851c3502013-01-18 13:14:10 +0000129 seen_nets = self._list_networks()
130 seen_names = [n['name'] for n in seen_nets]
131 seen_ids = [n['id'] for n in seen_nets]
Yair Frieded8392f2014-01-15 17:21:35 +0200132 self.assertIn(self.network.name, seen_names)
133 self.assertIn(self.network.id, seen_ids)
134
David Shrewsbury9bac3662014-08-07 15:07:01 -0400135 if self.subnet:
136 seen_subnets = self._list_subnets()
137 seen_net_ids = [n['network_id'] for n in seen_subnets]
138 seen_subnet_ids = [n['id'] for n in seen_subnets]
139 self.assertIn(self.network.id, seen_net_ids)
140 self.assertIn(self.subnet.id, seen_subnet_ids)
Yair Frieded8392f2014-01-15 17:21:35 +0200141
David Shrewsbury9bac3662014-08-07 15:07:01 -0400142 if self.router:
143 seen_routers = self._list_routers()
144 seen_router_ids = [n['id'] for n in seen_routers]
145 seen_router_names = [n['name'] for n in seen_routers]
146 self.assertIn(self.router.name,
147 seen_router_names)
148 self.assertIn(self.router.id,
149 seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000150
Matt Riedemann17940732015-03-13 14:18:19 +0000151 def _create_server(self, name, network, port_id=None):
Yair Fried1fc32a12014-08-04 09:11:30 +0300152 keypair = self.create_keypair()
153 self.keypairs[keypair['name']] = keypair
Ken'ichi Ohmichi1b3461e2014-12-02 03:41:07 +0000154 security_groups = [{'name': self.security_group['name']}]
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700155 create_kwargs = {
Dirk Mueller8cf79722014-09-12 17:37:15 +0200156 'networks': [
157 {'uuid': network.id},
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700158 ],
Yair Fried1fc32a12014-08-04 09:11:30 +0300159 'key_name': keypair['name'],
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700160 'security_groups': security_groups,
161 }
Matt Riedemann17940732015-03-13 14:18:19 +0000162 if port_id is not None:
163 create_kwargs['networks'][0]['port'] = port_id
Giulio Fidente61cadca2013-09-24 18:33:37 +0200164 server = self.create_server(name=name, create_kwargs=create_kwargs)
Yair Fried1fc32a12014-08-04 09:11:30 +0300165 self.servers.append(server)
166 return server
167
168 def _get_server_key(self, server):
169 return self.keypairs[server['key_name']]['private_key']
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700170
Matthew Treinish2b59f842013-09-09 20:32:51 +0000171 def _check_tenant_network_connectivity(self):
Sean Dague86bd8422013-12-20 09:56:44 -0500172 ssh_login = CONF.compute.image_ssh_user
Yair Fried1fc32a12014-08-04 09:11:30 +0300173 for server in self.servers:
Matt Riedemann2d005be2014-05-27 10:52:35 -0700174 # call the common method in the parent class
175 super(TestNetworkBasicOps, self).\
176 _check_tenant_network_connectivity(
Yair Fried1fc32a12014-08-04 09:11:30 +0300177 server, ssh_login, self._get_server_key(server),
178 servers_for_debug=self.servers)
Brent Eaglesc26d4522013-12-02 13:28:49 -0500179
Alok Maurya6384bbb2014-07-13 06:44:29 -0700180 def check_public_network_connectivity(
181 self, should_connect=True, msg=None,
182 should_check_floating_ip_status=True):
Yair Fried45f92952014-06-26 05:19:19 +0300183 """Verifies connectivty to a VM via public network and floating IP,
184 and verifies floating IP has resource status is correct.
185
Yair Fried45f92952014-06-26 05:19:19 +0300186 :param should_connect: bool. determines if connectivity check is
187 negative or positive.
188 :param msg: Failure message to add to Error message. Should describe
189 the place in the test scenario where the method was called,
190 to indicate the context of the failure
Alok Maurya6384bbb2014-07-13 06:44:29 -0700191 :param should_check_floating_ip_status: bool. should status of
192 floating_ip be checked or not
Yair Fried45f92952014-06-26 05:19:19 +0300193 """
Sean Dague86bd8422013-12-20 09:56:44 -0500194 ssh_login = CONF.compute.image_ssh_user
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200195 floating_ip, server = self.floating_ip_tuple
196 ip_address = floating_ip.floating_ip_address
197 private_key = None
Yair Fried45f92952014-06-26 05:19:19 +0300198 floatingip_status = 'DOWN'
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200199 if should_connect:
Yair Fried1fc32a12014-08-04 09:11:30 +0300200 private_key = self._get_server_key(server)
Yair Fried45f92952014-06-26 05:19:19 +0300201 floatingip_status = 'ACTIVE'
Swaminathan Vasudevandc8bcdb2015-02-28 12:47:21 -0800202 # Check FloatingIP Status before initiating a connection
203 if should_check_floating_ip_status:
204 self.check_floating_ip_status(floating_ip, floatingip_status)
Matt Riedemann343305f2014-05-27 09:55:03 -0700205 # call the common method in the parent class
Yair Friedae0e73d2014-11-24 11:56:26 +0200206 super(TestNetworkBasicOps, self).check_public_network_connectivity(
Matt Riedemann343305f2014-05-27 09:55:03 -0700207 ip_address, ssh_login, private_key, should_connect, msg,
Yair Fried1fc32a12014-08-04 09:11:30 +0300208 self.servers)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000209
Yair Fried9a551c42013-12-15 14:59:34 +0200210 def _disassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200211 floating_ip, server = self.floating_ip_tuple
212 self._disassociate_floating_ip(floating_ip)
213 self.floating_ip_tuple = Floating_IP_tuple(
214 floating_ip, None)
Yair Fried9a551c42013-12-15 14:59:34 +0200215
Yair Fried05db2522013-11-18 11:02:10 +0200216 def _reassociate_floating_ips(self):
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200217 floating_ip, server = self.floating_ip_tuple
Ken'ichi Ohmichi6ded8df2015-03-23 02:00:19 +0000218 name = data_utils.rand_name('new_server-smoke')
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200219 # create a new server for the floating ip
Yair Fried1fc32a12014-08-04 09:11:30 +0300220 server = self._create_server(name, self.network)
221 self._associate_floating_ip(floating_ip, server)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200222 self.floating_ip_tuple = Floating_IP_tuple(
Yair Fried1fc32a12014-08-04 09:11:30 +0300223 floating_ip, server)
Yair Fried05db2522013-11-18 11:02:10 +0200224
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300225 def _create_new_network(self, create_gateway=False):
Yair Frieddb6c9e92014-08-06 08:53:13 +0300226 self.new_net = self._create_network(tenant_id=self.tenant_id)
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300227 if create_gateway:
228 self.new_subnet = self._create_subnet(
229 network=self.new_net)
230 else:
231 self.new_subnet = self._create_subnet(
232 network=self.new_net,
233 gateway_ip=None)
Yair Fried3097dc12014-01-26 08:46:43 +0200234
235 def _hotplug_server(self):
236 old_floating_ip, server = self.floating_ip_tuple
237 ip_address = old_floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300238 private_key = self._get_server_key(server)
Yair Fried3097dc12014-01-26 08:46:43 +0200239 ssh_client = self.get_remote_client(ip_address,
240 private_key=private_key)
241 old_nic_list = self._get_server_nics(ssh_client)
242 # get a port from a list of one item
Yair Fried1fc32a12014-08-04 09:11:30 +0300243 port_list = self._list_ports(device_id=server['id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200244 self.assertEqual(1, len(port_list))
245 old_port = port_list[0]
David Kranzb2b0c182015-02-18 13:28:19 -0500246 interface = self.interface_client.create_interface(
Ken'ichi Ohmichi9509b962015-07-07 05:30:15 +0000247 server_id=server['id'],
Ken'ichi Ohmichi12e76a12015-07-17 10:11:23 +0000248 net_id=self.new_net.id)
Yair Fried1fc32a12014-08-04 09:11:30 +0300249 self.addCleanup(self.network_client.wait_for_resource_deletion,
250 'port',
251 interface['port_id'])
252 self.addCleanup(self.delete_wrapper,
253 self.interface_client.delete_interface,
254 server['id'], interface['port_id'])
Yair Fried3097dc12014-01-26 08:46:43 +0200255
256 def check_ports():
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200257 self.new_port_list = [port for port in
Yair Fried1fc32a12014-08-04 09:11:30 +0300258 self._list_ports(device_id=server['id'])
armando-migliaccio3820a062015-02-12 19:31:54 -0800259 if port['id'] != old_port['id']]
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200260 return len(self.new_port_list) == 1
Yair Fried3097dc12014-01-26 08:46:43 +0200261
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200262 if not test.call_until_true(check_ports, CONF.network.build_timeout,
263 CONF.network.build_interval):
Matt Riedemann892094e2015-02-05 07:24:02 -0800264 raise exceptions.TimeoutException(
265 "No new port attached to the server in time (%s sec)! "
266 "Old port: %s. Number of new ports: %d" % (
267 CONF.network.build_timeout, old_port,
268 len(self.new_port_list)))
Yair Fried1fc32a12014-08-04 09:11:30 +0300269 new_port = net_resources.DeletablePort(client=self.network_client,
270 **self.new_port_list[0])
Attila Fazekasa8bb3942014-08-19 09:06:30 +0200271
272 def check_new_nic():
273 new_nic_list = self._get_server_nics(ssh_client)
274 self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
275 return len(self.diff_list) == 1
276
277 if not test.call_until_true(check_new_nic, CONF.network.build_timeout,
278 CONF.network.build_interval):
279 raise exceptions.TimeoutException("Interface not visible on the "
280 "guest after %s sec"
281 % CONF.network.build_timeout)
282
283 num, new_nic = self.diff_list[0]
Yair Fried3097dc12014-01-26 08:46:43 +0200284 ssh_client.assign_static_ip(nic=new_nic,
285 addr=new_port.fixed_ips[0]['ip_address'])
286 ssh_client.turn_nic_on(nic=new_nic)
287
288 def _get_server_nics(self, ssh_client):
289 reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
290 ipatxt = ssh_client.get_ip_list()
291 return reg.findall(ipatxt)
292
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300293 def _check_network_internal_connectivity(self, network,
294 should_connect=True):
Yair Fried3097dc12014-01-26 08:46:43 +0200295 """
296 via ssh check VM internal connectivity:
Yair Fried06552292013-11-11 12:10:09 +0200297 - ping internal gateway and DHCP port, implying in-tenant connectivity
298 pinging both, because L3 and DHCP agents might be on different nodes
Yair Fried3097dc12014-01-26 08:46:43 +0200299 """
300 floating_ip, server = self.floating_ip_tuple
301 # get internal ports' ips:
302 # get all network ports in the new network
303 internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
Yair Fried1fc32a12014-08-04 09:11:30 +0300304 self._list_ports(tenant_id=server['tenant_id'],
Yair Fried06552292013-11-11 12:10:09 +0200305 network_id=network.id)
Yair Fried3097dc12014-01-26 08:46:43 +0200306 if p['device_owner'].startswith('network'))
307
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300308 self._check_server_connectivity(floating_ip,
309 internal_ips,
310 should_connect)
Yair Fried06552292013-11-11 12:10:09 +0200311
312 def _check_network_external_connectivity(self):
313 """
314 ping public network default gateway to imply external connectivity
315
316 """
317 if not CONF.network.public_network_id:
318 msg = 'public network not defined.'
319 LOG.info(msg)
320 return
321
Andrew Boik4a3daf12015-03-27 01:59:31 -0400322 # We ping the external IP from the instance using its floating IP
323 # which is always IPv4, so we must only test connectivity to
324 # external IPv4 IPs if the external network is dualstack.
325 v4_subnets = [s for s in self._list_subnets(
326 network_id=CONF.network.public_network_id) if s['ip_version'] == 4]
327 self.assertEqual(1, len(v4_subnets),
328 "Found %d IPv4 subnets" % len(v4_subnets))
Yair Fried06552292013-11-11 12:10:09 +0200329
Andrew Boik4a3daf12015-03-27 01:59:31 -0400330 external_ips = [v4_subnets[0]['gateway_ip']]
Yair Fried06552292013-11-11 12:10:09 +0200331 self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
332 external_ips)
333
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300334 def _check_server_connectivity(self, floating_ip, address_list,
335 should_connect=True):
Yair Fried3097dc12014-01-26 08:46:43 +0200336 ip_address = floating_ip.floating_ip_address
Yair Fried1fc32a12014-08-04 09:11:30 +0300337 private_key = self._get_server_key(self.floating_ip_tuple.server)
Yair Fried3097dc12014-01-26 08:46:43 +0200338 ssh_source = self._ssh_to_server(ip_address, private_key)
339
Yair Fried06552292013-11-11 12:10:09 +0200340 for remote_ip in address_list:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300341 if should_connect:
PranaliDeoreb68b9472015-08-11 00:14:50 -0700342 msg = ("Timed out waiting for %s to become "
343 "reachable") % remote_ip
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300344 else:
345 msg = "ip address %s is reachable" % remote_ip
Yair Fried3097dc12014-01-26 08:46:43 +0200346 try:
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300347 self.assertTrue(self._check_remote_connectivity
348 (ssh_source, remote_ip, should_connect),
349 msg)
Yair Fried3097dc12014-01-26 08:46:43 +0200350 except Exception:
351 LOG.exception("Unable to access {dest} via ssh to "
352 "floating-ip {src}".format(dest=remote_ip,
353 src=floating_ip))
Yair Fried3097dc12014-01-26 08:46:43 +0200354 raise
355
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900356 @test.attr(type='smoke')
Chris Hoge7579c1a2015-02-26 14:12:15 -0800357 @test.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
Yoshihiro Kaneko05670262014-01-18 19:22:44 +0900358 @test.services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000359 def test_network_basic_ops(self):
Yair Fried3097dc12014-01-26 08:46:43 +0200360 """
361 For a freshly-booted VM with an IP address ("port") on a given
362 network:
363
364 - the Tempest host can ping the IP address. This implies, but
365 does not guarantee (see the ssh check that follows), that the
366 VM has been assigned the correct IP address and has
367 connectivity to the Tempest host.
368
369 - the Tempest host can perform key-based authentication to an
370 ssh server hosted at the IP address. This check guarantees
371 that the IP address is associated with the target VM.
372
Yair Fried3097dc12014-01-26 08:46:43 +0200373 - the Tempest host can ssh into the VM via the IP address and
374 successfully execute the following:
375
376 - ping an external IP address, implying external connectivity.
377
378 - ping an external hostname, implying that dns is correctly
379 configured.
380
381 - ping an internal IP address, implying connectivity to another
382 VM on the same network.
383
Yair Fried06552292013-11-11 12:10:09 +0200384 - detach the floating-ip from the VM and verify that it becomes
385 unreachable
386
387 - associate detached floating ip to a new VM and verify connectivity.
388 VMs are created with unique keypair so connectivity also asserts that
389 floating IP is associated with the new VM instead of the old one
390
Yair Fried45f92952014-06-26 05:19:19 +0300391 Verifies that floating IP status is updated correctly after each change
392
Yair Fried06552292013-11-11 12:10:09 +0200393
Yair Fried3097dc12014-01-26 08:46:43 +0200394 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400395 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200396 self.check_public_network_connectivity(should_connect=True)
Yair Fried06552292013-11-11 12:10:09 +0200397 self._check_network_internal_connectivity(network=self.network)
398 self._check_network_external_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200399 self._disassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200400 self.check_public_network_connectivity(should_connect=False,
401 msg="after disassociate "
402 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200403 self._reassociate_floating_ips()
Yair Friedae0e73d2014-11-24 11:56:26 +0200404 self.check_public_network_connectivity(should_connect=True,
405 msg="after re-associate "
406 "floating ip")
Yair Fried3097dc12014-01-26 08:46:43 +0200407
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300408 @test.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
Adam Gandelman36b71fc2015-03-12 12:24:08 -0700409 @testtools.skipIf(CONF.baremetal.driver_enabled,
410 'Baremetal relies on a shared physical network.')
Fei Long Wang05a1c4a2015-02-02 16:58:24 +1300411 @test.services('compute', 'network')
412 def test_connectivity_between_vms_on_different_networks(self):
413 """
414 For a freshly-booted VM with an IP address ("port") on a given
415 network:
416
417 - the Tempest host can ping the IP address.
418
419 - the Tempest host can ssh into the VM via the IP address and
420 successfully execute the following:
421
422 - ping an external IP address, implying external connectivity.
423
424 - ping an external hostname, implying that dns is correctly
425 configured.
426
427 - ping an internal IP address, implying connectivity to another
428 VM on the same network.
429
430 - Create another network on the same tenant with subnet, create
431 an VM on the new network.
432
433 - Ping the new VM from previous VM failed since the new network
434 was not attached to router yet.
435
436 - Attach the new network to the router, Ping the new VM from
437 previous VM succeed.
438
439 """
440 self._setup_network_and_servers()
441 self.check_public_network_connectivity(should_connect=True)
442 self._check_network_internal_connectivity(network=self.network)
443 self._check_network_external_connectivity()
444 self._create_new_network(create_gateway=True)
445 name = data_utils.rand_name('server-smoke')
446 self._create_server(name, self.new_net)
447 self._check_network_internal_connectivity(network=self.new_net,
448 should_connect=False)
449 self.new_subnet.add_to_router(self.router.id)
450 self._check_network_internal_connectivity(network=self.new_net,
451 should_connect=True)
452
Chris Hoge7579c1a2015-02-26 14:12:15 -0800453 @test.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
Adam Gandelman7186f7a2014-07-23 09:28:56 -0400454 @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
455 'NIC hotplug not available')
Itzik Brown2ca01cd2014-12-08 12:58:20 +0200456 @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
457 'NIC hotplug not supported for '
458 'vnic_type direct or macvtap')
Yair Fried3097dc12014-01-26 08:46:43 +0200459 @test.services('compute', 'network')
460 def test_hotplug_nic(self):
461 """
462 1. create a new network, with no gateway (to prevent overwriting VM's
463 gateway)
464 2. connect VM to new network
465 3. set static ip and bring new nic up
466 4. check VM can ping new network dhcp port
467
468 """
David Shrewsbury9bac3662014-08-07 15:07:01 -0400469 self._setup_network_and_servers()
Yair Friedae0e73d2014-11-24 11:56:26 +0200470 self.check_public_network_connectivity(should_connect=True)
Yair Fried3097dc12014-01-26 08:46:43 +0200471 self._create_new_network()
472 self._hotplug_server()
Yair Fried06552292013-11-11 12:10:09 +0200473 self._check_network_internal_connectivity(network=self.new_net)
Alok Maurya6384bbb2014-07-13 06:44:29 -0700474
Chris Hoge7579c1a2015-02-26 14:12:15 -0800475 @test.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
Adam Gandelmancf611212014-12-09 14:13:28 -0800476 @testtools.skipIf(CONF.baremetal.driver_enabled,
477 'Router state cannot be altered on a shared baremetal '
478 'network')
Alok Maurya6384bbb2014-07-13 06:44:29 -0700479 @test.services('compute', 'network')
480 def test_update_router_admin_state(self):
481 """
482 1. Check public connectivity before updating
483 admin_state_up attribute of router to False
484 2. Check public connectivity after updating
485 admin_state_up attribute of router to False
486 3. Check public connectivity after updating
487 admin_state_up attribute of router to True
488 """
489 self._setup_network_and_servers()
490 self.check_public_network_connectivity(
491 should_connect=True, msg="before updating "
492 "admin_state_up of router to False")
493 self._update_router_admin_state(self.router, False)
494 # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
495 # once bug 1396310 is fixed
496
497 self.check_public_network_connectivity(
498 should_connect=False, msg="after updating "
499 "admin_state_up of router to False",
500 should_check_floating_ip_status=False)
501 self._update_router_admin_state(self.router, True)
502 self.check_public_network_connectivity(
503 should_connect=True, msg="after updating "
504 "admin_state_up of router to True")
Yair Fried413bf2d2014-11-19 17:07:11 +0200505
Chris Hoge7579c1a2015-02-26 14:12:15 -0800506 @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
Adam Gandelman40371682015-03-03 11:27:03 -0800507 @testtools.skipIf(CONF.baremetal.driver_enabled,
508 'network isolation not available for baremetal nodes')
Yair Fried413bf2d2014-11-19 17:07:11 +0200509 @testtools.skipUnless(CONF.scenario.dhcp_client,
510 "DHCP client is not available.")
Yair Fried413bf2d2014-11-19 17:07:11 +0200511 @test.services('compute', 'network')
512 def test_subnet_details(self):
513 """Tests that subnet's extra configuration details are affecting
Adam Gandelman40371682015-03-03 11:27:03 -0800514 the VMs. This test relies on non-shared, isolated tenant networks.
Yair Fried413bf2d2014-11-19 17:07:11 +0200515
516 NOTE: Neutron subnets push data to servers via dhcp-agent, so any
517 update in subnet requires server to actively renew its DHCP lease.
518
519 1. Configure subnet with dns nameserver
520 2. retrieve the VM's configured dns and verify it matches the one
521 configured for the subnet.
522 3. update subnet's dns
523 4. retrieve the VM's configured dns and verify it matches the new one
524 configured for the subnet.
525
526 TODO(yfried): add host_routes
527
528 any resolution check would be testing either:
529 * l3 forwarding (tested in test_network_basic_ops)
530 * Name resolution of an external DNS nameserver - out of scope for
531 Tempest
532 """
533 # this test check only updates (no actual resolution) so using
534 # arbitrary ip addresses as nameservers, instead of parsing CONF
535 initial_dns_server = '1.2.3.4'
536 alt_dns_server = '9.8.7.6'
Yair Friedbb0ea392015-01-19 07:26:08 +0000537
538 # renewal should be immediate.
539 # Timeouts are suggested by salvatore-orlando in
540 # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
541 renew_delay = CONF.network.build_interval
542 renew_timeout = CONF.network.build_timeout
543
Yair Fried413bf2d2014-11-19 17:07:11 +0200544 self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
545 self.check_public_network_connectivity(should_connect=True)
546
547 floating_ip, server = self.floating_ip_tuple
548 ip_address = floating_ip.floating_ip_address
549 private_key = self._get_server_key(server)
550 ssh_client = self._ssh_to_server(ip_address, private_key)
551
armando-migliaccio424aa412015-02-22 17:55:17 -0800552 dns_servers = [initial_dns_server]
553 servers = ssh_client.get_dns_servers()
554 self.assertEqual(set(dns_servers), set(servers),
555 'Looking for servers: {trgt_serv}. '
556 'Retrieved DNS nameservers: {act_serv} '
557 'From host: {host}.'
558 .format(host=ssh_client.ssh_client.host,
559 act_serv=servers,
560 trgt_serv=dns_servers))
Yair Fried413bf2d2014-11-19 17:07:11 +0200561
562 self.subnet.update(dns_nameservers=[alt_dns_server])
563 # asserts that Neutron DB has updated the nameservers
564 self.assertEqual([alt_dns_server], self.subnet.dns_nameservers,
565 "Failed to update subnet's nameservers")
566
Yair Friedbb0ea392015-01-19 07:26:08 +0000567 def check_new_dns_server():
568 """Server needs to renew its dhcp lease in order to get the new dns
569 definitions from subnet
570 NOTE(amuller): we are renewing the lease as part of the retry
571 because Neutron updates dnsmasq asynchronously after the
572 subnet-update API call returns.
573 """
574 ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
armando-migliaccio424aa412015-02-22 17:55:17 -0800575 if ssh_client.get_dns_servers() != [alt_dns_server]:
Yair Friedbb0ea392015-01-19 07:26:08 +0000576 LOG.debug("Failed to update DNS nameservers")
577 return False
578 return True
579
580 self.assertTrue(test.call_until_true(check_new_dns_server,
581 renew_timeout,
582 renew_delay),
583 msg="DHCP renewal failed to fetch "
584 "new DNS nameservers")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800585
Chris Hoge7579c1a2015-02-26 14:12:15 -0800586 @test.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
Adam Gandelman0a7948e2015-02-16 15:13:50 -0800587 @testtools.skipIf(CONF.baremetal.driver_enabled,
588 'admin_state of instance ports cannot be altered '
589 'for baremetal nodes')
Itzik Brownbeb30d32015-03-29 09:42:54 +0300590 @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
591 "Changing a port's admin state is not supported "
592 "by the test environment")
Thalabathy Venkatesan76553d82015-01-07 22:54:39 -0800593 @test.services('compute', 'network')
594 def test_update_instance_port_admin_state(self):
595 """
596 1. Check public connectivity before updating
597 admin_state_up attribute of instance port to False
598 2. Check public connectivity after updating
599 admin_state_up attribute of instance port to False
600 3. Check public connectivity after updating
601 admin_state_up attribute of instance port to True
602 """
603 self._setup_network_and_servers()
604 floating_ip, server = self.floating_ip_tuple
605 server_id = server['id']
606 port_id = self._list_ports(device_id=server_id)[0]['id']
607 self.check_public_network_connectivity(
608 should_connect=True, msg="before updating "
609 "admin_state_up of instance port to False")
610 self.network_client.update_port(port_id, admin_state_up=False)
611 self.check_public_network_connectivity(
612 should_connect=False, msg="after updating "
613 "admin_state_up of instance port to False",
614 should_check_floating_ip_status=False)
615 self.network_client.update_port(port_id, admin_state_up=True)
616 self.check_public_network_connectivity(
617 should_connect=True, msg="after updating "
618 "admin_state_up of instance port to True")
Matt Riedemann17940732015-03-13 14:18:19 +0000619
620 @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
621 @testtools.skipUnless(CONF.compute_feature_enabled.preserve_ports,
622 'Preserving ports on instance delete may not be '
623 'supported in the version of Nova being tested.')
Matt Riedemann17940732015-03-13 14:18:19 +0000624 @test.services('compute', 'network')
625 def test_preserve_preexisting_port(self):
626 """Tests that a pre-existing port provided on server boot is not
627 deleted if the server is deleted.
628
629 Nova should unbind the port from the instance on delete if the port was
630 not created by Nova as part of the boot request.
631 """
632 # Setup the network, create a port and boot the server from that port.
633 self._setup_network_and_servers(boot_with_port=True)
634 _, server = self.floating_ip_tuple
635 self.assertIsNotNone(self.port_id,
636 'Server should have been created from a '
637 'pre-existing port.')
638 # Assert the port is bound to the server.
639 port_list = self._list_ports(device_id=server['id'],
640 network_id=self.network['id'])
641 self.assertEqual(1, len(port_list),
642 'There should only be one port created for '
643 'server %s.' % server['id'])
644 self.assertEqual(self.port_id, port_list[0]['id'])
645 # Delete the server.
646 self.servers_client.delete_server(server['id'])
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000647 waiters.wait_for_server_termination(self.servers_client, server['id'])
Matt Riedemann17940732015-03-13 14:18:19 +0000648 # Assert the port still exists on the network but is unbound from
649 # the deleted server.
650 port = self.network_client.show_port(self.port_id)['port']
651 self.assertEqual(self.network['id'], port['network_id'])
652 self.assertEqual('', port['device_id'])
653 self.assertEqual('', port['device_owner'])