Add lbaas test

Change-Id: Ie4e1a72af612a00a8d72968f6f0534761aae6bda
This commit is contained in:
Georgy Dyuldin 2017-05-02 13:54:32 +03:00
parent 7bb3233061
commit 84cd80fc4b
6 changed files with 345 additions and 4 deletions

View File

@ -13,6 +13,7 @@ from vapor.fixtures.dns import * # noqa
from vapor.fixtures.images import * # noqa
from vapor.fixtures.instance_ip import * # noqa
from vapor.fixtures.ipams import * # noqa
from vapor.fixtures.lbaas import * # noqa
from vapor.fixtures.networks import * # noqa
from vapor.fixtures.nodes import * # noqa
from vapor.fixtures.policies import * # noqa

View File

@ -0,0 +1,58 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import functools
import pytest
from stepler.third_party import utils
from vapor.helpers import lbaas
@pytest.fixture
def lbaas_steps(neutron_client):
return lbaas.LBaaSSteps(neutron_client)
@pytest.fixture
def loadbalancer(request, lbaas_steps, net_subnet_router):
"""Fixture to create loadbalancer on default subnet."""
name = next(utils.generate_ids('lb'))
request.addfinalizer(
functools.partial(lbaas_steps.cleanup_lbs, names=[name]))
return lbaas_steps.create_lb(name, net_subnet_router[1])
@pytest.fixture
def lb_listener(request, lbaas_steps, loadbalancer):
"""Fixture to create lbaas HTTP listener."""
name = next(utils.generate_ids('lb_listener'))
request.addfinalizer(
functools.partial(lbaas_steps.cleanup_listeners, names=[name]))
return lbaas_steps.create_listener(
name=name,
loadbalancer=loadbalancer,
protocol="HTTP",
protocol_port=80)
@pytest.fixture
def lb_pool(request, lbaas_steps, lb_listener):
"""Fixture to create lbaas pool."""
name = next(utils.generate_ids('lb_pool'))
request.addfinalizer(
functools.partial(lbaas_steps.cleanup_pools, names=[name]))
return lbaas_steps.create_pool(
name=name,
listener=lb_listener,
protocol="HTTP",
lb_algorithm="ROUND_ROBIN")

View File

