Merge "nb: add support for lb health checks API"
This commit is contained in:
commit
96cf8d6288
@ -912,6 +912,88 @@ class API(api.API, metaclass=abc.ABCMeta):
|
||||
def lb_list(self):
|
||||
"""Get the UUIDs of all load balanacers"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def lb_get(self, lb):
|
||||
"""Get load balancer for 'lb'
|
||||
|
||||
:returns: :class:`Command` with RowView result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def lb_add_health_check(self, lb, vip, **options):
|
||||
"""Add health check for 'lb'
|
||||
|
||||
:param lb: The name or uuid of a load balancer
|
||||
:type lb: string or uuid.UUID
|
||||
:param vip: A virtual IP
|
||||
:type vip: string
|
||||
:param options: keys and values for the port 'options' dict
|
||||
:type options: key: string, value: string
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def lb_del_health_check(self, lb, hc_uuid, if_exists=False):
|
||||
"""Remove health check from 'lb'
|
||||
|
||||
:param lb: The name or uuid of a load balancer
|
||||
:type lb: string or uuid.UUID
|
||||
:param hc_uuid: uuid of a health check
|
||||
:type hc_uuid: uuid.UUID
|
||||
:param if_exists: If True, don't fail if the hc_uuid doesn't exist
|
||||
:type if_exists: boolean
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def lb_add_ip_port_mapping(self, lb, endpoint_ip, port_name, source_ip):
|
||||
"""Add IP port mapping to 'lb'
|
||||
|
||||
Maps from endpoint IP to a colon-separated pair of logical port name
|
||||
and source IP, e.g. port_name:sourc_ip.
|
||||
|
||||
:param lb: The name or uuid of a load balancer
|
||||
:type lb: string or uuid.UUID
|
||||
:param endpoint_ip: IPv4 address
|
||||
:type endpoint_ip: string
|
||||
:param port_name: The name of a logical port
|
||||
:type port_name: string
|
||||
:param source_ip: IPv4 address
|
||||
:type source_ip: string
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def lb_del_ip_port_mapping(self, lb, endpoint_ip):
|
||||
"""Remove IP port mapping from 'lb'
|
||||
|
||||
:param lb: The name or uuid of a load balancer
|
||||
:type lb: string or uuid.UUID
|
||||
:param endpoint_ip: IPv4 address
|
||||
:type endpoint_ip: string
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def health_check_set_options(self, hc_uuid, **options):
|
||||
"""Set options to the 'health_check'
|
||||
|
||||
:param hc_uuid: uuid of the health check
|
||||
:type hc_uuid: uuid.UUID
|
||||
:param options: keys and values for the port 'options' dict
|
||||
:type options: key: string, value: string
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def health_check_get_options(self, hc_uuid):
|
||||
"""Get the options for 'health_check'
|
||||
|
||||
:param hc_uuid: uuid of the health check
|
||||
:type hc_uuid: uuid.UUID
|
||||
:returns: :class:`Command` with dict result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def lr_lb_add(self, router, lb, may_exist=False):
|
||||
"""Add a load-balancer to 'router'
|
||||
|
@ -1376,6 +1376,100 @@ class LbListCommand(cmd.ReadOnlyCommand):
|
||||
for r in self.api.tables['Load_Balancer'].rows.values()]
|
||||
|
||||
|
||||
class LbGetCommand(cmd.BaseGetRowCommand):
|
||||
table = 'Load_Balancer'
|
||||
|
||||
|
||||
class LbAddHealthCheckCommand(cmd.BaseCommand):
|
||||
table = 'Load_Balancer'
|
||||
|
||||
def __init__(self, api, lb, vip, **options):
|
||||
super().__init__(api)
|
||||
self.lb = lb
|
||||
self.vip = vip
|
||||
self.options = options
|
||||
|
||||
def run_idl(self, txn):
|
||||
lb = self.api.lookup(self.table, self.lb)
|
||||
cmd = HealthCheckAddCommand(self.api, self.vip, **self.options)
|
||||
cmd.run_idl(txn)
|
||||
lb.addvalue('health_check', cmd.result)
|
||||
|
||||
|
||||
class LbDelHealthCheckCommand(cmd.BaseCommand):
|
||||
table = 'Load_Balancer'
|
||||
|
||||
def __init__(self, api, lb, hc_uuid, if_exists=False):
|
||||
super().__init__(api)
|
||||
self.lb = lb
|
||||
self.hc_uuid = hc_uuid
|
||||
self.if_exists = if_exists
|
||||
|
||||
def run_idl(self, txn):
|
||||
lb = self.api.lookup(self.table, self.lb)
|
||||
for health_check in lb.health_check:
|
||||
if health_check.uuid == self.hc_uuid:
|
||||
lb.delvalue('health_check', health_check)
|
||||
health_check.delete()
|
||||
return
|
||||
if not self.if_exists:
|
||||
msg = "Health check '%s' on lb %s does not exist" % (
|
||||
self.hc_uuid, self.lb)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
class LbAddIpPortMappingСommand(cmd.BaseCommand):
|
||||
table = 'Load_Balancer'
|
||||
|
||||
def __init__(self, api, lb, endpoint_ip, port_name, source_ip):
|
||||
super().__init__(api)
|
||||
self.lb = lb
|
||||
self.endpoint_ip = str(netaddr.IPAddress(endpoint_ip))
|
||||
self.port_name = port_name
|
||||
self.source_ip = str(netaddr.IPAddress(source_ip))
|
||||
|
||||
def run_idl(self, txn):
|
||||
lb = self.api.lookup(self.table, self.lb)
|
||||
lb.setkey('ip_port_mappings', self.endpoint_ip,
|
||||
'%s:%s' % (self.port_name, self.source_ip))
|
||||
|
||||
|
||||
class LbDelIpPortMappingCommand(cmd.BaseCommand):
|
||||
table = 'Load_Balancer'
|
||||
|
||||
def __init__(self, api, lb, endpoint_ip):
|
||||
super().__init__(api)
|
||||
self.lb = lb
|
||||
self.endpoint_ip = str(netaddr.IPAddress(endpoint_ip))
|
||||
|
||||
def run_idl(self, txn):
|
||||
lb = self.api.lookup(self.table, self.lb)
|
||||
lb.delkey('ip_port_mappings', self.endpoint_ip)
|
||||
|
||||
|
||||
class HealthCheckAddCommand(cmd.AddCommand):
|
||||
table_name = 'Load_Balancer_Health_Check'
|
||||
|
||||
def __init__(self, api, vip, **options):
|
||||
super().__init__(api)
|
||||
self.vip = utils.normalize_ip_port(vip)
|
||||
self.options = options
|
||||
|
||||
def run_idl(self, txn):
|
||||
hc = txn.insert(self.api.tables[self.table_name])
|
||||
hc.vip = self.vip
|
||||
hc.options = self.options
|
||||
self.result = hc
|
||||
|
||||
|
||||
class HealthCheckSetOptionsCommand(cmd.BaseSetOptionsCommand):
|
||||
table = 'Load_Balancer_Health_Check'
|
||||
|
||||
|
||||
class HealthCheckGetOptionsCommand(cmd.BaseGetOptionsCommand):
|
||||
table = 'Load_Balancer_Health_Check'
|
||||
|
||||
|
||||
class LrLbAddCommand(cmd.BaseCommand):
|
||||
def __init__(self, api, router, lb, may_exist=False):
|
||||
super().__init__(api)
|
||||
|
@ -279,6 +279,28 @@ class OvnNbApiIdlImpl(ovs_idl.Backend, api.API):
|
||||
def lb_list(self):
|
||||
return cmd.LbListCommand(self)
|
||||
|
||||
def lb_get(self, lb):
|
||||
return cmd.LbGetCommand(self, lb)
|
||||
|
||||
def lb_add_health_check(self, lb, vip, **options):
|
||||
return cmd.LbAddHealthCheckCommand(self, lb, vip, **options)
|
||||
|
||||
def lb_del_health_check(self, lb, hc_uuid, if_exists=False):
|
||||
return cmd.LbDelHealthCheckCommand(self, lb, hc_uuid, if_exists)
|
||||
|
||||
def lb_add_ip_port_mapping(self, lb, endport_ip, port_name, source_ip):
|
||||
return cmd.LbAddIpPortMappingСommand(self, lb, endport_ip,
|
||||
port_name, source_ip)
|
||||
|
||||
def lb_del_ip_port_mapping(self, lb, endport_ip):
|
||||
return cmd.LbDelIpPortMappingCommand(self, lb, endport_ip)
|
||||
|
||||
def health_check_set_options(self, hc_uuid, **options):
|
||||
return cmd.HealthCheckSetOptionsCommand(self, hc_uuid, **options)
|
||||
|
||||
def health_check_get_options(self, hc_uuid):
|
||||
return cmd.HealthCheckGetOptionsCommand(self, hc_uuid)
|
||||
|
||||
def lr_lb_add(self, router, lb, may_exist=False):
|
||||
return cmd.LrLbAddCommand(self, router, lb, may_exist)
|
||||
|
||||
|
@ -1715,6 +1715,109 @@ class TestLoadBalancerOps(OvnNorthboundTest):
|
||||
lbset = self.api.lb_list().execute(check_error=True)
|
||||
self.assertTrue(lbs.issubset(lbset))
|
||||
|
||||
def _test_lb_get(self, col):
|
||||
lb = self._lb_add(utils.get_rand_device_name(),
|
||||
'192.0.0.1', ['10.0.0.1'])
|
||||
val = getattr(lb, col)
|
||||
found = self.api.lb_get(val).execute(check_error=True)
|
||||
self.assertEqual(lb, found)
|
||||
|
||||
def test_lb_get_uuid(self):
|
||||
self._test_lb_get('uuid')
|
||||
|
||||
def test_lb_get_name(self):
|
||||
self._test_lb_get('name')
|
||||
|
||||
def _test_lb_add_del_health_check(self, col):
|
||||
hc_options = {
|
||||
'interval': '2',
|
||||
'timeout': '10',
|
||||
'success_count': '3',
|
||||
'failure_count': '3',
|
||||
}
|
||||
hc_vip = '172.31.0.1'
|
||||
|
||||
lb = self._lb_add(utils.get_rand_device_name(),
|
||||
'192.0.0.1', ['10.0.0.1'])
|
||||
self.assertEqual(lb.health_check, [])
|
||||
val = getattr(lb, col)
|
||||
self.api.lb_add_health_check(val,
|
||||
hc_vip,
|
||||
**hc_options).execute(check_error=True)
|
||||
self.assertEqual(len(lb.health_check), 1)
|
||||
hc = self.api.lookup('Load_Balancer_Health_Check',
|
||||
lb.health_check[0].uuid)
|
||||
self.assertEqual(hc.vip, hc_vip)
|
||||
self.assertEqual(hc.options, hc_options)
|
||||
|
||||
self.api.lb_del_health_check(val, hc.uuid).execute(check_error=True)
|
||||
self.assertEqual(len(lb.health_check), 0)
|
||||
self.assertNotIn(hc.uuid,
|
||||
self.api.tables['Load_Balancer_Health_Check'].rows)
|
||||
|
||||
def test_lb_add_del_health_check_uuid(self):
|
||||
self._test_lb_add_del_health_check('uuid')
|
||||
|
||||
def test_lb_add_del_health_check_name(self):
|
||||
self._test_lb_add_del_health_check('name')
|
||||
|
||||
def test_lb_del_health_check_if_exists(self):
|
||||
lb = self._lb_add(utils.get_rand_device_name(),
|
||||
'192.0.0.1', ['10.0.0.1'])
|
||||
self.api.lb_del_health_check(lb.name, uuid.uuid4(),
|
||||
if_exists=True).execute(check_error=True)
|
||||
|
||||
def _test_lb_add_del_ip_port_mapping(self, col):
|
||||
endpoint_ip = '172.31.0.4'
|
||||
port_name = 'sw1-p1'
|
||||
source_ip = '172.31.0.6'
|
||||
lb = self._lb_add(utils.get_rand_device_name(),
|
||||
'192.0.0.1', ['10.0.0.1'])
|
||||
self.assertEqual(lb.ip_port_mappings, {})
|
||||
val = getattr(lb, col)
|
||||
self.api.lb_add_ip_port_mapping(val,
|
||||
endpoint_ip,
|
||||
port_name,
|
||||
source_ip).execute(check_error=True)
|
||||
self.assertEqual(lb.ip_port_mappings[endpoint_ip],
|
||||
'%s:%s' % (port_name, source_ip))
|
||||
|
||||
self.api.lb_del_ip_port_mapping(val,
|
||||
endpoint_ip).execute(check_error=True)
|
||||
self.assertEqual(lb.ip_port_mappings, {})
|
||||
|
||||
def test_lb_add_del_ip_port_mapping_uuid(self):
|
||||
self._test_lb_add_del_ip_port_mapping('uuid')
|
||||
|
||||
def test_lb_add_del_ip_port_mapping_name(self):
|
||||
self._test_lb_add_del_ip_port_mapping('name')
|
||||
|
||||
def test_hc_get_set_options(self):
|
||||
hc_options = {
|
||||
'interval': '2',
|
||||
'timeout': '10',
|
||||
'success_count': '3',
|
||||
'failure_count': '3',
|
||||
}
|
||||
lb = self._lb_add(utils.get_rand_device_name(),
|
||||
'192.0.0.1', ['10.0.0.1'])
|
||||
self.api.lb_add_health_check(lb.uuid,
|
||||
'172.31.0.1',
|
||||
**hc_options).execute(check_error=True)
|
||||
hc = self.api.lookup('Load_Balancer_Health_Check',
|
||||
lb.health_check[0].uuid)
|
||||
options = self.api.health_check_get_options(
|
||||
hc.uuid).execute(check_error=True)
|
||||
self.assertEqual(hc_options, options)
|
||||
|
||||
options.update({
|
||||
'interval': '5',
|
||||
'new-option': 'option',
|
||||
})
|
||||
self.api.health_check_set_options(hc.uuid,
|
||||
**options).execute(check_error=True)
|
||||
self.assertEqual(hc.options, options)
|
||||
|
||||
|
||||
class TestObLbOps(testscenarios.TestWithScenarios, OvnNorthboundTest):
|
||||
scenarios = [
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added functions and commands to add, delete, list and update records of
|
||||
'Load_Balancer_Health_Check' table. Also added a method to get one load balancer
|
||||
by name or uuid and methods to modify 'ip_port_mappings' column in the load balancer.
|
Loading…
x
Reference in New Issue
Block a user