Skip to content

Commit

Permalink
functional tests + further fixes (#36)
Browse files Browse the repository at this point in the history
functional tests + further fixes

Reviewed-by: Artem Goncharov <Artem.goncharov@gmail.com>
Reviewed-by: None <None>
Reviewed-by: Anton Sidelnikov <None>
  • Loading branch information
kucerakk authored Sep 17, 2021
1 parent 4b81f72 commit 5959169
Show file tree
Hide file tree
Showing 19 changed files with 700 additions and 26 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*.swo
*.swp
*~
AUTHORS
octavia_proxy-*/
.coverage
.idea
Expand Down
Empty file added .stestr.blacklist.functional
Empty file.
6 changes: 6 additions & 0 deletions octavia_proxy/api/drivers/elbv2/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def loadbalancer_create(self, session, loadbalancer):
if 'listeners' in lb_attrs:
lb_attrs.pop('listeners')
lb_attrs.pop('loadbalancer_id', None)
lb_attrs.pop('vip_network_id', None)

lb = session.elb.create_load_balancer(**lb_attrs)

Expand Down Expand Up @@ -314,6 +315,11 @@ def member_create(self, session, pool_id, member):
LOG.debug('Creating member %s' % member.to_dict())
attrs = member.to_dict()

if 'subnet_id' not in attrs:
lb_id = session.elb.get_pool(pool_id)['loadbalancers'][0]['id']
attrs['subnet_id'] = session.elb.get_load_balancer(
lb_id)['vip_subnet_id']

attrs['address'] = attrs.pop('ip_address', None)
attrs.pop('backup', None)
attrs.pop('monitor_port', None)
Expand Down
31 changes: 31 additions & 0 deletions octavia_proxy/api/drivers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.

import copy

from octavia_lib.api.drivers import exceptions as lib_exceptions
from oslo_config import cfg
Expand Down Expand Up @@ -67,3 +68,33 @@ def call_provider(provider, driver_method, *args, **kwargs):
LOG.exception("Provider '%s' raised an unknown error: %s",
provider, str(e))
raise exceptions.ProviderDriverError(prov=provider, user_msg=e)


def _base_to_provider_dict(current_dict, include_project_id=False):
new_dict = copy.deepcopy(current_dict)
for key in [
'provisioning_status', 'operating_status', 'provider',
'created_at', 'updated_at', 'tenant_id', 'tags',
'flavor_id', 'topology', 'vrrp_group', 'amphorae', 'vip',
'listeners', 'pools', 'server_group_id',
]:
new_dict.pop(key, None)
if 'enabled' in new_dict:
new_dict['admin_state_up'] = new_dict.pop('enabled')
if 'project_id' in new_dict and not include_project_id:
del new_dict['project_id']
return new_dict


# Note: The provider dict returned from this method will have provider
# data model objects in it.
def lb_dict_to_provider_dict(lb_dict, vip=None):
new_lb_dict = _base_to_provider_dict(lb_dict, include_project_id=True)
new_lb_dict['loadbalancer_id'] = new_lb_dict.pop('id')
if vip:
new_lb_dict['vip_address'] = vip.ip_address
new_lb_dict['vip_network_id'] = vip.network_id
new_lb_dict['vip_port_id'] = vip.port_id
new_lb_dict['vip_subnet_id'] = vip.subnet_id
new_lb_dict['vip_qos_policy_id'] = vip.qos_policy_id
return new_lb_dict
1 change: 0 additions & 1 deletion octavia_proxy/api/v2/controllers/load_balancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ def _validate_vip_request_object(self, load_balancer, context=None):
def post(self, load_balancer):
"""Creates a load balancer."""
load_balancer = load_balancer.loadbalancer
print(load_balancer.to_dict())
context = pecan_request.context.get('octavia_context')

if not load_balancer.project_id and context.project_id:
Expand Down
2 changes: 1 addition & 1 deletion octavia_proxy/api/v2/controllers/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def post(self, pool_):
pool_dict = pool.to_dict(render_unsets=False)
pool_dict['id'] = None

if listener.default_pool_id:
if listener and listener.default_pool_id:
raise exceptions.DuplicatePoolEntry()

result = driver_utils.call_provider(
Expand Down
3 changes: 1 addition & 2 deletions octavia_proxy/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@
'octavia:Deprecated alias of the Octavia '
'Amphora driver.'),
default={'elbv2': 'The ELBv2 driver.',
'elbv3': 'The ELBv3 driver.'
}),
'elbv3': 'The ELBv3 driver.'}),
cfg.StrOpt('default_provider_driver', default='elbv2',
help=_('Default provider driver.')),
cfg.StrOpt('region', default='eu-de',
Expand Down
232 changes: 225 additions & 7 deletions octavia_proxy/tests/functional/api/v2/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,32 @@

from octavia_proxy.api import config as pconfig

_network = None
_sdk = None
_lb = None


def _destroy_lb(_lb: dict):
if _lb.get('provider') == 'elbv2':
for listener in _sdk.elb.listeners():
if any(lb['id'] == _lb.get('id')
for lb in listener.load_balancers):
for l7policy in _sdk.elb.l7_policies():
if l7policy.get('listener_id') == listener.get('id'):
_sdk.elb.delete_l7_policy(l7policy)
_sdk.elb.delete_listener(listener)
for pool in _sdk.elb.pools(loadbalancer_id=_lb.get('id')):
for member in _sdk.elb.members(pool):
_sdk.elb.delete_member(member, pool)
for hm in _sdk.elb.health_monitors():
if any(pl['id'] == pool.get('id') for pl in hm.pools):
_sdk.elb.delete_health_monitor(hm)
_sdk.elb.delete_pool(pool)
_sdk.elb.delete_load_balancer(_lb.get('id'))
else:
# TODO implement cleanup for elbv3 _sdk.vlb.delete_
pass


class BaseAPITest(base.TestCase):

Expand Down Expand Up @@ -85,13 +111,16 @@ class BaseAPITest(base.TestCase):

def setUp(self):
super().setUp()
self._token = None
self._sdk_connection = None
self.project_id = None
self._sdk_connection = self._get_sdk_connection()
self._token = self._get_token()
self._network = self._create_network()
self.project_id = self._get_project_id()
self.vip_subnet_id = None
self.conf.config(
group='api_settings',
auth_strategy=constants.KEYSTONE_EXT)
self.app = self._make_app()
self._lb = self._create_lb()

def reset_pecan():
pecan.set_config({}, overwrite=True)
Expand All @@ -103,6 +132,73 @@ def tearDown(self):
self._sdk_connection.close()
super().tearDown()

@classmethod
def tearDownClass(cls):
try:
_destroy_lb(_lb)
except Exception:
pass

def _get_sdk_connection(self):
global _sdk
if not _sdk:
_sdk = openstack.connect()
return _sdk

def _create_network(self):
global _network
cidr = '192.168.0.0/16'
ipv4 = 4
router_name = 'octavia-proxy-test-router'
net_name = 'octavia-proxy-test-net'
subnet_name = 'octavia-proxy-test-subnet'

if not _network:
if not self._sdk_connection:
self._sdk_connection = self._get_sdk_connection()
network = self._sdk_connection.network.find_network(net_name)
if not network:
network = self._sdk_connection.network.create_network(
name=net_name)
net_id = network.id
subnet = self._sdk_connection.network.find_subnet(subnet_name)
if not subnet:
subnet = self._sdk_connection.network.create_subnet(
name=subnet_name,
ip_version=ipv4,
network_id=net_id,
cidr=cidr
)
subnet_id = subnet.id

router = self._sdk_connection.network.find_router(router_name)
if not router:
router = self._sdk_connection.network.create_router(
name=router_name)
router.add_interface(
self._sdk_connection.network,
subnet_id=subnet_id)
router_id = router.id

_network = {
'router_id': router_id,
'subnet_id': subnet_id,
'network_id': net_id
}
return _network

def _create_lb(self):
global _lb
if not _lb:
body = {'loadbalancer': {
'name': 'lb-common',
'vip_subnet_id': self._network['subnet_id'],
'project_id': self.project_id}
}
response = self.post(self.LBS_PATH, body)
_lb = response.json.get('loadbalancer')
return _lb

def _make_app(self):
# Note: we need to set argv=() to stop the wsgi setup_app from
# pulling in the testing tool sys.argv
Expand All @@ -124,12 +220,16 @@ def _build_body(self, json):

def _get_token(self):
if not self._sdk_connection:
self._sdk_connection = openstack.connect()
if not self._token:
self._token = self._sdk_connection.auth_token
self.project_id = self._sdk_connection.current_project_id
self._sdk_connection = self._get_sdk_connection()
self._token = self._sdk_connection.auth_token
return self._token

def _get_project_id(self):
if not self._sdk_connection:
self._sdk_connection = self._get_sdk_connection()
self.project_id = self._sdk_connection.current_project_id
return self.project_id

def get(self, path, params=None, headers=None, status=200,
expect_errors=False, authorized=True):
full_path = self._get_full_path(path)
Expand All @@ -145,3 +245,121 @@ def get(self, path, params=None, headers=None, status=200,
expect_errors=expect_errors
)
return response

def get_lb_id(self):
return _lb.get('id')

def post(self, path, body, headers=None, status=201, expect_errors=False,
use_v2_0=False, authorized=True):
headers = headers or {}
if use_v2_0:
full_path = self._get_full_path_v2_0(path)
else:
full_path = self._get_full_path(path)
if authorized:
if not headers:
headers = dict()
headers['X-Auth-Token'] = self._get_token()
response = self.app.post_json(full_path,
params=body,
headers=headers,
status=status,
expect_errors=expect_errors)
return response

def create_load_balancer(self, vip_subnet_id,
**optionals):
req_dict = {'vip_subnet_id': vip_subnet_id,
'project_id': self.project_id}
req_dict.update(optionals)
body = {'loadbalancer': req_dict}
response = self.post(self.LBS_PATH, body)
return response.json

def delete(self, path, headers=None, params=None, status=204,
expect_errors=False, authorized=True):
headers = headers or {}
params = params or {}
full_path = self._get_full_path(path)
param_string = ""
for k, v in params.items():
param_string += "{key}={value}&".format(key=k, value=v)
if param_string:
full_path = "{path}?{params}".format(
path=full_path, params=param_string.rstrip("&"))
if authorized:
if not headers:
headers = dict()
headers['X-Auth-Token'] = self._get_token()
response = self.app.delete(full_path,
headers=headers,
status=status,
expect_errors=expect_errors)
return response

def create_listener(self, protocol, protocol_port, lb_id,
status=None, **optionals):
req_dict = {'protocol': protocol, 'protocol_port': protocol_port,
'loadbalancer_id': lb_id}
req_dict.update(optionals)
path = self.LISTENERS_PATH
body = {'listener': req_dict}
status = {'status': status} if status else {}
response = self.post(path, body, **status)
return response.json

def create_pool(self, lb_id, protocol, lb_algorithm,
status=None, **optionals):
req_dict = {'loadbalancer_id': lb_id, 'protocol': protocol,
'lb_algorithm': lb_algorithm}
req_dict.update(optionals)
body = {'pool': req_dict}
path = self.POOLS_PATH
status = {'status': status} if status else {}
response = self.post(path, body, **status)
return response.json

def create_member(self, pool_id, address, protocol_port,
status=None, **optionals):
req_dict = {'address': address, 'protocol_port': protocol_port}
req_dict.update(optionals)
body = {'member': req_dict}
path = self.MEMBERS_PATH.format(pool_id=pool_id)
status = {'status': status} if status else {}
response = self.post(path, body, **status)
return response.json

def create_health_monitor(self, pool_id, type, delay, timeout,
max_retries_down, max_retries,
status=None, **optionals):
req_dict = {'pool_id': pool_id,
'type': type,
'delay': delay,
'timeout': timeout,
'max_retries_down': max_retries_down,
'max_retries': max_retries}
req_dict.update(optionals)
body = {'healthmonitor': req_dict}
path = self.HMS_PATH
status = {'status': status} if status else {}
response = self.post(path, body, **status)
return response.json

def create_l7policy(self, listener_id, action, status=None, **optionals):
req_dict = {'listener_id': listener_id, 'action': action}
req_dict.update(optionals)
body = {'l7policy': req_dict}
path = self.L7POLICIES_PATH
status = {'status': status} if status else {}
response = self.post(path, body, **status)
return response.json

def create_l7rule(self, l7policy_id, type, compare_type,
value, status=None, **optionals):
req_dict = {'type': type, 'compare_type': compare_type, 'value': value}
req_dict.update(optionals)
body = {'rule': req_dict}
path = self.L7RULES_PATH.format(l7policy_id=l7policy_id)
status = {'status': status} if status else {}
response = self.post(path, body, **status)
return response.json
Loading

0 comments on commit 5959169

Please sign in to comment.