@ -0,0 +1,191 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from hamcrest import (assert_that, equal_to, is_, is_not, contains,
has_entries, starts_with, has_length) # noqa: H310
import requests
from stepler import base
from stepler.third_party import waiter
from vapor import settings
class LBaaSSteps(base.BaseSteps):
"""LBaaS steps."""
def _check_presence(self, objs, list_method, expected_presence, timeout=0):
def _check_presence():
all_objs = list_method()
matcher = is_
if not expected_presence:
matcher = is_not
return waiter.expect_that(
all_objs,
matcher(
contains(*[has_entries(id=obj['id']) for obj in objs])))
waiter.wait(_check_presence, timeout_seconds=timeout)
def create_lb(self, name, subnet, **kwargs):
"""Create loadbalancer and wait it became to online."""
loadbalancer = self._client.lbaas_loadbalancers.create(
name=name, vip_subnet_id=subnet['id'], **kwargs)
loadbalancer = self.check_lb_provisioning_status(
loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
return loadbalancer
def delete_lbs(self, loadbalancers):
"""Delete loadbalancer and wait for deletion to be completed."""
for loadbalancer in loadbalancers:
self._client.lbaas_loadbalancers.delete(loadbalancer['id'])
self.check_lbs_presence(
loadbalancers, timeout=settings.LBAAS_DELETE_TIMEOUT)
def check_lb_provisioning_status(self,
loadbalancer,
expected_status="ACTIVE",
timeout=0):
"""Check that loadbalancer has expected provisioning status."""
def _check_status():
lb = self._client.lbaas_loadbalancers.get(loadbalancer['id'])
waiter.expect_that(lb['provisioning_status'],
is_not(starts_with('PENDING_')))
return lb
loadbalancer = waiter.wait(_check_status, timeout_seconds=timeout)
assert_that(loadbalancer['provisioning_status'],
equal_to(expected_status))
return loadbalancer
def check_lbs_presence(self,
loadbalancers,
expected_presence=True,
timeout=0):
"""Check that loadbalancer is present (or not)."""
self._check_presence(
loadbalancers,
self._client.lbaas_loadbalancers.list,
expected_presence,
timeout=timeout)
def cleanup_lbs(self, names):
"""Remove all loadbalancers by names list."""
loadbalancers = []
for name in names:
for loadbalancer in self._client.lbaas_loadbalancers.find_all(
name=name):
loadbalancers.append(loadbalancer)
self._client.lbaas_loadbalancers.delete(loadbalancer['id'])
self.check_lbs_presence(
loadbalancers,
expected_presence=False,
timeout=settings.LBAAS_DELETE_TIMEOUT)
def create_listener(self, name, loadbalancer, protocol, protocol_port,
**kwargs):
"""Create LBaaS listener."""
listener = self._client.lbaas_listeners.create(
name=name,
loadbalancer_id=loadbalancer['id'],
protocol=protocol,
protocol_port=protocol_port,
**kwargs)
self.check_lb_provisioning_status(
loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
return listener
def delete_listener(self, listener):
"""Delete LBaaS listener."""
listener = self._client.lbaas_listeners.get(listener['id'])
loadbalancers = listener['loadbalancers']
self._client.lbaas_listeners.delete(listener['id'])
for lb in loadbalancers:
self.check_lb_provisioning_status(
lb, timeout=settings.LBAAS_ONLINE_TIMEOUT)
def cleanup_listeners(self, names):
"""Remove all listeners by names list."""
for name in names:
for listener in self._client.lbaas_listeners.find_all(name=name):
self.delete_listener(listener)
def create_pool(self, name, listener, protocol, lb_algorithm, **kwargs):
"""Create LBaaS pool."""
pool = self._client.lbaas_pools.create(
name=name,
listener_id=listener['id'],
protocol=protocol,
lb_algorithm=lb_algorithm,
**kwargs)
for loadbalancer in pool['loadbalancers']:
self.check_lb_provisioning_status(
loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
return pool
def delete_pool(self, pool):
"""Create LBaaS pool."""
self._client.lbaas_pools.delete(pool['id'])
for loadbalancer in pool['loadbalancers']:
self.check_lb_provisioning_status(
loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
def cleanup_pools(self, names):
"""Remove all pools by names list."""
loadbalancers = []
for name in names:
for pool in self._client.lbaas_pools.find_all(name=name):
self._client.lbaas_pools.delete(pool['id'])
loadbalancers.extend(pool['loadbalancers'])
for loadbalancer in loadbalancers:
self.check_lb_provisioning_status(
loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
def create_member(self, pool, address, protocol_port, subnet, **kwargs):
"""Create LBaaS pool member."""
member = pool.members.create(
address=address,
protocol_port=protocol_port,
subnet_id=subnet['id'],
**kwargs)
for loadbalancer in pool['loadbalancers']:
self.check_lb_provisioning_status(
loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
return member
def delete_member(self, pool, member):
"""Delete LBaaS pool member."""
pool.members.delete(member['id'])
for loadbalancer in pool['loadbalancers']:
self.check_lb_provisioning_status(
loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
def check_balancing(self, ip, port, expected_count):
"""Check that responses contains `expected_counts` variants."""
responses = set()
for _ in range(expected_count * 3):
r = requests.get("http://{}:{}/".format(ip, port))
r.raise_for_status()
responses.add(r.text)
assert_that(responses, has_length(expected_count))

View File

@ -221,12 +221,19 @@ SECURITY_GROUP_SSH_PING_RULES = (stepler_config.SECURITY_GROUP_SSH_RULES +
DPDK_ENABLED_GROUP = u'Network devices using DPDK-compatible driver'
# Service chaining
# TODO(gdyuldin): relace with real URL
NAT_SERVICE_IMAGE_URL = os.environ.get('NAT_SERVICE_IMAGE_URL',
'/home/jenkins/nat.qcow2')
SERVICE_INSTANCE_CREATE_TIMEOUT = 2 * 60
SERVICE_INSTANCE_BOOT_TIMEOUT = 10 * 60
SERVICE_INSTANCE_BOOT_DONE_PATTERN = 'Cloud-init .+ finished'
SERVICE_INSTANCE_BOOT_DONE_PATTERN = 'Cloud-init .+ finished'
# LBAAS
LBAAS_ONLINE_TIMEOUT = 5 * 60
LBAAS_DELETE_TIMEOUT = 2 * 60
HTTP_SERVER_CMD = (
'while true; do '
'echo -e "HTTP/1.0 200 OK\\r\\nContent-Length: $(hostname | wc -c)\\r\\n\\r\\n$(hostname)" | nc -l -p {port}; ' # noqa
'done')

View File

@ -70,7 +70,8 @@ def test_contrail_vrouter_dpdk_cpu_usage(os_faults_steps, computes):
@pytest.mark.parametrize(
'flavor', [dict(ram=1024, metadata={"hw:mem_page_size": "large"})], indirect=True)
'flavor', [dict(ram=1024, metadata={"hw:mem_page_size": "large"})],
indirect=True)
@pytest.mark.usefixtures('flavor')
def test_vrouter_create_interface(request, os_faults_steps, computes):
"""Verify if vRouter creates interface after creation of a virtual machine.

View File

@ -0,0 +1,83 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from six import moves
from stepler import config as stepler_config
from vapor import settings
def test_loadbalancer_after_deleting_server(
flavor, cirros_image, net_subnet_router, security_group, loadbalancer,
create_floating_ip, port_steps, server_steps, lb_listener, lb_pool,
neutron_security_group_rule_steps, lbaas_steps):
"""Check loadbalancer after deleting server.
Steps:
#. Create network, subnet
#. Create loadbalancer
#. Create lbaas listener
#. Create lbaas pool
#. Create security group with allow ping rule
#. Create floating IP on loadbalancer port
#. Create 2 servers with simple HTTP server
#. Add servers' IPs to loadbalancer pool
#. Check that loadbalancer routes HTTP queries between servers
#. Delete one of servers
#. Check that loadbalancer pass all HTTP queries to single alive server
"""
port = 80
neutron_security_group_rule_steps.add_rule_to_group(
security_group['id'],
direction='ingress',
protocol='tcp',
port_range_min=port,
port_range_max=port)
http_server_cmd = settings.HTTP_SERVER_CMD.format(port=port)
userdata = "\n".join([
'#!/bin/sh -v',
'screen -dmS daemon /bin/sh -c {cmd}',
'screen -ls',
'echo {done_marker}',
]).format(
cmd=moves.shlex_quote(http_server_cmd),
done_marker=stepler_config.USERDATA_DONE_MARKER)
network, subnet, _ = net_subnet_router
servers = server_steps.create_servers(
count=2,
image=cirros_image,
flavor=flavor,
networks=[network],
security_groups=[security_group],
userdata=userdata)
for server in servers:
server_steps.check_server_log_contains_record(
server,
stepler_config.USERDATA_DONE_MARKER,
timeout=stepler_config.USERDATA_EXECUTING_TIMEOUT)
ip = server_steps.get_fixed_ip(server)
lbaas_steps.create_member(lb_pool, ip, port, subnet)
vip_port = {'id': loadbalancer['vip_port_id']}
port_steps.update(vip_port, security_groups=[security_group['id']])
floating_ip = create_floating_ip(port=vip_port)
lbaas_steps.check_balancing(
floating_ip['floating_ip_address'], port, expected_count=2)
server_steps.delete_servers(servers[1:])
lbaas_steps.check_balancing(
floating_ip['floating_ip_address'], port, expected_count=1)