blob: 6cd9fe8bcd08f05f46c091f003c5ab4a53f4fdc9 [file] [log] [blame]
Maru Newby81f07a02012-09-05 20:21:19 -07001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
ZhiQiang Fan39f97222013-09-20 04:49:44 +08003# Copyright 2012 OpenStack Foundation
Gavin Brebner0f465a32013-03-14 13:26:09 +00004# Copyright 2013 Hewlett-Packard Development Company, L.P.
Maru Newby81f07a02012-09-05 20:21:19 -07005# All Rights Reserved.
6#
7# Licensed under the Apache License, Version 2.0 (the "License"); you may
8# not use this file except in compliance with the License. You may obtain
9# a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16# License for the specific language governing permissions and limitations
17# under the License.
18
Sean Dague1937d092013-05-17 16:36:38 -040019from tempest.api.network import common as net_common
Attila Fazekasaeeeefd2013-08-06 17:01:56 +020020from tempest.common import debug
Maru Newby81f07a02012-09-05 20:21:19 -070021from tempest.common.utils.data_utils import rand_name
Matthew Treinishcb569942013-08-09 16:33:44 -040022from tempest import config
Matthew Treinish2b59f842013-09-09 20:32:51 +000023from tempest.openstack.common import log as logging
Sean Dague6dbc6da2013-05-08 17:49:46 -040024from tempest.scenario import manager
Maru Newbybd360222013-04-08 22:48:50 +000025from tempest.test import attr
Matthew Treinish2153ec02013-09-09 20:57:30 +000026from tempest.test import services
Maru Newby81f07a02012-09-05 20:21:19 -070027
Matthew Treinish2b59f842013-09-09 20:32:51 +000028LOG = logging.getLogger(__name__)
29
Maru Newby81f07a02012-09-05 20:21:19 -070030
Sean Dague6dbc6da2013-05-08 17:49:46 -040031class TestNetworkBasicOps(manager.NetworkScenarioTest):
Maru Newby81f07a02012-09-05 20:21:19 -070032
33 """
34 This smoke test suite assumes that Nova has been configured to
Mark McClainf2982e82013-07-06 17:48:03 -040035 boot VM's with Neutron-managed networking, and attempts to
Maru Newby81f07a02012-09-05 20:21:19 -070036 verify network connectivity as follows:
37
38 * For a freshly-booted VM with an IP address ("port") on a given network:
39
Maru Newbyaf292e82013-05-20 21:32:28 +000040 - the Tempest host can ping the IP address. This implies, but
41 does not guarantee (see the ssh check that follows), that the
42 VM has been assigned the correct IP address and has
Maru Newby81f07a02012-09-05 20:21:19 -070043 connectivity to the Tempest host.
44
Maru Newbyaf292e82013-05-20 21:32:28 +000045 - the Tempest host can perform key-based authentication to an
46 ssh server hosted at the IP address. This check guarantees
47 that the IP address is associated with the target VM.
48
Attila Fazekasc3a095b2013-08-17 09:15:44 +020049 # TODO(mnewby) - Need to implement the following:
Maru Newby81f07a02012-09-05 20:21:19 -070050 - the Tempest host can ssh into the VM via the IP address and
51 successfully execute the following:
52
53 - ping an external IP address, implying external connectivity.
54
55 - ping an external hostname, implying that dns is correctly
56 configured.
57
58 - ping an internal IP address, implying connectivity to another
59 VM on the same network.
60
61 There are presumed to be two types of networks: tenant and
62 public. A tenant network may or may not be reachable from the
63 Tempest host. A public network is assumed to be reachable from
64 the Tempest host, and it should be possible to associate a public
65 ('floating') IP address with a tenant ('fixed') IP address to
Chang Bo Guocc1623c2013-09-13 20:11:27 -070066 facilitate external connectivity to a potentially unroutable
Maru Newby81f07a02012-09-05 20:21:19 -070067 tenant IP address.
68
69 This test suite can be configured to test network connectivity to
70 a VM via a tenant network, a public network, or both. If both
71 networking types are to be evaluated, tests that need to be
72 executed remotely on the VM (via ssh) will only be run against
73 one of the networks (to minimize test execution time).
74
75 Determine which types of networks to test as follows:
76
77 * Configure tenant network checks (via the
78 'tenant_networks_reachable' key) if the Tempest host should
79 have direct connectivity to tenant networks. This is likely to
80 be the case if Tempest is running on the same host as a
81 single-node devstack installation with IP namespaces disabled.
82
83 * Configure checks for a public network if a public network has
84 been configured prior to the test suite being run and if the
85 Tempest host should have connectivity to that public network.
86 Checking connectivity for a public network requires that a
87 value be provided for 'public_network_id'. A value can
88 optionally be provided for 'public_router_id' if tenants will
89 use a shared router to access a public network (as is likely to
90 be the case when IP namespaces are not enabled). If a value is
91 not provided for 'public_router_id', a router will be created
92 for each tenant and use the network identified by
93 'public_network_id' as its gateway.
94
95 """
96
Matthew Treinishcb569942013-08-09 16:33:44 -040097 CONF = config.TempestConfig()
98
Maru Newby81f07a02012-09-05 20:21:19 -070099 @classmethod
100 def check_preconditions(cls):
Gavin Brebner0f465a32013-03-14 13:26:09 +0000101 super(TestNetworkBasicOps, cls).check_preconditions()
Maru Newby81f07a02012-09-05 20:21:19 -0700102 cfg = cls.config.network
Maru Newby81f07a02012-09-05 20:21:19 -0700103 if not (cfg.tenant_networks_reachable or cfg.public_network_id):
104 msg = ('Either tenant_networks_reachable must be "true", or '
105 'public_network_id must be defined.')
Gavin Brebner0f465a32013-03-14 13:26:09 +0000106 cls.enabled = False
ivan-zhu1feeb382013-01-24 10:14:39 +0800107 raise cls.skipException(msg)
Maru Newby81f07a02012-09-05 20:21:19 -0700108
109 @classmethod
110 def setUpClass(cls):
111 super(TestNetworkBasicOps, cls).setUpClass()
112 cls.check_preconditions()
Maru Newby81f07a02012-09-05 20:21:19 -0700113 # TODO(mnewby) Consider looking up entities as needed instead
114 # of storing them as collections on the class.
115 cls.keypairs = {}
116 cls.security_groups = {}
117 cls.networks = []
Gavin Brebner851c3502013-01-18 13:14:10 +0000118 cls.subnets = []
119 cls.routers = []
Maru Newby81f07a02012-09-05 20:21:19 -0700120 cls.servers = []
121 cls.floating_ips = {}
122
Maru Newby81f07a02012-09-05 20:21:19 -0700123 def _get_router(self, tenant_id):
124 """Retrieve a router for the given tenant id.
125
126 If a public router has been configured, it will be returned.
127
128 If a public router has not been configured, but a public
129 network has, a tenant router will be created and returned that
130 routes traffic to the public network.
131
132 """
133 router_id = self.config.network.public_router_id
134 network_id = self.config.network.public_network_id
135 if router_id:
136 result = self.network_client.show_router(router_id)
Maru Newby207d68c2013-04-09 01:06:03 +0000137 return net_common.AttributeDict(**result['router'])
Maru Newby81f07a02012-09-05 20:21:19 -0700138 elif network_id:
139 router = self._create_router(tenant_id)
140 router.add_gateway(network_id)
141 return router
142 else:
143 raise Exception("Neither of 'public_router_id' or "
144 "'public_network_id' has been defined.")
145
Gavin Brebner0f465a32013-03-14 13:26:09 +0000146 def _create_router(self, tenant_id, namestart='router-smoke-'):
147 name = rand_name(namestart)
Maru Newby81f07a02012-09-05 20:21:19 -0700148 body = dict(
149 router=dict(
150 name=name,
151 admin_state_up=True,
152 tenant_id=tenant_id,
153 ),
154 )
155 result = self.network_client.create_router(body=body)
Maru Newby207d68c2013-04-09 01:06:03 +0000156 router = net_common.DeletableRouter(client=self.network_client,
157 **result['router'])
Maru Newby81f07a02012-09-05 20:21:19 -0700158 self.assertEqual(router.name, name)
159 self.set_resource(name, router)
160 return router
161
Matthew Treinish2b59f842013-09-09 20:32:51 +0000162 def _create_keypairs(self):
Ken'ichi Ohmichi599d1b82013-08-19 18:48:37 +0900163 self.keypairs[self.tenant_id] = self.create_keypair(
164 name=rand_name('keypair-smoke-'))
Maru Newby81f07a02012-09-05 20:21:19 -0700165
Matthew Treinish2b59f842013-09-09 20:32:51 +0000166 def _create_security_groups(self):
Giulio Fidente61cadca2013-09-24 18:33:37 +0200167 self.security_groups[self.tenant_id] = self._create_security_group()
Maru Newby81f07a02012-09-05 20:21:19 -0700168
Matthew Treinish2b59f842013-09-09 20:32:51 +0000169 def _create_networks(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700170 network = self._create_network(self.tenant_id)
171 router = self._get_router(self.tenant_id)
172 subnet = self._create_subnet(network)
173 subnet.add_to_router(router.id)
174 self.networks.append(network)
Gavin Brebner851c3502013-01-18 13:14:10 +0000175 self.subnets.append(subnet)
176 self.routers.append(router)
Maru Newby81f07a02012-09-05 20:21:19 -0700177
Matthew Treinish2b59f842013-09-09 20:32:51 +0000178 def _check_networks(self):
Attila Fazekasc3a095b2013-08-17 09:15:44 +0200179 # Checks that we see the newly created network/subnet/router via
180 # checking the result of list_[networks,routers,subnets]
Gavin Brebner851c3502013-01-18 13:14:10 +0000181 seen_nets = self._list_networks()
182 seen_names = [n['name'] for n in seen_nets]
183 seen_ids = [n['id'] for n in seen_nets]
184 for mynet in self.networks:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000185 self.assertIn(mynet.name, seen_names)
186 self.assertIn(mynet.id, seen_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000187 seen_subnets = self._list_subnets()
188 seen_net_ids = [n['network_id'] for n in seen_subnets]
189 seen_subnet_ids = [n['id'] for n in seen_subnets]
190 for mynet in self.networks:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000191 self.assertIn(mynet.id, seen_net_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000192 for mysubnet in self.subnets:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000193 self.assertIn(mysubnet.id, seen_subnet_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000194 seen_routers = self._list_routers()
195 seen_router_ids = [n['id'] for n in seen_routers]
196 seen_router_names = [n['name'] for n in seen_routers]
197 for myrouter in self.routers:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000198 self.assertIn(myrouter.name, seen_router_names)
199 self.assertIn(myrouter.id, seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000200
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700201 def _create_server(self, name, network):
202 tenant_id = network.tenant_id
203 keypair_name = self.keypairs[tenant_id].name
204 security_groups = [self.security_groups[tenant_id].name]
205 create_kwargs = {
206 'nics': [
207 {'net-id': network.id},
208 ],
209 'key_name': keypair_name,
210 'security_groups': security_groups,
211 }
Giulio Fidente61cadca2013-09-24 18:33:37 +0200212 server = self.create_server(name=name, create_kwargs=create_kwargs)
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700213 return server
214
Matthew Treinish2b59f842013-09-09 20:32:51 +0000215 def _create_servers(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700216 for i, network in enumerate(self.networks):
Maru Newby81f07a02012-09-05 20:21:19 -0700217 name = rand_name('server-smoke-%d-' % i)
Salvatore Orlando5ed3b6e2013-09-17 01:27:26 -0700218 server = self._create_server(name, network)
Maru Newby81f07a02012-09-05 20:21:19 -0700219 self.servers.append(server)
220
Matthew Treinish2b59f842013-09-09 20:32:51 +0000221 def _check_tenant_network_connectivity(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700222 if not self.config.network.tenant_networks_reachable:
223 msg = 'Tenant networks not configured to be reachable.'
Matthew Treinish2b59f842013-09-09 20:32:51 +0000224 LOG.info(msg)
225 return
Maru Newbyaf292e82013-05-20 21:32:28 +0000226 # The target login is assumed to have been configured for
227 # key-based authentication by cloud-init.
228 ssh_login = self.config.compute.image_ssh_user
229 private_key = self.keypairs[self.tenant_id].private_key
Maru Newby81f07a02012-09-05 20:21:19 -0700230 for server in self.servers:
231 for net_name, ip_addresses in server.networks.iteritems():
232 for ip_address in ip_addresses:
Maru Newbyaf292e82013-05-20 21:32:28 +0000233 self._check_vm_connectivity(ip_address, ssh_login,
234 private_key)
Maru Newby81f07a02012-09-05 20:21:19 -0700235
Matthew Treinish2b59f842013-09-09 20:32:51 +0000236 def _assign_floating_ips(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700237 public_network_id = self.config.network.public_network_id
Maru Newby81f07a02012-09-05 20:21:19 -0700238 for server in self.servers:
239 floating_ip = self._create_floating_ip(server, public_network_id)
240 self.floating_ips.setdefault(server, [])
241 self.floating_ips[server].append(floating_ip)
242
Matthew Treinish2b59f842013-09-09 20:32:51 +0000243 def _check_public_network_connectivity(self):
Maru Newbyaf292e82013-05-20 21:32:28 +0000244 # The target login is assumed to have been configured for
245 # key-based authentication by cloud-init.
246 ssh_login = self.config.compute.image_ssh_user
247 private_key = self.keypairs[self.tenant_id].private_key
Attila Fazekasaeeeefd2013-08-06 17:01:56 +0200248 try:
249 for server, floating_ips in self.floating_ips.iteritems():
250 for floating_ip in floating_ips:
251 ip_address = floating_ip.floating_ip_address
252 self._check_vm_connectivity(ip_address,
253 ssh_login,
254 private_key)
255 except Exception as exc:
256 LOG.exception(exc)
257 debug.log_ip_ns()
258 raise exc
Matthew Treinish2b59f842013-09-09 20:32:51 +0000259
260 @attr(type='smoke')
Matthew Treinish2153ec02013-09-09 20:57:30 +0000261 @services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000262 def test_network_basic_ops(self):
263 self._create_keypairs()
264 self._create_security_groups()
265 self._create_networks()
266 self._check_networks()
267 self._create_servers()
Matthew Treinish2b59f842013-09-09 20:32:51 +0000268 self._assign_floating_ips()
269 self._check_public_network_connectivity()
Salvatore Orlando8d076cb2013-09-16 11:00:44 -0700270 self._check_tenant_network_connectivity()