Merge " Improve test_load_balancer_basic"

This commit is contained in:
Jenkins 2014-04-15 21:42:46 +00:00 committed by Gerrit Code Review
commit c066015fb7
2 changed files with 162 additions and 73 deletions

View File

@ -112,3 +112,8 @@ class RemoteClient():
def turn_nic_on(self, nic):
cmd = "sudo /bin/ip link set {nic} up".format(nic=nic)
return self.exec_command(cmd)
def get_pids(self, pr_name):
# Get pid(s) of a process/program
cmd = "ps -ef | grep %s | grep -v 'grep' | awk {'print $1'}" % pr_name
return self.exec_command(cmd).split('\n')

View File

@ -17,7 +17,6 @@ import time
import urllib
from tempest.api.network import common as net_common
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
from tempest.scenario import manager
@ -59,20 +58,27 @@ class TestLoadBalancerBasic(manager.NetworkScenarioTest):
def setUpClass(cls):
super(TestLoadBalancerBasic, cls).setUpClass()
cls.check_preconditions()
cls.security_groups = {}
cls.servers_keypairs = {}
cls.members = []
cls.floating_ips = {}
cls.server_ip = None
cls.vip_ip = None
cls.server_ips = {}
cls.port1 = 80
cls.port2 = 88
def _create_security_groups(self):
self.security_groups[self.tenant_id] =\
self._create_security_group_neutron(tenant_id=self.tenant_id)
def setUp(self):
super(TestLoadBalancerBasic, self).setUp()
self.server_ips = {}
self._create_security_group()
def cleanup_wrapper(self, resource):
self.cleanup_resource(resource, self.__class__.__name__)
def _create_security_group(self):
self.security_group = self._create_security_group_neutron(
tenant_id=self.tenant_id)
self._create_security_group_rules_for_port(self.port1)
self._create_security_group_rules_for_port(self.port2)
self.addCleanup(self.cleanup_wrapper, self.security_group)
def _create_security_group_rules_for_port(self, port):
rule = {
@ -83,15 +89,14 @@ class TestLoadBalancerBasic(manager.NetworkScenarioTest):
}
self._create_security_group_rule(
client=self.network_client,
secgroup=self.security_groups[self.tenant_id],
secgroup=self.security_group,
tenant_id=self.tenant_id,
**rule)
def _create_server(self):
tenant_id = self.tenant_id
name = data_utils.rand_name("smoke_server-")
def _create_server(self, name):
keypair = self.create_keypair(name='keypair-%s' % name)
security_groups = [self.security_groups[tenant_id].name]
self.addCleanup(self.cleanup_wrapper, keypair)
security_groups = [self.security_group.name]
net = self._list_networks(tenant_id=self.tenant_id)[0]
create_kwargs = {
'nics': [
@ -102,51 +107,106 @@ class TestLoadBalancerBasic(manager.NetworkScenarioTest):
}
server = self.create_server(name=name,
create_kwargs=create_kwargs)
self.servers_keypairs[server] = keypair
self.addCleanup(self.cleanup_wrapper, server)
self.servers_keypairs[server.id] = keypair
if (config.network.public_network_id and not
config.network.tenant_networks_reachable):
public_network_id = config.network.public_network_id
floating_ip = self._create_floating_ip(
server, public_network_id)
self.addCleanup(self.cleanup_wrapper, floating_ip)
self.floating_ips[floating_ip] = server
self.server_ip = floating_ip.floating_ip_address
self.server_ips[server.id] = floating_ip.floating_ip_address
else:
self.server_ip = server.networks[net['name']][0]
self.server_ips[server.id] = server.networks[net.name][0]
self.assertTrue(self.servers_keypairs)
return server
def _start_servers(self, server):
def _create_servers(self):
for count in range(2):
self._create_server(name=("server%s" % (count + 1)))
self.assertEqual(len(self.servers_keypairs), 2)
def _start_servers(self):
"""
Start two backends
1. SSH to the instance
2. Start two http backends listening on ports 80 and 88 respectively
In case there are two instances, each backend is created on a separate
instance.
The backends are the inetd services. To start them we need to edit
/etc/inetd.conf in the following way:
www stream tcp nowait root /bin/sh sh /home/cirros/script_name
Where /home/cirros/script_name is a path to a script which
echoes the responses:
echo -e 'HTTP/1.0 200 OK\r\n\r\nserver_name
If we want the server to listen on port 88, then we use
"kerberos" instead of "www".
"""
private_key = self.servers_keypairs[server].private_key
ssh_client = self.get_remote_client(
server_or_ip=self.server_ip,
private_key=private_key).ssh_client
start_server = "while true; do echo -e 'HTTP/1.0 200 OK\r\n\r\n" \
"%(server)s' | sudo nc -l -p %(port)s ; done &"
cmd = start_server % {'server': 'server1',
'port': self.port1}
ssh_client.exec_command(cmd)
cmd = start_server % {'server': 'server2',
'port': self.port2}
ssh_client.exec_command(cmd)
for server_id, ip in self.server_ips.iteritems():
private_key = self.servers_keypairs[server_id].private_key
server_name = self.compute_client.servers.get(server_id).name
ssh_client = self.get_remote_client(
server_or_ip=ip,
private_key=private_key)
ssh_client.validate_authentication()
# Create service for inetd
create_script = """sudo sh -c "echo -e \\"echo -e 'HTTP/1.0 """ \
"""200 OK\\\\\\r\\\\\\n\\\\\\r\\\\\\n""" \
"""%(server)s'\\" >>/home/cirros/%(script)s\""""
def _check_connection(self, check_ip):
def try_connect(ip):
cmd = create_script % {
'server': server_name,
'script': 'script1'}
ssh_client.exec_command(cmd)
# Configure inetd
configure_inetd = """sudo sh -c "echo -e \\"%(service)s """ \
"""stream tcp nowait root /bin/sh sh """ \
"""/home/cirros/%(script)s\\" >> """ \
"""/etc/inetd.conf\""""
# "www" stands for port 80
cmd = configure_inetd % {'service': 'www',
'script': 'script1'}
ssh_client.exec_command(cmd)
if len(self.server_ips) == 1:
cmd = create_script % {'server': 'server2',
'script': 'script2'}
ssh_client.exec_command(cmd)
# "kerberos" stands for port 88
cmd = configure_inetd % {'service': 'kerberos',
'script': 'script2'}
ssh_client.exec_command(cmd)
# Get PIDs of inetd
pids = ssh_client.get_pids('inetd')
if pids != ['']:
# If there are any inetd processes, reload them
kill_cmd = "sudo kill -HUP %s" % ' '.join(pids)
ssh_client.exec_command(kill_cmd)
else:
# In other case start inetd
start_inetd = "sudo /usr/sbin/inetd /etc/inetd.conf"
ssh_client.exec_command(start_inetd)
def _check_connection(self, check_ip, port=80):
def try_connect(ip, port):
try:
urllib.urlopen("http://{0}/".format(ip))
return True
resp = urllib.urlopen("http://{0}:{1}/".format(ip, port))
if resp.getcode() == 200:
return True
return False
except IOError:
return False
timeout = config.compute.ping_timeout
timer = 0
while not try_connect(check_ip):
time.sleep(1)
timer += 1
if timer >= timeout:
start = time.time()
while not try_connect(check_ip, port):
if (time.time() - start) > timeout:
message = "Timed out trying to connect to %s" % check_ip
raise exceptions.TimeoutException(message)
@ -157,30 +217,37 @@ class TestLoadBalancerBasic(manager.NetworkScenarioTest):
self.subnet = net_common.DeletableSubnet(client=self.network_client,
**subnet)
self.pool = super(TestLoadBalancerBasic, self)._create_pool(
'ROUND_ROBIN',
'HTTP',
self.subnet.id)
lb_method='ROUND_ROBIN',
protocol='HTTP',
subnet_id=self.subnet.id)
self.addCleanup(self.cleanup_wrapper, self.pool)
self.assertTrue(self.pool)
def _create_members(self, server_ids):
def _create_members(self):
"""
Create two members.
In case there is only one server, create both members with the same ip
but with different ports to listen on.
"""
servers = self.compute_client.servers.list()
for server in servers:
if server.id in server_ids:
ip = self.server_ip
pool_id = self.pool.id
if len(set(server_ids)) == 1 or len(servers) == 1:
member1 = self._create_member(ip, self.port1, pool_id)
member2 = self._create_member(ip, self.port2, pool_id)
self.members.extend([member1, member2])
else:
member = self._create_member(ip, self.port1, pool_id)
self.members.append(member)
for server_id, ip in self.server_ips.iteritems():
if len(self.server_ips) == 1:
member1 = self._create_member(address=ip,
protocol_port=self.port1,
pool_id=self.pool.id)
self.addCleanup(self.cleanup_wrapper, member1)
member2 = self._create_member(address=ip,
protocol_port=self.port2,
pool_id=self.pool.id)
self.addCleanup(self.cleanup_wrapper, member2)
self.members.extend([member1, member2])
else:
member = self._create_member(address=ip,
protocol_port=self.port1,
pool_id=self.pool.id)
self.addCleanup(self.cleanup_wrapper, member)
self.members.append(member)
self.assertTrue(self.members)
def _assign_floating_ip_to_vip(self, vip):
@ -188,22 +255,23 @@ class TestLoadBalancerBasic(manager.NetworkScenarioTest):
port_id = vip.port_id
floating_ip = self._create_floating_ip(vip, public_network_id,
port_id=port_id)
self.addCleanup(self.cleanup_wrapper, floating_ip)
self.floating_ips.setdefault(vip.id, [])
self.floating_ips[vip.id].append(floating_ip)
def _create_load_balancer(self):
self._create_pool()
self._create_members([self.servers_keypairs.keys()[0].id])
subnet_id = self.subnet.id
pool_id = self.pool.id
self.vip = super(TestLoadBalancerBasic, self)._create_vip('HTTP', 80,
subnet_id,
pool_id)
self._status_timeout(NeutronRetriever(self.network_client,
self.network_client.vip_path,
net_common.DeletableVip),
self.vip.id,
expected_status='ACTIVE')
self._create_members()
self.vip = self._create_vip(protocol='HTTP',
protocol_port=80,
subnet_id=self.subnet.id,
pool_id=self.pool.id)
self.addCleanup(self.cleanup_wrapper, self.vip)
self.status_timeout(NeutronRetriever(self.network_client,
self.network_client.vip_path,
net_common.DeletableVip),
self.vip.id,
expected_status='ACTIVE')
if (config.network.public_network_id and not
config.network.tenant_networks_reachable):
self._assign_floating_ip_to_vip(self.vip)
@ -214,33 +282,49 @@ class TestLoadBalancerBasic(manager.NetworkScenarioTest):
def _check_load_balancing(self):
"""
1. Send 10 requests on the floating ip associated with the VIP
1. Send 100 requests on the floating ip associated with the VIP
2. Check that the requests are shared between
the two servers and that both of them get equal portions
of the requests
"""
self._check_connection(self.vip_ip)
resp = self._send_requests(self.vip_ip)
self.assertEqual(set(["server1\n", "server2\n"]), set(resp))
self.assertEqual(50, resp.count("server1\n"))
self.assertEqual(50, resp.count("server2\n"))
def _send_requests(self, vip_ip):
resp = []
for count in range(10):
for count in range(100):
resp.append(
urllib.urlopen(
"http://{0}/".format(self.vip_ip)).read())
self.assertEqual(set(["server1\n", "server2\n"]), set(resp))
self.assertEqual(5, resp.count("server1\n"))
self.assertEqual(5, resp.count("server2\n"))
"http://{0}/".format(vip_ip)).read())
return resp
@test.attr(type='smoke')
@test.services('compute', 'network')
def test_load_balancer_basic(self):
self._create_security_groups()
server = self._create_server()
self._start_servers(server)
self._create_server('server1')
self._start_servers()
self._create_load_balancer()
self._check_load_balancing()
class NeutronRetriever(object):
"""
Helper class to make possible handling neutron objects returned by GET
requests as attribute dicts.
Whet get() method is called, the returned dictionary is wrapped into
a corresponding DeletableResource class which provides attribute access
to dictionary values.
Usage:
This retriever is used to allow using status_timeout from
tempest.manager with Neutron objects.
"""
def __init__(self, network_client, path, resource):
self.network_client = network_client
self.path = path