Add lbaas test
Change-Id: Ie4e1a72af612a00a8d72968f6f0534761aae6bda
This commit is contained in:
parent
7bb3233061
commit
84cd80fc4b
|
@ -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
|
||||
|
|
|
@ -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")
|
|
@ -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))
|
|
@ -221,8 +221,6 @@ 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',
|
||||
|
@ -230,3 +228,12 @@ NAT_SERVICE_IMAGE_URL = os.environ.get('NAT_SERVICE_IMAGE_URL',
|
|||
SERVICE_INSTANCE_CREATE_TIMEOUT = 2 * 60
|
||||
SERVICE_INSTANCE_BOOT_TIMEOUT = 10 * 60
|
||||
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')
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue