Tempest: Support lbaas api & scenario tests to run against upstream
NSX-v lbaas requires lbaas's network attached to an exclusive router. To run lbaas tests on upstream implemantion, we need to remove rotuer_type attributes at creating router. Fixed lbaas API: delete-all load-balanacer resources without deleting listeners. wait for status function is now at load_balancers client. Lbaas scenario tests replace urllib2 with urllib3. Change-Id: Ief935eff8007c4c46115309f55ab3447ce146340
This commit is contained in:
parent
b3f1ff4ba2
commit
8dca2a4031
@ -61,7 +61,7 @@ class LoadBalancersClient(base.BaseNetworkClient):
|
|||||||
uri = self.resource_base_path
|
uri = self.resource_base_path
|
||||||
return self.list_resources(uri, **filters)
|
return self.list_resources(uri, **filters)
|
||||||
|
|
||||||
def wait_for_load_balancers_status(self, load_balancer_id,
|
def wait_for_load_balancer_status(self, load_balancer_id,
|
||||||
provisioning_status='ACTIVE',
|
provisioning_status='ACTIVE',
|
||||||
operating_status='ONLINE',
|
operating_status='ONLINE',
|
||||||
is_delete_op=False):
|
is_delete_op=False):
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
# ported from neutron-lbaas to comply to tempest framework
|
# ported from neutron-lbaas to comply to tempest framework
|
||||||
# NSX-v require vip-subnet attached to exclusive router
|
# NSX-v require vip-subnet attached to exclusive router
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from tempest.api.network import base
|
from tempest.api.network import base
|
||||||
@ -28,7 +26,6 @@ from tempest.lib.common.utils import data_utils
|
|||||||
from tempest.lib.common.utils import test_utils
|
from tempest.lib.common.utils import test_utils
|
||||||
from tempest.lib import exceptions
|
from tempest.lib import exceptions
|
||||||
|
|
||||||
from vmware_nsx_tempest._i18n import _
|
|
||||||
from vmware_nsx_tempest._i18n import _LI
|
from vmware_nsx_tempest._i18n import _LI
|
||||||
from vmware_nsx_tempest.services.lbaas import health_monitors_client
|
from vmware_nsx_tempest.services.lbaas import health_monitors_client
|
||||||
from vmware_nsx_tempest.services.lbaas import listeners_client
|
from vmware_nsx_tempest.services.lbaas import listeners_client
|
||||||
@ -38,6 +35,7 @@ from vmware_nsx_tempest.services.lbaas import pools_client
|
|||||||
|
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
NO_ROUTER_TYPE = CONF.nsxv.no_router_type
|
||||||
|
|
||||||
|
|
||||||
class BaseTestCase(base.BaseNetworkTest):
|
class BaseTestCase(base.BaseNetworkTest):
|
||||||
@ -82,6 +80,9 @@ class BaseTestCase(base.BaseNetworkTest):
|
|||||||
cls.subnet_id = cls.subnet.get('id')
|
cls.subnet_id = cls.subnet.get('id')
|
||||||
# NSX-v: load-balancer's subnet need to attach to exclusive-router
|
# NSX-v: load-balancer's subnet need to attach to exclusive-router
|
||||||
router_cfg = dict(router_name=router_name, router_type='exclusive')
|
router_cfg = dict(router_name=router_name, router_type='exclusive')
|
||||||
|
if NO_ROUTER_TYPE:
|
||||||
|
# router_type is NSX-v extension.
|
||||||
|
router_cfg.pop('router_type', None)
|
||||||
cls.router = cls.create_router(**router_cfg)
|
cls.router = cls.create_router(**router_cfg)
|
||||||
cls.create_router_interface(cls.router['id'], cls.subnet['id'])
|
cls.create_router_interface(cls.router['id'], cls.subnet['id'])
|
||||||
|
|
||||||
@ -95,25 +96,30 @@ class BaseTestCase(base.BaseNetworkTest):
|
|||||||
continue
|
continue
|
||||||
for listener in lb.get('listeners', []):
|
for listener in lb.get('listeners', []):
|
||||||
for pool in listener.get('pools'):
|
for pool in listener.get('pools'):
|
||||||
|
# delete pool's health-monitor
|
||||||
hm = pool.get('healthmonitor')
|
hm = pool.get('healthmonitor')
|
||||||
if hm:
|
if hm:
|
||||||
test_utils.call_and_ignore_notfound_exc(
|
test_utils.call_and_ignore_notfound_exc(
|
||||||
cls.health_monitors_client.delete_health_monitor,
|
cls.health_monitors_client.delete_health_monitor,
|
||||||
pool.get('healthmonitor').get('id'))
|
pool.get('healthmonitor').get('id'))
|
||||||
cls._wait_for_load_balancer_status(lb_id)
|
cls._wait_for_load_balancer_status(lb_id)
|
||||||
|
# delete pool's members
|
||||||
|
members = pool.get('members', [])
|
||||||
|
for member in members:
|
||||||
|
test_utils.call_and_ignore_notfound_exc(
|
||||||
|
cls.members_client.delete_member,
|
||||||
|
pool.get('id'), member.get('id'))
|
||||||
|
cls._wait_for_load_balancer_status(lb_id)
|
||||||
|
# delete pool
|
||||||
test_utils.call_and_ignore_notfound_exc(
|
test_utils.call_and_ignore_notfound_exc(
|
||||||
cls.pools_client.delete_pool, pool.get('id'))
|
cls.pools_client.delete_pool, pool.get('id'))
|
||||||
cls._wait_for_load_balancer_status(lb_id)
|
cls._wait_for_load_balancer_status(lb_id)
|
||||||
health_monitor = pool.get('healthmonitor')
|
# delete listener
|
||||||
if health_monitor:
|
|
||||||
test_utils.call_and_ignore_notfound_exc(
|
|
||||||
cls.health_monitors_client.delete_health_monitor,
|
|
||||||
health_monitor.get('id'))
|
|
||||||
cls._wait_for_load_balancer_status(lb_id)
|
|
||||||
test_utils.call_and_ignore_notfound_exc(
|
test_utils.call_and_ignore_notfound_exc(
|
||||||
cls.listeners_client.delete_listener,
|
cls.listeners_client.delete_listener,
|
||||||
listener.get('id'))
|
listener.get('id'))
|
||||||
cls._wait_for_load_balancer_status(lb_id)
|
cls._wait_for_load_balancer_status(lb_id)
|
||||||
|
# delete load-balancer
|
||||||
test_utils.call_and_ignore_notfound_exc(
|
test_utils.call_and_ignore_notfound_exc(
|
||||||
cls._delete_load_balancer, lb_id)
|
cls._delete_load_balancer, lb_id)
|
||||||
# NSX-v: delete exclusive router
|
# NSX-v: delete exclusive router
|
||||||
@ -186,54 +192,11 @@ class BaseTestCase(base.BaseNetworkTest):
|
|||||||
provisioning_status='ACTIVE',
|
provisioning_status='ACTIVE',
|
||||||
operating_status='ONLINE',
|
operating_status='ONLINE',
|
||||||
delete=False):
|
delete=False):
|
||||||
interval_time = 1
|
return cls.load_balancers_client.wait_for_load_balancer_status(
|
||||||
timeout = 600
|
load_balancer_id,
|
||||||
end_time = time.time() + timeout
|
|
||||||
lb = {}
|
|
||||||
while time.time() < end_time:
|
|
||||||
try:
|
|
||||||
lb = cls.load_balancers_client.show_load_balancer(
|
|
||||||
load_balancer_id)
|
|
||||||
if not lb:
|
|
||||||
# loadbalancer not found
|
|
||||||
if delete:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise Exception(
|
|
||||||
_("loadbalancer {lb_id} not"
|
|
||||||
" found").format(
|
|
||||||
lb_id=load_balancer_id))
|
|
||||||
lb = lb.get('loadbalancer', lb)
|
|
||||||
if (lb.get('provisioning_status') == provisioning_status and
|
|
||||||
lb.get('operating_status') == operating_status):
|
|
||||||
break
|
|
||||||
time.sleep(interval_time)
|
|
||||||
except exceptions.NotFound as e:
|
|
||||||
# if wait is for delete operation do break
|
|
||||||
if delete:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# raise original exception
|
|
||||||
raise e
|
|
||||||
else:
|
|
||||||
if delete:
|
|
||||||
raise exceptions.TimeoutException(
|
|
||||||
_("Waited for load balancer {lb_id} to be deleted for "
|
|
||||||
"{timeout} seconds but can still observe that it "
|
|
||||||
"exists.").format(
|
|
||||||
lb_id=load_balancer_id,
|
|
||||||
timeout=timeout))
|
|
||||||
else:
|
|
||||||
raise exceptions.TimeoutException(
|
|
||||||
_("Wait for load balancer ran for {timeout} seconds and "
|
|
||||||
"did not observe {lb_id} reach {provisioning_status} "
|
|
||||||
"provisioning status and {operating_status} "
|
|
||||||
"operating status.").format(
|
|
||||||
timeout=timeout,
|
|
||||||
lb_id=load_balancer_id,
|
|
||||||
provisioning_status=provisioning_status,
|
provisioning_status=provisioning_status,
|
||||||
operating_status=operating_status))
|
operating_status=operating_status,
|
||||||
return lb
|
is_delete_op=delete)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _show_load_balancer_status_tree(cls, load_balancer_id):
|
def _show_load_balancer_status_tree(cls, load_balancer_id):
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
import urllib2
|
import urllib3
|
||||||
|
|
||||||
from tempest.common import waiters
|
from tempest.common import waiters
|
||||||
from tempest import config
|
from tempest import config
|
||||||
@ -151,14 +151,14 @@ class TestLBaasRoundRobinOps(dmgr.TopoDeployScenarioManager):
|
|||||||
self.wait_for_load_balancer_status(lb_id)
|
self.wait_for_load_balancer_status(lb_id)
|
||||||
test_utils.call_and_ignore_notfound_exc(
|
test_utils.call_and_ignore_notfound_exc(
|
||||||
lb_client.delete_load_balancer, lb_id)
|
lb_client.delete_load_balancer, lb_id)
|
||||||
self.load_balancers_client.wait_for_load_balancers_status(
|
self.load_balancers_client.wait_for_load_balancer_status(
|
||||||
lb_id, is_delete_op=True)
|
lb_id, is_delete_op=True)
|
||||||
lbs = lb_client.list_load_balancers()['loadbalancers']
|
lbs = lb_client.list_load_balancers()['loadbalancers']
|
||||||
self.assertEqual(0, len(lbs))
|
self.assertEqual(0, len(lbs))
|
||||||
|
|
||||||
def wait_for_load_balancer_status(self, lb_id):
|
def wait_for_load_balancer_status(self, lb_id):
|
||||||
# Wait for load balancer become ONLINE and ACTIVE
|
# Wait for load balancer become ONLINE and ACTIVE
|
||||||
self.load_balancers_client.wait_for_load_balancers_status(lb_id)
|
self.load_balancers_client.wait_for_load_balancer_status(lb_id)
|
||||||
|
|
||||||
def create_lbaas_networks(self):
|
def create_lbaas_networks(self):
|
||||||
"""Create network, subnet and router for lbaasv2 environment."""
|
"""Create network, subnet and router for lbaasv2 environment."""
|
||||||
@ -263,9 +263,12 @@ class TestLBaasRoundRobinOps(dmgr.TopoDeployScenarioManager):
|
|||||||
|
|
||||||
def send_request(self, web_ip):
|
def send_request(self, web_ip):
|
||||||
try:
|
try:
|
||||||
response = urllib2.urlopen("http://{0}/".format(web_ip)).read()
|
url_path = "http://{0}/".format(web_ip)
|
||||||
return response
|
# lbaas servers use nc, might be slower to response
|
||||||
except urllib2.HTTPError:
|
http = urllib3.PoolManager(retries=10)
|
||||||
|
resp = http.request('GET', url_path)
|
||||||
|
return resp.data.strip()
|
||||||
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def create_project_lbaas(self):
|
def create_project_lbaas(self):
|
||||||
@ -306,6 +309,14 @@ class TestLBaasRoundRobinOps(dmgr.TopoDeployScenarioManager):
|
|||||||
self.wait_for_load_balancer_status(lb_id)
|
self.wait_for_load_balancer_status(lb_id)
|
||||||
self.members.append(member)
|
self.members.append(member)
|
||||||
|
|
||||||
|
# Currently the ovs-agent is not enforcing security groups on the
|
||||||
|
# vip port - see https://bugs.launchpad.net/neutron/+bug/1163569
|
||||||
|
# However the linuxbridge-agent does, and it is necessary to add a
|
||||||
|
# security group with a rule that allows tcp port 80 to the vip port.
|
||||||
|
# NSX-v lbaasv2 OK, but for upstream neutron-lbaas needs this.
|
||||||
|
self.ports_client.update_port(
|
||||||
|
self.loadbalancer['vip_port_id'],
|
||||||
|
security_groups=[self.security_group['id']])
|
||||||
# create lbaas public interface
|
# create lbaas public interface
|
||||||
self.vip_fip = self.create_floatingip_for_server(
|
self.vip_fip = self.create_floatingip_for_server(
|
||||||
self.loadbalancer, self.public_network_id,
|
self.loadbalancer, self.public_network_id,
|
||||||
@ -321,9 +332,11 @@ class TestLBaasRoundRobinOps(dmgr.TopoDeployScenarioManager):
|
|||||||
self.loadbalancer['id'])
|
self.loadbalancer['id'])
|
||||||
statuses = statuses.get('statuses', statuses)
|
statuses = statuses.get('statuses', statuses)
|
||||||
self.http_cnt = {}
|
self.http_cnt = {}
|
||||||
|
http = urllib3.PoolManager(retries=10)
|
||||||
|
url_path = "http://{0}/".format(self.vip_ip_address)
|
||||||
for x in range(self.poke_counters):
|
for x in range(self.poke_counters):
|
||||||
response = self.send_request(self.vip_ip_address)
|
resp = http.request('GET', url_path)
|
||||||
self.count_response(response)
|
self.count_response(resp.data.strip())
|
||||||
# should response from 2 servers
|
# should response from 2 servers
|
||||||
self.assertEqual(2, len(self.http_cnt))
|
self.assertEqual(2, len(self.http_cnt))
|
||||||
# ROUND_ROUBIN, so equal counts
|
# ROUND_ROUBIN, so equal counts
|
||||||
|
Loading…
Reference in New Issue
Block a user