blob: 5bcdacd62c186bffc72259dd165e49f682c83a97 [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
20from tempest.common import ssh
21from tempest.common.utils import data_utils
22from tempest import config
23from tempest import exceptions
24from tempest.scenario import manager
25from tempest import test
26
27config = config.CONF
28
29
30class TestLoadBalancerBasic(manager.NetworkScenarioTest):
31
32 """
33 This test checks basic load balancing.
34
35 The following is the scenario outline:
36 1. Create an instance
37 2. SSH to the instance and start two servers
38 3. Create a load balancer with two members and with ROUND_ROBIN algorithm
39 associate the VIP with a floating ip
40 4. Send 10 requests to the floating ip and check that they are shared
41 between the two servers and that both of them get equal portions
42 of the requests
43 """
44
45 @classmethod
46 def check_preconditions(cls):
47 super(TestLoadBalancerBasic, cls).check_preconditions()
48 cfg = config.network
49 if not test.is_extension_enabled('lbaas', 'network'):
50 msg = 'LBaaS Extension is not enabled'
51 cls.enabled = False
52 raise cls.skipException(msg)
53 if not (cfg.tenant_networks_reachable or cfg.public_network_id):
54 msg = ('Either tenant_networks_reachable must be "true", or '
55 'public_network_id must be defined.')
56 cls.enabled = False
57 raise cls.skipException(msg)
58
59 @classmethod
60 def setUpClass(cls):
61 super(TestLoadBalancerBasic, cls).setUpClass()
62 cls.check_preconditions()
63 cls.security_groups = {}
Elena Ezhovaa5105e62013-11-26 20:46:52 +040064 cls.servers_keypairs = {}
Elena Ezhovaa5105e62013-11-26 20:46:52 +040065 cls.members = []
Elena Ezhovaa5105e62013-11-26 20:46:52 +040066 cls.floating_ips = {}
67 cls.port1 = 80
68 cls.port2 = 88
69
70 def _create_security_groups(self):
71 self.security_groups[self.tenant_id] =\
72 self._create_security_group_neutron(tenant_id=self.tenant_id)
73
74 def _create_server(self):
75 tenant_id = self.tenant_id
76 name = data_utils.rand_name("smoke_server-")
77 keypair = self.create_keypair(name='keypair-%s' % name)
78 security_groups = [self.security_groups[tenant_id].name]
Yair Fried2d2f3fe2014-02-24 16:19:20 +020079 net = self.list_networks(tenant_id=self.tenant_id)[0]
80 self.network = net_common.DeletableNetwork(client=self.network_client,
81 **net['network'])
82 create_kwargs = {
83 'nics': [
84 {'net-id': self.network.id},
85 ],
86 'key_name': keypair.name,
87 'security_groups': security_groups,
88 }
89 server = self.create_server(name=name,
90 create_kwargs=create_kwargs)
91 self.servers_keypairs[server] = keypair
Elena Ezhovaa5105e62013-11-26 20:46:52 +040092 self.assertTrue(self.servers_keypairs)
93
94 def _start_servers(self):
95 """
96 1. SSH to the instance
97 2. Start two servers listening on ports 80 and 88 respectively
98 """
99 for server in self.servers_keypairs.keys():
100 ssh_login = config.compute.image_ssh_user
101 private_key = self.servers_keypairs[server].private_key
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200102 network_name = self.network.name
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400103
104 ip_address = server.networks[network_name][0]
105 ssh_client = ssh.Client(ip_address, ssh_login,
106 pkey=private_key,
107 timeout=100)
108 start_server = "while true; do echo -e 'HTTP/1.0 200 OK\r\n\r\n" \
109 "%(server)s' | sudo nc -l -p %(port)s ; done &"
110 cmd = start_server % {'server': 'server1',
111 'port': self.port1}
112 ssh_client.exec_command(cmd)
113 cmd = start_server % {'server': 'server2',
114 'port': self.port2}
115 ssh_client.exec_command(cmd)
116
117 def _check_connection(self, check_ip):
118 def try_connect(ip):
119 try:
120 urllib.urlopen("http://{0}/".format(ip))
121 return True
122 except IOError:
123 return False
124 timeout = config.compute.ping_timeout
125 timer = 0
126 while not try_connect(check_ip):
127 time.sleep(1)
128 timer += 1
129 if timer >= timeout:
130 message = "Timed out trying to connect to %s" % check_ip
131 raise exceptions.TimeoutException(message)
132
133 def _create_pool(self):
134 """Create a pool with ROUND_ROBIN algorithm."""
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200135 # get tenant subnet and verify there's only one
136 subnet = self._list_subnets(tenant_id=self.tenant_id)[0]
137 self.subnet = net_common.DeletableSubnet(client=self.network_client,
138 **subnet['subnet'])
139 self.pool = super(TestLoadBalancerBasic, self)._create_pool(
140 'ROUND_ROBIN',
141 'HTTP',
142 self.subnet.id)
143 self.assertTrue(self.pool)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400144
145 def _create_members(self, network_name, server_ids):
146 """
147 Create two members.
148
149 In case there is only one server, create both members with the same ip
150 but with different ports to listen on.
151 """
152 servers = self.compute_client.servers.list()
153 for server in servers:
154 if server.id in server_ids:
155 ip = server.networks[network_name][0]
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200156 pool_id = self.pool.id
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400157 if len(set(server_ids)) == 1 or len(servers) == 1:
158 member1 = self._create_member(ip, self.port1, pool_id)
159 member2 = self._create_member(ip, self.port2, pool_id)
160 self.members.extend([member1, member2])
161 else:
162 member = self._create_member(ip, self.port1, pool_id)
163 self.members.append(member)
164 self.assertTrue(self.members)
165
166 def _assign_floating_ip_to_vip(self, vip):
167 public_network_id = config.network.public_network_id
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200168 port_id = vip.port_id
Yair Frieda2e3b2c2014-02-17 10:56:10 +0200169 floating_ip = self._create_floating_ip(vip, public_network_id,
170 port_id=port_id)
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200171 self.floating_ips.setdefault(vip.id, [])
172 self.floating_ips[vip.id].append(floating_ip)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400173
174 def _create_load_balancer(self):
175 self._create_pool()
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200176 self._create_members(self.network.name,
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400177 [self.servers_keypairs.keys()[0].id])
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200178 subnet_id = self.subnet.id
179 pool_id = self.pool.id
180 self.vip = super(TestLoadBalancerBasic, self)._create_vip('HTTP', 80,
181 subnet_id,
182 pool_id)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400183 self._status_timeout(NeutronRetriever(self.network_client,
184 self.network_client.vip_path,
185 net_common.DeletableVip),
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200186 self.vip.id,
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400187 expected_status='ACTIVE')
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200188 self._assign_floating_ip_to_vip(self.vip)
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400189
190 def _check_load_balancing(self):
191 """
192 1. Send 10 requests on the floating ip associated with the VIP
193 2. Check that the requests are shared between
194 the two servers and that both of them get equal portions
195 of the requests
196 """
197
Yair Fried2d2f3fe2014-02-24 16:19:20 +0200198 vip = self.vip
199 floating_ip_vip = self.floating_ips[vip.id][0]['floating_ip_address']
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400200 self._check_connection(floating_ip_vip)
201 resp = []
202 for count in range(10):
203 resp.append(
204 urllib.urlopen(
205 "http://{0}/".format(floating_ip_vip)).read())
Matt Riedemann30670e02014-02-08 12:06:56 -0800206 self.assertEqual(set(["server1\n", "server2\n"]), set(resp))
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400207 self.assertEqual(5, resp.count("server1\n"))
208 self.assertEqual(5, resp.count("server2\n"))
209
Mark McClain2f5cdc52014-02-07 13:54:57 -0500210 @test.skip_because(bug="1277381")
Elena Ezhovaa5105e62013-11-26 20:46:52 +0400211 @test.attr(type='smoke')
212 @test.services('compute', 'network')
213 def test_load_balancer_basic(self):
214 self._create_security_groups()
215 self._create_server()
216 self._start_servers()
217 self._create_load_balancer()
218 self._check_load_balancing()
219
220
221class NeutronRetriever(object):
222 def __init__(self, network_client, path, resource):
223 self.network_client = network_client
224 self.path = path
225 self.resource = resource
226
227 def get(self, thing_id):
228 obj = self.network_client.get(self.path % thing_id)
229 return self.resource(client=self.network_client, **obj.values()[0])