# 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 time from tempest.lib.common.utils import misc as misc_utils from tempest.lib import exceptions as lib_exc from tempest import exceptions from vmware_nsx_tempest._i18n import _ from vmware_nsx_tempest.services import network_client_base as base POOL_RID = 'pools' VIP_RID = 'vips' HEALTHMONITOR_RID = 'health_monitors' MEMBER_RID = 'members' class LoadBalancerV1Client(base.BaseNetworkClient): def _list_lb(self, lb_resource, **filters): resource_name_s, resource_name_p = _g_resource_namelist(lb_resource) req_uri = '/lb/%s' % (resource_name_p) return self.list_resources(req_uri, **filters) def _show_lb(self, lb_resource, resource_id, **fields): resource_name_s, resource_name_p = _g_resource_namelist(lb_resource) req_uri = '/lb/%s/%s' % (resource_name_p, resource_id) return self.show_resource(req_uri, **fields) def _delete_lb(self, lb_resource, resource_id): resource_name_s, resource_name_p = _g_resource_namelist(lb_resource) req_uri = '/lb/%s/%s' % (resource_name_p, resource_id) return self.delete_resource(req_uri) def _create_lb(self, lb_resource, **kwargs): resource_name_s, resource_name_p = _g_resource_namelist(lb_resource) req_uri = '/lb/%s' % (resource_name_p) post_body = {resource_name_s: kwargs} return self.create_resource(req_uri, post_body) def _update_lb(self, lb_resource, resource_id, **kwargs): resource_name_s, resource_name_p = _g_resource_namelist(lb_resource) req_uri = '/lb/%s/%s' % (resource_name_p, resource_id) post_body = {resource_name_s: kwargs} return self.update_resource(req_uri, post_body) def show_agent_hosting_pool(self, pool_id): """Get loadbalancer agent hosting a pool.""" req_uri = "/lb/pools/%s/loadbalancer-agent" % (pool_id) return self.show_resource(req_uri) def associate_health_monitor_with_pool(self, health_monitor_id, pool_id): """Create a mapping between a health monitor and a pool.""" post_body = {'health_monitor': {'id': health_monitor_id}} req_uri = '/lb/pools/%s/%s' % (pool_id, HEALTHMONITOR_RID) return self.create_resource(req_uri, post_body) def create_health_monitor(self, **kwargs): """Create a health monitor.""" create_kwargs = dict( type=kwargs.pop('type', 'TCP'), max_retries=kwargs.pop('nax_retries', 3), timeout=kwargs.pop('timeout', 1), delay=kwargs.pop('delay', 4), ) create_kwargs.update(**kwargs) return self._create_lb(HEALTHMONITOR_RID, **create_kwargs) def delete_health_monitor(self, health_monitor_id): """Delete a given health monitor.""" return self._delete_lb(HEALTHMONITOR_RID, health_monitor_id) def disassociate_health_monitor_with_pool(self, health_monitor_id, pool_id): """Remove a mapping from a health monitor to a pool.""" req_uri = ('/lb/pools/%s/%s/%s' % (pool_id, HEALTHMONITOR_RID, health_monitor_id)) return self.delete_resource(req_uri) def list_health_monitors(self, **filters): """List health monitors that belong to a given tenant.""" return self._list_lb(HEALTHMONITOR_RID, **filters) def show_health_monitor(self, health_monitor_id): """Show information of a given health monitor.""" return self._show_lb(HEALTHMONITOR_RID, health_monitor_id) def update_health_monitor(self, health_monitor_id, show_then_update=False, **kwargs): """Update a given health monitor.""" body = (self.show_health_monitor(health_monitor_id)['health_monitor'] if show_then_update else {}) body.update(**kwargs) return self._update_lb(HEALTHMONITOR_RID, health_monitor_id, **body) # tempest create_member(self,protocol_port, pool, ip_version) # we use pool_id def create_member(self, protocol_port, pool_id, ip_version=4, **kwargs): """Create a member.""" create_kwargs = dict( protocol_port=protocol_port, pool_id=pool_id, address=("fd00:abcd" if ip_version == 6 else "10.0.9.46"), ) create_kwargs.update(**kwargs) return self._create_lb(MEMBER_RID, **create_kwargs) def delete_member(self, member_id): """Delete a given member.""" return self._delete_lb(MEMBER_RID, member_id) def list_members(self, **filters): """List members that belong to a given tenant.""" return self._list_lb(MEMBER_RID, **filters) def show_member(self, member_id): """Show information of a given member.""" return self._show_lb(MEMBER_RID, member_id) def update_member(self, member_id, show_then_update=False, **kwargs): """Update a given member.""" body = (self.show_member(member_id)['member'] if show_then_update else {}) body.update(**kwargs) return self._update_lb(MEMBER_RID, member_id, **body) def create_pool(self, name, lb_method, protocol, subnet_id, **kwargs): """Create a pool.""" lb_method = lb_method or 'ROUND_ROBIN' protocol = protocol or 'HTTP' create_kwargs = dict( name=name, lb_method=lb_method, protocol=protocol, subnet_id=subnet_id, ) create_kwargs.update(kwargs) return self._create_lb(POOL_RID, **create_kwargs) def delete_pool(self, pool_id): """Delete a given pool.""" return self._delete_lb(POOL_RID, pool_id) def list_pools(self, **filters): """List pools that belong to a given tenant.""" return self._list_lb(POOL_RID, **filters) def list_lb_pool_stats(self, pool_id, **filters): """Retrieve stats for a given pool.""" req_uri = '/lb/pools/%s/stats' % (pool_id) return self.list_resources(req_uri, **filters) def list_pool_on_agents(self, **filters): """List the pools on a loadbalancer agent.""" pass def show_pool(self, pool_id): """Show information of a given pool.""" return self._show_lb(POOL_RID, pool_id) def update_pool(self, pool_id, show_then_update=False, **kwargs): """Update a given pool.""" body = (self.show_pool(pool_id)['pool'] if show_then_update else {}) body.update(**kwargs) return self._update_lb(POOL_RID, pool_id, **body) def create_vip(self, pool_id, **kwargs): """Create a vip.""" create_kwargs = dict( pool_id=pool_id, protocol=kwargs.pop('protocol', 'HTTP'), protocol_port=kwargs.pop('protocol_port', 80), name=kwargs.pop('name', None), address=kwargs.pop('address', None), ) for k in create_kwargs.keys(): if create_kwargs[k] is None: create_kwargs.pop(k) create_kwargs.update(**kwargs) # subnet_id needed to create vip return self._create_lb(VIP_RID, **create_kwargs) def delete_vip(self, vip_id): """Delete a given vip.""" return self._delete_lb(VIP_RID, vip_id) def list_vips(self, **filters): """List vips that belong to a given tenant.""" return self._list_lb(VIP_RID, **filters) def show_vip(self, vip_id): """Show information of a given vip.""" return self._show_lb(VIP_RID, vip_id) def update_vip(self, vip_id, show_then_update=False, **kwargs): """Update a given vip.""" body = (self.show_vip(vip_id)['vip'] if show_then_update else {}) body.update(**kwargs) return self._update_lb(VIP_RID, vip_id, **body) # Following 3 methods are specifically to load-balancer V1 client. # They are being implemented by the pareant tempest.lib.common.rest_client # with different calling signatures, only id, no resoure_type. Because, # starting in Liberty release, each resource should have its own client. # Since V1 is deprecated, we are not going to change it, and # copy following 2 methods for V1 LB client only. def wait_for_resource_deletion(self, resource_type, id, client=None): """Waits for a resource to be deleted.""" start_time = int(time.time()) while True: if self.is_resource_deleted(resource_type, id, client=client): return if int(time.time()) - start_time >= self.build_timeout: raise exceptions.TimeoutException time.sleep(self.build_interval) def is_resource_deleted(self, resource_type, id, client=None): if client is None: client = self method = 'show_' + resource_type try: getattr(client, method)(id) except AttributeError: raise Exception(_("Unknown resource type %s ") % resource_type) except lib_exc.NotFound: return True return False def wait_for_resource_status(self, fetch, status, interval=None, timeout=None): """This has different calling signature then rest_client. @summary: Waits for a network resource to reach a status @param fetch: the callable to be used to query the resource status @type fecth: callable that takes no parameters and returns the resource @param status: the status that the resource has to reach @type status: String @param interval: the number of seconds to wait between each status query @type interval: Integer @param timeout: the maximum number of seconds to wait for the resource to reach the desired status @type timeout: Integer """ if not interval: interval = self.build_interval if not timeout: timeout = self.build_timeout start_time = time.time() while time.time() - start_time <= timeout: resource = fetch() if resource['status'] == status: return time.sleep(interval) # At this point, the wait has timed out message = 'Resource %s' % (str(resource)) message += ' failed to reach status %s' % status message += ' (current: %s)' % resource['status'] message += ' within the required time %s' % timeout caller = misc_utils.find_test_caller() if caller: message = '(%s) %s' % (caller, message) raise exceptions.TimeoutException(message) def _g_resource_namelist(lb_resource): if lb_resource[-1] == 's': return (lb_resource[:-1], lb_resource) return (lb_resource, lb_resource + "s") def destroy_tenant_lb(lbv1_client): for o in lbv1_client.list_members(): lbv1_client.delete_member(o['id']) for o in lbv1_client.list_health_monitors(): lbv1_client.delete_health_monitor(o['id']) for o in lbv1_client.list_vips(): lbv1_client.delete_vip(o['id']) for o in lbv1_client.list_pools(): lbv1_client.delete_pool(o['id']) def get_client(client_mgr): """create a v1 load balancer client For itempest user: from itempest import load_our_solar_system as osn from vmware_nsx_tempest.services import load_balancer_v1_client lbv1 = load_balancer_v1_client.get_client(osn.adm.manager) For tempest user: lbv1 = load_balancer_v1_client.get_client(cls.os_adm) """ manager = getattr(client_mgr, 'manager', client_mgr) net_client = getattr(manager, 'networks_client') try: _params = manager.default_params_with_timeout_values.copy() except Exception: _params = {} client = LoadBalancerV1Client(net_client.auth_provider, net_client.service, net_client.region, net_client.endpoint_type, **_params) return client