blob: 4f74d1093bcf23007cedbb56a5560fb8070aa502 [file] [log] [blame]
Maru Newby81f07a02012-09-05 20:21:19 -07001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 OpenStack, LLC
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
Maru Newby81f07a02012-09-05 20:21:19 -070020from tempest.common.utils.data_utils import rand_name
Matthew Treinishcb569942013-08-09 16:33:44 -040021from tempest import config
Matthew Treinish2b59f842013-09-09 20:32:51 +000022from tempest.openstack.common import log as logging
Sean Dague6dbc6da2013-05-08 17:49:46 -040023from tempest.scenario import manager
Maru Newbybd360222013-04-08 22:48:50 +000024from tempest.test import attr
Matthew Treinish2153ec02013-09-09 20:57:30 +000025from tempest.test import services
Maru Newby81f07a02012-09-05 20:21:19 -070026
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
Attila Fazekasc3a095b2013-08-17 09:15:44 +020048 # TODO(mnewby) - Need to implement the following:
Maru Newby81f07a02012-09-05 20:21:19 -070049 - the Tempest host can ssh into the VM via the IP address and
50 successfully execute the following:
51
52 - ping an external IP address, implying external connectivity.
53
54 - ping an external hostname, implying that dns is correctly
55 configured.
56
57 - ping an internal IP address, implying connectivity to another
58 VM on the same network.
59
60 There are presumed to be two types of networks: tenant and
61 public. A tenant network may or may not be reachable from the
62 Tempest host. A public network is assumed to be reachable from
63 the Tempest host, and it should be possible to associate a public
64 ('floating') IP address with a tenant ('fixed') IP address to
Chang Bo Guocc1623c2013-09-13 20:11:27 -070065 facilitate external connectivity to a potentially unroutable
Maru Newby81f07a02012-09-05 20:21:19 -070066 tenant IP address.
67
68 This test suite can be configured to test network connectivity to
69 a VM via a tenant network, a public network, or both. If both
70 networking types are to be evaluated, tests that need to be
71 executed remotely on the VM (via ssh) will only be run against
72 one of the networks (to minimize test execution time).
73
74 Determine which types of networks to test as follows:
75
76 * Configure tenant network checks (via the
77 'tenant_networks_reachable' key) if the Tempest host should
78 have direct connectivity to tenant networks. This is likely to
79 be the case if Tempest is running on the same host as a
80 single-node devstack installation with IP namespaces disabled.
81
82 * Configure checks for a public network if a public network has
83 been configured prior to the test suite being run and if the
84 Tempest host should have connectivity to that public network.
85 Checking connectivity for a public network requires that a
86 value be provided for 'public_network_id'. A value can
87 optionally be provided for 'public_router_id' if tenants will
88 use a shared router to access a public network (as is likely to
89 be the case when IP namespaces are not enabled). If a value is
90 not provided for 'public_router_id', a router will be created
91 for each tenant and use the network identified by
92 'public_network_id' as its gateway.
93
94 """
95
Matthew Treinishcb569942013-08-09 16:33:44 -040096 CONF = config.TempestConfig()
97
Maru Newby81f07a02012-09-05 20:21:19 -070098 @classmethod
99 def check_preconditions(cls):
Gavin Brebner0f465a32013-03-14 13:26:09 +0000100 super(TestNetworkBasicOps, cls).check_preconditions()
Maru Newby81f07a02012-09-05 20:21:19 -0700101 cfg = cls.config.network
Maru Newby81f07a02012-09-05 20:21:19 -0700102 if not (cfg.tenant_networks_reachable or cfg.public_network_id):
103 msg = ('Either tenant_networks_reachable must be "true", or '
104 'public_network_id must be defined.')
Gavin Brebner0f465a32013-03-14 13:26:09 +0000105 cls.enabled = False
ivan-zhu1feeb382013-01-24 10:14:39 +0800106 raise cls.skipException(msg)
Maru Newby81f07a02012-09-05 20:21:19 -0700107
108 @classmethod
109 def setUpClass(cls):
110 super(TestNetworkBasicOps, cls).setUpClass()
111 cls.check_preconditions()
Maru Newby81f07a02012-09-05 20:21:19 -0700112 cls.tenant_id = cls.manager._get_identity_client(
Gavin Brebnercb7faa32013-01-30 12:01:31 +0000113 cls.config.identity.username,
114 cls.config.identity.password,
115 cls.config.identity.tenant_name).tenant_id
Maru Newby81f07a02012-09-05 20:21:19 -0700116 # TODO(mnewby) Consider looking up entities as needed instead
117 # of storing them as collections on the class.
118 cls.keypairs = {}
119 cls.security_groups = {}
120 cls.networks = []
Gavin Brebner851c3502013-01-18 13:14:10 +0000121 cls.subnets = []
122 cls.routers = []
Maru Newby81f07a02012-09-05 20:21:19 -0700123 cls.servers = []
124 cls.floating_ips = {}
125
Maru Newby81f07a02012-09-05 20:21:19 -0700126 def _get_router(self, tenant_id):
127 """Retrieve a router for the given tenant id.
128
129 If a public router has been configured, it will be returned.
130
131 If a public router has not been configured, but a public
132 network has, a tenant router will be created and returned that
133 routes traffic to the public network.
134
135 """
136 router_id = self.config.network.public_router_id
137 network_id = self.config.network.public_network_id
138 if router_id:
139 result = self.network_client.show_router(router_id)
Maru Newby207d68c2013-04-09 01:06:03 +0000140 return net_common.AttributeDict(**result['router'])
Maru Newby81f07a02012-09-05 20:21:19 -0700141 elif network_id:
142 router = self._create_router(tenant_id)
143 router.add_gateway(network_id)
144 return router
145 else:
146 raise Exception("Neither of 'public_router_id' or "
147 "'public_network_id' has been defined.")
148
Gavin Brebner0f465a32013-03-14 13:26:09 +0000149 def _create_router(self, tenant_id, namestart='router-smoke-'):
150 name = rand_name(namestart)
Maru Newby81f07a02012-09-05 20:21:19 -0700151 body = dict(
152 router=dict(
153 name=name,
154 admin_state_up=True,
155 tenant_id=tenant_id,
156 ),
157 )
158 result = self.network_client.create_router(body=body)
Maru Newby207d68c2013-04-09 01:06:03 +0000159 router = net_common.DeletableRouter(client=self.network_client,
160 **result['router'])
Maru Newby81f07a02012-09-05 20:21:19 -0700161 self.assertEqual(router.name, name)
162 self.set_resource(name, router)
163 return router
164
Matthew Treinish2b59f842013-09-09 20:32:51 +0000165 def _create_keypairs(self):
Ken'ichi Ohmichi599d1b82013-08-19 18:48:37 +0900166 self.keypairs[self.tenant_id] = self.create_keypair(
167 name=rand_name('keypair-smoke-'))
Maru Newby81f07a02012-09-05 20:21:19 -0700168
Matthew Treinish2b59f842013-09-09 20:32:51 +0000169 def _create_security_groups(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700170 self.security_groups[self.tenant_id] = self._create_security_group(
171 self.compute_client)
172
Matthew Treinish2b59f842013-09-09 20:32:51 +0000173 def _create_networks(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700174 network = self._create_network(self.tenant_id)
175 router = self._get_router(self.tenant_id)
176 subnet = self._create_subnet(network)
177 subnet.add_to_router(router.id)
178 self.networks.append(network)
Gavin Brebner851c3502013-01-18 13:14:10 +0000179 self.subnets.append(subnet)
180 self.routers.append(router)
Maru Newby81f07a02012-09-05 20:21:19 -0700181
Matthew Treinish2b59f842013-09-09 20:32:51 +0000182 def _check_networks(self):
Attila Fazekasc3a095b2013-08-17 09:15:44 +0200183 # Checks that we see the newly created network/subnet/router via
184 # checking the result of list_[networks,routers,subnets]
Gavin Brebner851c3502013-01-18 13:14:10 +0000185 seen_nets = self._list_networks()
186 seen_names = [n['name'] for n in seen_nets]
187 seen_ids = [n['id'] for n in seen_nets]
188 for mynet in self.networks:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000189 self.assertIn(mynet.name, seen_names)
190 self.assertIn(mynet.id, seen_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000191 seen_subnets = self._list_subnets()
192 seen_net_ids = [n['network_id'] for n in seen_subnets]
193 seen_subnet_ids = [n['id'] for n in seen_subnets]
194 for mynet in self.networks:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000195 self.assertIn(mynet.id, seen_net_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000196 for mysubnet in self.subnets:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000197 self.assertIn(mysubnet.id, seen_subnet_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000198 seen_routers = self._list_routers()
199 seen_router_ids = [n['id'] for n in seen_routers]
200 seen_router_names = [n['name'] for n in seen_routers]
201 for myrouter in self.routers:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000202 self.assertIn(myrouter.name, seen_router_names)
203 self.assertIn(myrouter.id, seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000204
Matthew Treinish2b59f842013-09-09 20:32:51 +0000205 def _create_servers(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700206 for i, network in enumerate(self.networks):
207 tenant_id = network.tenant_id
208 name = rand_name('server-smoke-%d-' % i)
209 keypair_name = self.keypairs[tenant_id].name
210 security_groups = [self.security_groups[tenant_id].name]
Ken'ichi Ohmichi61f272b2013-08-15 15:58:53 +0900211 create_kwargs = {
212 'nics': [
213 {'net-id': network.id},
214 ],
215 'key_name': keypair_name,
216 'security_groups': security_groups,
217 }
218 server = self.create_server(self.compute_client, name=name,
219 create_kwargs=create_kwargs)
Maru Newby81f07a02012-09-05 20:21:19 -0700220 self.servers.append(server)
221
Matthew Treinish2b59f842013-09-09 20:32:51 +0000222 def _check_tenant_network_connectivity(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700223 if not self.config.network.tenant_networks_reachable:
224 msg = 'Tenant networks not configured to be reachable.'
Matthew Treinish2b59f842013-09-09 20:32:51 +0000225 LOG.info(msg)
226 return
Maru Newbyaf292e82013-05-20 21:32:28 +0000227 # The target login is assumed to have been configured for
228 # key-based authentication by cloud-init.
229 ssh_login = self.config.compute.image_ssh_user
230 private_key = self.keypairs[self.tenant_id].private_key
Maru Newby81f07a02012-09-05 20:21:19 -0700231 for server in self.servers:
232 for net_name, ip_addresses in server.networks.iteritems():
233 for ip_address in ip_addresses:
Maru Newbyaf292e82013-05-20 21:32:28 +0000234 self._check_vm_connectivity(ip_address, ssh_login,
235 private_key)
Maru Newby81f07a02012-09-05 20:21:19 -0700236
Matthew Treinish2b59f842013-09-09 20:32:51 +0000237 def _assign_floating_ips(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700238 public_network_id = self.config.network.public_network_id
Maru Newby81f07a02012-09-05 20:21:19 -0700239 for server in self.servers:
240 floating_ip = self._create_floating_ip(server, public_network_id)
241 self.floating_ips.setdefault(server, [])
242 self.floating_ips[server].append(floating_ip)
243
Matthew Treinish2b59f842013-09-09 20:32:51 +0000244 def _check_public_network_connectivity(self):
Maru Newbyaf292e82013-05-20 21:32:28 +0000245 # The target login is assumed to have been configured for
246 # key-based authentication by cloud-init.
247 ssh_login = self.config.compute.image_ssh_user
248 private_key = self.keypairs[self.tenant_id].private_key
Maru Newby81f07a02012-09-05 20:21:19 -0700249 for server, floating_ips in self.floating_ips.iteritems():
250 for floating_ip in floating_ips:
251 ip_address = floating_ip.floating_ip_address
Maru Newbyaf292e82013-05-20 21:32:28 +0000252 self._check_vm_connectivity(ip_address, ssh_login, private_key)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000253
254 @attr(type='smoke')
Matthew Treinish2153ec02013-09-09 20:57:30 +0000255 @services('compute', 'network')
Matthew Treinish2b59f842013-09-09 20:32:51 +0000256 def test_network_basic_ops(self):
257 self._create_keypairs()
258 self._create_security_groups()
259 self._create_networks()
260 self._check_networks()
261 self._create_servers()
Matthew Treinish2b59f842013-09-09 20:32:51 +0000262 self._assign_floating_ips()
263 self._check_public_network_connectivity()
Salvatore Orlando8d076cb2013-09-16 11:00:44 -0700264 self._check_tenant_network_connectivity()