blob: f7a3d6f824cd57770e45e86e71ca564bb6988b10 [file] [log] [blame]
Elena Ezhovaa5105e62013-11-26 20:46:52 +04001# Copyright 2014 Mirantis.inc
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16import time
17import urllib
18
19from tempest.api.network import common as net_common
Elena Ezhovaa5105e62013-11-26 20:46:52 +040020from tempest.common.utils import data_utils
21from tempest import config
22from tempest import exceptions
23from tempest.scenario import manager
24from tempest import test
25
26config = config.CONF
27
28
29class TestLoadBalancerBasic(manager.NetworkScenarioTest):
30
31 """
32 This test checks basic load balancing.
33
34 The following is the scenario outline:
35 1. Create an instance
36 2. SSH to the instance and start two servers
37 3. Create a load balancer with two members and with ROUND_ROBIN algorithm
38 associate the VIP with a floating ip
39 4. Send 10 requests to the floating ip and check that they are shared
40 between the two servers and that both of them get equal portions
41 of the requests
42 """
43
44 @classmethod
45 def check_preconditions(cls):
46 super(TestLoadBalancerBasic, cls).check_preconditions()
47 cfg = config.network
48 if not test.is_extension_enabled('lbaas', 'network'):
49 msg = 'LBaaS Extension is not enabled'
50 cls.enabled = False
51 raise cls.skipException(msg)
52 if not (cfg.tenant_networks_reachable or cfg.public_network_id):
53 msg = ('Either tenant_networks_reachable must be "true", or '
54 'public_network_id must be defined.')
55 cls.enabled = False
56 raise cls.skipException(msg)
57
58 @classmethod
59 def setUpClass(cls):
60 super(TestLoadBalancerBasic, cls).setUpClass()
61 cls.check_preconditions()
62 cls.security_groups = {}
Elena Ezhovaa5105e62013-11-26 20:46:52 +040063 cls.servers_keypairs = {}
Elena Ezhovaa5105e62013-11-26 20:46:52 +040064 cls.members = []
Elena Ezhovaa5105e62013-11-26 20:46:52 +040065 cls.floating_ips = {}
Elena Ezhova91531102014-02-07 17:25:58 +040066 cls.server_ip = None
67 cls.vip_ip = None
Elena Ezhovaa5105e62013-11-26 20:46:52 +040068 cls.port1 = 80
69 cls.port2 = 88
70
71 def _create_security_groups(self):
72 self.security_groups[self.tenant_id] =\
73 self._create_security_group_neutron(tenant_id=self.tenant_id)
74
75 def _create_server(self):
76 tenant_id = self.tenant_id
77 name = data_utils.rand_name("smoke_server-")
78 keypair = self.create_keypair(name='keypair-%s' % name)
79 security_groups = [self.security_groups[tenant_id].name]
Elena Ezhova91531102014-02-07 17:25:58 +040080 net = self._list_networks(tenant_id=self.tenant_id)[0]
Yair Fried2d2f3fe2014-02-24 16:19:20 +020081 create_kwargs = {
82 'nics': [
Elena Ezhova91531102014-02-07 17:25:58 +040083 {'net-id': net['id']},
Yair Fried2d2f3fe2014-02-24 16:19:20 +020084 ],
85 'key_name': keypair.name,
86 'security_groups': security_groups,
87 }
88 server = self.create_server(name=name,
89 create_kwargs=create_kwargs)
90 self.servers_keypairs[server] = keypair
Elena Ezhova91531102014-02-07 17:25:58 +040091 if (config.network.public_network_id and not
92 config.network.tenant_networks_reachable):
93 public_network_id = config.network.public_network_id
94 floating_ip = self._create_floating_ip(
95 server, public_network_id)
96 self.floating_ips[floating_ip] = server
97 self.server_ip = floating_ip.floating_ip_address
98 else:
99 self.server_ip = server.networks[net['name']][0]
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400100 self.assertTrue(self.servers_keypairs)
Elena Ezhova91531102014-02-07 17:25:58 +0400101 return server
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400102
Elena Ezhova91531102014-02-07 17:25:58 +0400103 def _start_servers(self, server):
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400104 """
105 1. SSH to the instance
Elena Ezhova91531102014-02-07 17:25:58 +0400106 2. Start two http backends listening on ports 80 and 88 respectively
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400107 """
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400108
Elena Ezhova91531102014-02-07 17:25:58 +0400109 private_key = self.servers_keypairs[server].private_key
110 ssh_client = self.get_remote_client(
111 server_or_ip=self.server_ip,
112 private_key=private_key).ssh_client
113 start_server = "while true; do echo -e 'HTTP/1.0 200 OK\r\n\r\n" \
114 "%(server)s' | sudo nc -l -p %(port)s ; done &"
115 cmd = start_server % {'server': 'server1',
116 'port': self.port1}
117 ssh_client.exec_command(cmd)
118 cmd = start_server % {'server': 'server2',
119 'port': self.port2}
120 ssh_client.exec_command(cmd)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400121
122 def _check_connection(self, check_ip):
123 def try_connect(ip):
124 try:
125 urllib.urlopen("http://{0}/".format(ip))
126 return True
127 except IOError:
128 return False
129 timeout = config.compute.ping_timeout
130 timer = 0
131 while not try_connect(check_ip):
132 time.sleep(1)
133 timer += 1
134 if timer >= timeout:
135 message = "Timed out trying to connect to %s" % check_ip
136 raise exceptions.TimeoutException(message)
137
138 def _create_pool(self):
139 """Create a pool with ROUND_ROBIN algorithm."""
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200140 # get tenant subnet and verify there's only one
141 subnet = self._list_subnets(tenant_id=self.tenant_id)[0]
142 self.subnet = net_common.DeletableSubnet(client=self.network_client,
Elena Ezhova91531102014-02-07 17:25:58 +0400143 **subnet)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200144 self.pool = super(TestLoadBalancerBasic, self)._create_pool(
145 'ROUND_ROBIN',
146 'HTTP',
147 self.subnet.id)
148 self.assertTrue(self.pool)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400149
Elena Ezhova91531102014-02-07 17:25:58 +0400150 def _create_members(self, server_ids):
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400151 """
152 Create two members.
153
154 In case there is only one server, create both members with the same ip
155 but with different ports to listen on.
156 """
157 servers = self.compute_client.servers.list()
158 for server in servers:
159 if server.id in server_ids:
Elena Ezhova91531102014-02-07 17:25:58 +0400160 ip = self.server_ip
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200161 pool_id = self.pool.id
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400162 if len(set(server_ids)) == 1 or len(servers) == 1:
163 member1 = self._create_member(ip, self.port1, pool_id)
164 member2 = self._create_member(ip, self.port2, pool_id)
165 self.members.extend([member1, member2])
166 else:
167 member = self._create_member(ip, self.port1, pool_id)
168 self.members.append(member)
169 self.assertTrue(self.members)
170
171 def _assign_floating_ip_to_vip(self, vip):
172 public_network_id = config.network.public_network_id
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200173 port_id = vip.port_id
Yair Frieda2e3b2c2014-02-17 10:56:10 +0200174 floating_ip = self._create_floating_ip(vip, public_network_id,
175 port_id=port_id)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200176 self.floating_ips.setdefault(vip.id, [])
177 self.floating_ips[vip.id].append(floating_ip)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400178
179 def _create_load_balancer(self):
180 self._create_pool()
Elena Ezhova91531102014-02-07 17:25:58 +0400181 self._create_members([self.servers_keypairs.keys()[0].id])
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200182 subnet_id = self.subnet.id
183 pool_id = self.pool.id
184 self.vip = super(TestLoadBalancerBasic, self)._create_vip('HTTP', 80,
185 subnet_id,
186 pool_id)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400187 self._status_timeout(NeutronRetriever(self.network_client,
188 self.network_client.vip_path,
189 net_common.DeletableVip),
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200190 self.vip.id,
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400191 expected_status='ACTIVE')
Elena Ezhova91531102014-02-07 17:25:58 +0400192 if (config.network.public_network_id and not
193 config.network.tenant_networks_reachable):
194 self._assign_floating_ip_to_vip(self.vip)
195 self.vip_ip = self.floating_ips[
196 self.vip.id][0]['floating_ip_address']
197 else:
198 self.vip_ip = self.vip.address
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400199
200 def _check_load_balancing(self):
201 """
202 1. Send 10 requests on the floating ip associated with the VIP
203 2. Check that the requests are shared between
204 the two servers and that both of them get equal portions
205 of the requests
206 """
207
Elena Ezhova91531102014-02-07 17:25:58 +0400208 self._check_connection(self.vip_ip)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400209 resp = []
210 for count in range(10):
211 resp.append(
212 urllib.urlopen(
Elena Ezhova91531102014-02-07 17:25:58 +0400213 "http://{0}/".format(self.vip_ip)).read())
Matt Riedemann30670e02014-02-08 12:06:56 -0800214 self.assertEqual(set(["server1\n", "server2\n"]), set(resp))
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400215 self.assertEqual(5, resp.count("server1\n"))
216 self.assertEqual(5, resp.count("server2\n"))
217
Eugene Nikanorovc4aee352014-03-20 18:17:00 +0400218 @test.skip_because(bug='1295165')
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400219 @test.attr(type='smoke')
220 @test.services('compute', 'network')
221 def test_load_balancer_basic(self):
222 self._create_security_groups()
Elena Ezhova91531102014-02-07 17:25:58 +0400223 server = self._create_server()
224 self._start_servers(server)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400225 self._create_load_balancer()
226 self._check_load_balancing()
227
228
229class NeutronRetriever(object):
230 def __init__(self, network_client, path, resource):
231 self.network_client = network_client
232 self.path = path
233 self.resource = resource
234
235 def get(self, thing_id):
236 obj = self.network_client.get(self.path % thing_id)
237 return self.resource(client=self.network_client, **obj.values()[0])