blob: 930ffaeedd0c20581d44d24826e013b02c2cf9a0 [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
Maru Newby81f07a02012-09-05 20:21:19 -070025
Matthew Treinish2b59f842013-09-09 20:32:51 +000026LOG = logging.getLogger(__name__)
27
Maru Newby81f07a02012-09-05 20:21:19 -070028
Sean Dague6dbc6da2013-05-08 17:49:46 -040029class TestNetworkBasicOps(manager.NetworkScenarioTest):
Maru Newby81f07a02012-09-05 20:21:19 -070030
31 """
32 This smoke test suite assumes that Nova has been configured to
Mark McClainf2982e82013-07-06 17:48:03 -040033 boot VM's with Neutron-managed networking, and attempts to
Maru Newby81f07a02012-09-05 20:21:19 -070034 verify network connectivity as follows:
35
36 * For a freshly-booted VM with an IP address ("port") on a given network:
37
Maru Newbyaf292e82013-05-20 21:32:28 +000038 - the Tempest host can ping the IP address. This implies, but
39 does not guarantee (see the ssh check that follows), that the
40 VM has been assigned the correct IP address and has
Maru Newby81f07a02012-09-05 20:21:19 -070041 connectivity to the Tempest host.
42
Maru Newbyaf292e82013-05-20 21:32:28 +000043 - the Tempest host can perform key-based authentication to an
44 ssh server hosted at the IP address. This check guarantees
45 that the IP address is associated with the target VM.
46
Attila Fazekasc3a095b2013-08-17 09:15:44 +020047 # TODO(mnewby) - Need to implement the following:
Maru Newby81f07a02012-09-05 20:21:19 -070048 - the Tempest host can ssh into the VM via the IP address and
49 successfully execute the following:
50
51 - ping an external IP address, implying external connectivity.
52
53 - ping an external hostname, implying that dns is correctly
54 configured.
55
56 - ping an internal IP address, implying connectivity to another
57 VM on the same network.
58
59 There are presumed to be two types of networks: tenant and
60 public. A tenant network may or may not be reachable from the
61 Tempest host. A public network is assumed to be reachable from
62 the Tempest host, and it should be possible to associate a public
63 ('floating') IP address with a tenant ('fixed') IP address to
64 faciliate external connectivity to a potentially unroutable
65 tenant IP address.
66
67 This test suite can be configured to test network connectivity to
68 a VM via a tenant network, a public network, or both. If both
69 networking types are to be evaluated, tests that need to be
70 executed remotely on the VM (via ssh) will only be run against
71 one of the networks (to minimize test execution time).
72
73 Determine which types of networks to test as follows:
74
75 * Configure tenant network checks (via the
76 'tenant_networks_reachable' key) if the Tempest host should
77 have direct connectivity to tenant networks. This is likely to
78 be the case if Tempest is running on the same host as a
79 single-node devstack installation with IP namespaces disabled.
80
81 * Configure checks for a public network if a public network has
82 been configured prior to the test suite being run and if the
83 Tempest host should have connectivity to that public network.
84 Checking connectivity for a public network requires that a
85 value be provided for 'public_network_id'. A value can
86 optionally be provided for 'public_router_id' if tenants will
87 use a shared router to access a public network (as is likely to
88 be the case when IP namespaces are not enabled). If a value is
89 not provided for 'public_router_id', a router will be created
90 for each tenant and use the network identified by
91 'public_network_id' as its gateway.
92
93 """
94
Matthew Treinishcb569942013-08-09 16:33:44 -040095 CONF = config.TempestConfig()
96
Maru Newby81f07a02012-09-05 20:21:19 -070097 @classmethod
98 def check_preconditions(cls):
Gavin Brebner0f465a32013-03-14 13:26:09 +000099 super(TestNetworkBasicOps, cls).check_preconditions()
Maru Newby81f07a02012-09-05 20:21:19 -0700100 cfg = cls.config.network
Maru Newby81f07a02012-09-05 20:21:19 -0700101 if not (cfg.tenant_networks_reachable or cfg.public_network_id):
102 msg = ('Either tenant_networks_reachable must be "true", or '
103 'public_network_id must be defined.')
Gavin Brebner0f465a32013-03-14 13:26:09 +0000104 cls.enabled = False
ivan-zhu1feeb382013-01-24 10:14:39 +0800105 raise cls.skipException(msg)
Maru Newby81f07a02012-09-05 20:21:19 -0700106
107 @classmethod
108 def setUpClass(cls):
109 super(TestNetworkBasicOps, cls).setUpClass()
110 cls.check_preconditions()
Maru Newby81f07a02012-09-05 20:21:19 -0700111 cls.tenant_id = cls.manager._get_identity_client(
Gavin Brebnercb7faa32013-01-30 12:01:31 +0000112 cls.config.identity.username,
113 cls.config.identity.password,
114 cls.config.identity.tenant_name).tenant_id
Maru Newby81f07a02012-09-05 20:21:19 -0700115 # TODO(mnewby) Consider looking up entities as needed instead
116 # of storing them as collections on the class.
117 cls.keypairs = {}
118 cls.security_groups = {}
119 cls.networks = []
Gavin Brebner851c3502013-01-18 13:14:10 +0000120 cls.subnets = []
121 cls.routers = []
Maru Newby81f07a02012-09-05 20:21:19 -0700122 cls.servers = []
123 cls.floating_ips = {}
124
Maru Newby81f07a02012-09-05 20:21:19 -0700125 def _get_router(self, tenant_id):
126 """Retrieve a router for the given tenant id.
127
128 If a public router has been configured, it will be returned.
129
130 If a public router has not been configured, but a public
131 network has, a tenant router will be created and returned that
132 routes traffic to the public network.
133
134 """
135 router_id = self.config.network.public_router_id
136 network_id = self.config.network.public_network_id
137 if router_id:
138 result = self.network_client.show_router(router_id)
Maru Newby207d68c2013-04-09 01:06:03 +0000139 return net_common.AttributeDict(**result['router'])
Maru Newby81f07a02012-09-05 20:21:19 -0700140 elif network_id:
141 router = self._create_router(tenant_id)
142 router.add_gateway(network_id)
143 return router
144 else:
145 raise Exception("Neither of 'public_router_id' or "
146 "'public_network_id' has been defined.")
147
Gavin Brebner0f465a32013-03-14 13:26:09 +0000148 def _create_router(self, tenant_id, namestart='router-smoke-'):
149 name = rand_name(namestart)
Maru Newby81f07a02012-09-05 20:21:19 -0700150 body = dict(
151 router=dict(
152 name=name,
153 admin_state_up=True,
154 tenant_id=tenant_id,
155 ),
156 )
157 result = self.network_client.create_router(body=body)
Maru Newby207d68c2013-04-09 01:06:03 +0000158 router = net_common.DeletableRouter(client=self.network_client,
159 **result['router'])
Maru Newby81f07a02012-09-05 20:21:19 -0700160 self.assertEqual(router.name, name)
161 self.set_resource(name, router)
162 return router
163
Matthew Treinish2b59f842013-09-09 20:32:51 +0000164 def _create_keypairs(self):
Ken'ichi Ohmichi599d1b82013-08-19 18:48:37 +0900165 self.keypairs[self.tenant_id] = self.create_keypair(
166 name=rand_name('keypair-smoke-'))
Maru Newby81f07a02012-09-05 20:21:19 -0700167
Matthew Treinish2b59f842013-09-09 20:32:51 +0000168 def _create_security_groups(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700169 self.security_groups[self.tenant_id] = self._create_security_group(
170 self.compute_client)
171
Matthew Treinish2b59f842013-09-09 20:32:51 +0000172 def _create_networks(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700173 network = self._create_network(self.tenant_id)
174 router = self._get_router(self.tenant_id)
175 subnet = self._create_subnet(network)
176 subnet.add_to_router(router.id)
177 self.networks.append(network)
Gavin Brebner851c3502013-01-18 13:14:10 +0000178 self.subnets.append(subnet)
179 self.routers.append(router)
Maru Newby81f07a02012-09-05 20:21:19 -0700180
Matthew Treinish2b59f842013-09-09 20:32:51 +0000181 def _check_networks(self):
Attila Fazekasc3a095b2013-08-17 09:15:44 +0200182 # Checks that we see the newly created network/subnet/router via
183 # checking the result of list_[networks,routers,subnets]
Gavin Brebner851c3502013-01-18 13:14:10 +0000184 seen_nets = self._list_networks()
185 seen_names = [n['name'] for n in seen_nets]
186 seen_ids = [n['id'] for n in seen_nets]
187 for mynet in self.networks:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000188 self.assertIn(mynet.name, seen_names)
189 self.assertIn(mynet.id, seen_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000190 seen_subnets = self._list_subnets()
191 seen_net_ids = [n['network_id'] for n in seen_subnets]
192 seen_subnet_ids = [n['id'] for n in seen_subnets]
193 for mynet in self.networks:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000194 self.assertIn(mynet.id, seen_net_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000195 for mysubnet in self.subnets:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000196 self.assertIn(mysubnet.id, seen_subnet_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000197 seen_routers = self._list_routers()
198 seen_router_ids = [n['id'] for n in seen_routers]
199 seen_router_names = [n['name'] for n in seen_routers]
200 for myrouter in self.routers:
Gavin Brebner0f465a32013-03-14 13:26:09 +0000201 self.assertIn(myrouter.name, seen_router_names)
202 self.assertIn(myrouter.id, seen_router_ids)
Gavin Brebner851c3502013-01-18 13:14:10 +0000203
Matthew Treinish2b59f842013-09-09 20:32:51 +0000204 def _create_servers(self):
Maru Newby81f07a02012-09-05 20:21:19 -0700205 for i, network in enumerate(self.networks):
206 tenant_id = network.tenant_id
207 name = rand_name('server-smoke-%d-' % i)
208 keypair_name = self.keypairs[tenant_id].name
209 security_groups = [self.security_groups[tenant_id].name]
Ken'ichi Ohmichi61f272b2013-08-15 15:58:53 +0900210 create_kwargs = {
211 'nics': [
212 {'net-id': network.id},
213 ],
214 'key_name': keypair_name,
215 'security_groups': security_groups,
216 }
217 server = self.create_server(self.compute_client, name=name,
218 create_kwargs=create_kwargs)
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
Maru Newby81f07a02012-09-05 20:21:19 -0700248 for server, floating_ips in self.floating_ips.iteritems():
249 for floating_ip in floating_ips:
250 ip_address = floating_ip.floating_ip_address
Maru Newbyaf292e82013-05-20 21:32:28 +0000251 self._check_vm_connectivity(ip_address, ssh_login, private_key)
Matthew Treinish2b59f842013-09-09 20:32:51 +0000252
253 @attr(type='smoke')
254 def test_network_basic_ops(self):
255 self._create_keypairs()
256 self._create_security_groups()
257 self._create_networks()
258 self._check_networks()
259 self._create_servers()
260 self._check_tenant_network_connectivity()
261 self._assign_floating_ips()
262 self._check_public_network_connectivity()