blob: 020a256e26e0dc917b5331700c39b1f98e6f8386 [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.
16
Attila Fazekasaeeeefd2013-08-06 17:01:56 +020017from tempest.common import debug
Masayuki Igawa259c1132013-10-31 17:48:44 +090018from tempest.common.utils import data_utils
Matthew Treinishcb569942013-08-09 16:33:44 -040019from tempest import config
Matthew Treinish2b59f842013-09-09 20:32:51 +000020from tempest.openstack.common import log as logging
Sean Dague6dbc6da2013-05-08 17:49:46 -040021from tempest.scenario import manager
Brent Eaglesc26d4522013-12-02 13:28:49 -050022
Maru Newbybd360222013-04-08 22:48:50 +000023from tempest.test import attr
Matthew Treinish2153ec02013-09-09 20:57:30 +000024from tempest.test import services
Maru Newby81f07a02012-09-05 20:21:19 -070025
Sean Dague86bd8422013-12-20 09:56:44 -050026CONF = config.CONF
Matthew Treinish2b59f842013-09-09 20:32:51 +000027LOG = logging.getLogger(__name__)
28
Maru Newby81f07a02012-09-05 20:21:19 -070029
Sean Dague6dbc6da2013-05-08 17:49:46 -040030class TestNetworkBasicOps(manager.NetworkScenarioTest):
Maru Newby81f07a02012-09-05 20:21:19 -070031
32 """
33 This smoke test suite assumes that Nova has been configured to
Mark McClainf2982e82013-07-06 17:48:03 -040034 boot VM's with Neutron-managed networking, and attempts to
Maru Newby81f07a02012-09-05 20:21:19 -070035 verify network connectivity as follows:
36
37 * For a freshly-booted VM with an IP address ("port") on a given network:
38
Maru Newbyaf292e82013-05-20 21:32:28 +000039 - the Tempest host can ping the IP address. This implies, but
40 does not guarantee (see the ssh check that follows), that the
41 VM has been assigned the correct IP address and has
Maru Newby81f07a02012-09-05 20:21:19 -070042 connectivity to the Tempest host.
43
Maru Newbyaf292e82013-05-20 21:32:28 +000044 - the Tempest host can perform key-based authentication to an
45 ssh server hosted at the IP address. This check guarantees
46 that the IP address is associated with the target VM.
47
Yair Fried9a551c42013-12-15 14:59:34 +020048 - detach the floating-ip from the VM and verify that it becomes
49 unreachable
50
Yair Fried05db2522013-11-18 11:02:10 +020051 - associate detached floating ip to a new VM and verify connectivity.
52 VMs are created with unique keypair so connectivity also asserts that
53 floating IP is associated with the new VM instead of the old one
54
Attila Fazekasc3a095b2013-08-17 09:15:44 +020055 # TODO(mnewby) - Need to implement the following:
Maru Newby81f07a02012-09-05 20:21:19 -070056 - the Tempest host can ssh into the VM via the IP address and
57 successfully execute the following:
58
59 - ping an external IP address, implying external connectivity.
60
61 - ping an external hostname, implying that dns is correctly
62 configured.
63
64 - ping an internal IP address, implying connectivity to another
65 VM on the same network.
66
67 There are presumed to be two types of networks: tenant and
68 public. A tenant network may or may not be reachable from the
69 Tempest host. A public network is assumed to be reachable from
70 the Tempest host, and it should be possible to associate a public
71 ('floating') IP address with a tenant ('fixed') IP address to
Chang Bo Guocc1623c2013-09-13 20:11:27 -070072 facilitate external connectivity to a potentially unroutable
Maru Newby81f07a02012-09-05 20:21:19 -070073 tenant IP address.
74
75 This test suite can be configured to test network connectivity to
76 a VM via a tenant network, a public network, or both. If both
77 networking types are to be evaluated, tests that need to be
78 executed remotely on the VM (via ssh) will only be run against
79 one of the networks (to minimize test execution time).
80
81 Determine which types of networks to test as follows:
82
83 * Configure tenant network checks (via the
84 'tenant_networks_reachable' key) if the Tempest host should
85 have direct connectivity to tenant networks. This is likely to
86 be the case if Tempest is running on the same host as a
87 single-node devstack installation with IP namespaces disabled.
88
89 * Configure checks for a public network if a public network has
90 been configured prior to the test suite being run and if the
91 Tempest host should have connectivity to that public network.
92 Checking connectivity for a public network requires that a
93 value be provided for 'public_network_id'. A value can
94 optionally be provided for 'public_router_id' if tenants will
95 use a shared router to access a public network (as is likely to
96 be the case when IP namespaces are not enabled). If a value is
97 not provided for 'public_router_id', a router will be created
98 for each tenant and use the network identified by
99 'public_network_id' as its gateway.
100
101 """
102
103 @classmethod
104 def check_preconditions(cls):
Gavin Brebner0f465a32013-03-14 13:26:09 +0000105 super(TestNetworkBasicOps, cls).check_preconditions()
Matthew Treinish6c072292014-01-29 19:15:52 +0000106 if not (CONF.network.tenant_networks_reachable
107 or CONF.network.public_network_id):
Maru Newby81f07a02012-09-05 20:21:19 -0700108 msg = ('Either tenant_networks_reachable must be "true", or '
109 'public_network_id must be defined.')
Gavin Brebner0f465a32013-03-14 13:26:09 +0000110 cls.enabled = False
ivan-zhu1feeb382013-01-24 10:14:39 +0800111 raise cls.skipException(msg)
Maru Newby81f07a02012-09-05 20:21:19 -0700112
113 @classmethod
114 def setUpClass(cls):
115 super(TestNetworkBasicOps, cls).setUpClass()
116 cls.check_preconditions()
Maru Newby81f07a02012-09-05 20:21:19 -0700117 # TODO(mnewby) Consider looking up entities as needed instead
118 # of storing them as collections on the class.
Maru Newby81f07a02012-09-05 20:21:19 -0700119 cls.security_groups = {}
120 cls.networks = []
Gavin Brebner851c3502013-01-18 13:14:10 +0000121 cls.subnets = []
122 cls.routers = []
Yair Fried05db2522013-11-18 11:02:10 +0200123 cls.servers = {}
Maru Newby81f07a02012-09-05 20:21:19 -0700124 cls.floating_ips = {}
125
Matthew Treinish2b59f842013-09-09 20:32:51 +0000126 def _create_security_groups(self):
Yair Friedeb69f3f2013-10-10 13:18:16 +0300127 self.security_groups[self.tenant_id] =\
128 self._create_security_group_neutron(tenant_id=self.tenant_id)
Maru Newby81f07a02012-09-05 20:21:19 -0700129
Matthew Treinish2b59f842013-09-09 20:32:51 +0000130 def _check_networks(self):
Attila Fazekasc3a095b2013-08-17 09:15:44 +0200131 # Checks that we see the newly created network/subnet/router via
132 # checking the result of list_[networks,routers,subnets]
Gavin Brebner851c3502013-01-18 13:14:10 +0000133 seen_nets = self._list_networks()
134 seen_names = [n['name'] for n in seen_nets]
135 seen_ids = [n['id'] for n in seen_nets]
136 for mynet in self.networks:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000137 self.assertIn(mynet.name, seen_names)
138 self.assertIn(mynet.id, seen_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000139 seen_subnets = self._list_subnets()
140 seen_net_ids = [n['network_id'] for n in seen_subnets]
141 seen_subnet_ids = [n['id'] for n in seen_subnets]
142 for mynet in self.networks:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000143 self.assertIn(mynet.id, seen_net_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000144 for mysubnet in self.subnets:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000145 self.assertIn(mysubnet.id, seen_subnet_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000146 seen_routers = self._list_routers()
147 seen_router_ids = [n['id'] for n in seen_routers]
148 seen_router_names = [n['name'] for n in seen_routers]
149 for myrouter in self.routers:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000150 self.assertIn(myrouter.name, seen_router_names)
151 self.assertIn(myrouter.id, seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000152
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700153 def _create_server(self, name, network):
154 tenant_id = network.tenant_id
Yair Fried05db2522013-11-18 11:02:10 +0200155 keypair = self.create_keypair(name='keypair-%s' % name)
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700156 security_groups = [self.security_groups[tenant_id].name]
157 create_kwargs = {
158 'nics': [
159 {'net-id': network.id},
160 ],
Yair Fried05db2522013-11-18 11:02:10 +0200161 'key_name': keypair.name,
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700162 'security_groups': security_groups,
163 }
Giulio Fidente61cadca2013-09-24 18:33:37 +0200164 server = self.create_server(name=name, create_kwargs=create_kwargs)
Yair Fried05db2522013-11-18 11:02:10 +0200165 self.servers[server] = keypair
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700166 return server
167
Matthew Treinish2b59f842013-09-09 20:32:51 +0000168 def _create_servers(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700169 for i, network in enumerate(self.networks):
Masayuki Igawa259c1132013-10-31 17:48:44 +0900170 name = data_utils.rand_name('server-smoke-%d-' % i)
Yair Fried05db2522013-11-18 11:02:10 +0200171 self._create_server(name, network)
Maru Newby81f07a02012-09-05 20:21:19 -0700172
Matthew Treinish2b59f842013-09-09 20:32:51 +0000173 def _check_tenant_network_connectivity(self):
Sean Dague86bd8422013-12-20 09:56:44 -0500174 if not CONF.network.tenant_networks_reachable:
Maru Newby81f07a02012-09-05 20:21:19 -0700175 msg = 'Tenant networks not configured to be reachable.'
Matthew Treinish2b59f842013-09-09 20:32:51 +0000176 LOG.info(msg)
177 return
Maru Newbyaf292e82013-05-20 21:32:28 +0000178 # The target login is assumed to have been configured for
179 # key-based authentication by cloud-init.
Sean Dague86bd8422013-12-20 09:56:44 -0500180 ssh_login = CONF.compute.image_ssh_user
Brent Eaglesc26d4522013-12-02 13:28:49 -0500181 try:
Yair Fried05db2522013-11-18 11:02:10 +0200182 for server, key in self.servers.items():
Brent Eaglesc26d4522013-12-02 13:28:49 -0500183 for net_name, ip_addresses in server.networks.iteritems():
184 for ip_address in ip_addresses:
185 self._check_vm_connectivity(ip_address, ssh_login,
Yair Fried05db2522013-11-18 11:02:10 +0200186 key.private_key)
Yair Frieda039f872014-01-02 12:11:10 +0200187 except Exception:
188 LOG.exception('Tenant connectivity check failed')
Salvatore Orlando728d9162014-01-19 10:33:23 -0800189 self._log_console_output(servers=self.servers.keys())
Brent Eaglesc26d4522013-12-02 13:28:49 -0500190 debug.log_ip_ns()
Yair Frieda039f872014-01-02 12:11:10 +0200191 raise
Brent Eaglesc26d4522013-12-02 13:28:49 -0500192
Yair Fried9a551c42013-12-15 14:59:34 +0200193 def _create_and_associate_floating_ips(self):
Sean Dague86bd8422013-12-20 09:56:44 -0500194 public_network_id = CONF.network.public_network_id
Yair Fried05db2522013-11-18 11:02:10 +0200195 for server in self.servers.keys():
Maru Newby81f07a02012-09-05 20:21:19 -0700196 floating_ip = self._create_floating_ip(server, public_network_id)
Yair Fried9a551c42013-12-15 14:59:34 +0200197 self.floating_ips[floating_ip] = server
Maru Newby81f07a02012-09-05 20:21:19 -0700198
Yair Frieda4b0d1d2014-01-26 13:59:54 +0200199 def _check_public_network_connectivity(self, should_connect=True,
200 msg=None):
Maru Newbyaf292e82013-05-20 21:32:28 +0000201 # The target login is assumed to have been configured for
202 # key-based authentication by cloud-init.
Sean Dague86bd8422013-12-20 09:56:44 -0500203 ssh_login = CONF.compute.image_ssh_user
Nachi Ueno4fb7ce62014-01-09 18:29:34 -0800204 LOG.debug('checking network connections')
Attila Fazekasaeeeefd2013-08-06 17:01:56 +0200205 try:
Yair Fried9a551c42013-12-15 14:59:34 +0200206 for floating_ip, server in self.floating_ips.iteritems():
207 ip_address = floating_ip.floating_ip_address
Yair Fried05db2522013-11-18 11:02:10 +0200208 private_key = None
209 if should_connect:
210 private_key = self.servers[server].private_key
Yair Fried9a551c42013-12-15 14:59:34 +0200211 self._check_vm_connectivity(ip_address,
212 ssh_login,
213 private_key,
214 should_connect=should_connect)
Yair Frieda039f872014-01-02 12:11:10 +0200215 except Exception:
Yair Frieda4b0d1d2014-01-26 13:59:54 +0200216 ex_msg = 'Public network connectivity check failed'
217 if msg:
218 ex_msg += ": " + msg
219 LOG.exception(ex_msg)
Salvatore Orlando728d9162014-01-19 10:33:23 -0800220 self._log_console_output(servers=self.servers.keys())
Attila Fazekasaeeeefd2013-08-06 17:01:56 +0200221 debug.log_ip_ns()
Yair Frieda039f872014-01-02 12:11:10 +0200222 raise
Matthew Treinish2b59f842013-09-09 20:32:51 +0000223
Yair Fried9a551c42013-12-15 14:59:34 +0200224 def _disassociate_floating_ips(self):
225 for floating_ip, server in self.floating_ips.iteritems():
226 self._disassociate_floating_ip(floating_ip)
227 self.floating_ips[floating_ip] = None
228
Yair Fried05db2522013-11-18 11:02:10 +0200229 def _reassociate_floating_ips(self):
230 network = self.networks[0]
231 for floating_ip in self.floating_ips.keys():
232 name = data_utils.rand_name('new_server-smoke-')
233 # create a new server for the floating ip
234 server = self._create_server(name, network)
235 self._associate_floating_ip(floating_ip, server)
236 self.floating_ips[floating_ip] = server
237
Matthew Treinish2b59f842013-09-09 20:32:51 +0000238 @attr(type='smoke')
Matthew Treinish2153ec02013-09-09 20:57:30 +0000239 @services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000240 def test_network_basic_ops(self):
Matthew Treinish2b59f842013-09-09 20:32:51 +0000241 self._create_security_groups()
242 self._create_networks()
243 self._check_networks()
244 self._create_servers()
Yair Fried9a551c42013-12-15 14:59:34 +0200245 self._create_and_associate_floating_ips()
Salvatore Orlando8d076cb2013-09-16 11:00:44 -0700246 self._check_tenant_network_connectivity()
Yair Fried9a551c42013-12-15 14:59:34 +0200247 self._check_public_network_connectivity(should_connect=True)
248 self._disassociate_floating_ips()
Yair Frieda4b0d1d2014-01-26 13:59:54 +0200249 self._check_public_network_connectivity(should_connect=False,
250 msg="after disassociate "
251 "floating ip")
Yair Fried05db2522013-11-18 11:02:10 +0200252 self._reassociate_floating_ips()
Yair Frieda4b0d1d2014-01-26 13:59:54 +0200253 self._check_public_network_connectivity(should_connect=True,
254 msg="after re-associate "
255 "floating ip")