[API] Completed TCP Timeout work
Change-Id: Ie512dc5758609d0d0601f448984846b124647e24
This commit is contained in:
@@ -32,7 +32,7 @@ from libra.common.api.lbaas import loadbalancers_devices, Limits, Vip, Ports
|
|||||||
from libra.common.api.lbaas import HealthMonitor
|
from libra.common.api.lbaas import HealthMonitor
|
||||||
from libra.common.exc import ExhaustedError
|
from libra.common.exc import ExhaustedError
|
||||||
from libra.api.model.validators import LBPut, LBPost, LBResp, LBVipResp
|
from libra.api.model.validators import LBPut, LBPost, LBResp, LBVipResp
|
||||||
from libra.api.model.validators import LBRespNode
|
from libra.api.model.validators import LBRespNode, LBOptions
|
||||||
from libra.common.api.gearman_client import submit_job
|
from libra.common.api.gearman_client import submit_job
|
||||||
from libra.api.acl import get_limited_to_project
|
from libra.api.acl import get_limited_to_project
|
||||||
from libra.api.library.exp import OverLimit, IPOutOfRange, NotFound
|
from libra.api.library.exp import OverLimit, IPOutOfRange, NotFound
|
||||||
@@ -44,6 +44,12 @@ from wsme import types as wtypes
|
|||||||
|
|
||||||
|
|
||||||
class LoadBalancersController(RestController):
|
class LoadBalancersController(RestController):
|
||||||
|
|
||||||
|
LB_TIMEOUT_MS = 30000
|
||||||
|
LB_TIMEOUT_MAX = 1000000
|
||||||
|
LB_RETRIES = 3
|
||||||
|
LB_RETRIES_MAX = 256
|
||||||
|
|
||||||
def __init__(self, lbid=None):
|
def __init__(self, lbid=None):
|
||||||
self.lbid = lbid
|
self.lbid = lbid
|
||||||
|
|
||||||
@@ -77,7 +83,8 @@ class LoadBalancersController(RestController):
|
|||||||
LoadBalancer.protocol,
|
LoadBalancer.protocol,
|
||||||
LoadBalancer.port, LoadBalancer.algorithm,
|
LoadBalancer.port, LoadBalancer.algorithm,
|
||||||
LoadBalancer.status, LoadBalancer.created,
|
LoadBalancer.status, LoadBalancer.created,
|
||||||
LoadBalancer.updated
|
LoadBalancer.updated, LoadBalancer.timeout,
|
||||||
|
LoadBalancer.retries
|
||||||
).filter(LoadBalancer.tenantid == tenant_id).\
|
).filter(LoadBalancer.tenantid == tenant_id).\
|
||||||
filter(LoadBalancer.status == 'DELETED').all()
|
filter(LoadBalancer.status == 'DELETED').all()
|
||||||
else:
|
else:
|
||||||
@@ -86,7 +93,8 @@ class LoadBalancersController(RestController):
|
|||||||
LoadBalancer.protocol,
|
LoadBalancer.protocol,
|
||||||
LoadBalancer.port, LoadBalancer.algorithm,
|
LoadBalancer.port, LoadBalancer.algorithm,
|
||||||
LoadBalancer.status, LoadBalancer.created,
|
LoadBalancer.status, LoadBalancer.created,
|
||||||
LoadBalancer.updated
|
LoadBalancer.updated, LoadBalancer.timeout,
|
||||||
|
LoadBalancer.retries
|
||||||
).filter(LoadBalancer.tenantid == tenant_id).\
|
).filter(LoadBalancer.tenantid == tenant_id).\
|
||||||
filter(LoadBalancer.status != 'DELETED').all()
|
filter(LoadBalancer.status != 'DELETED').all()
|
||||||
load_balancers = {'loadBalancers': []}
|
load_balancers = {'loadBalancers': []}
|
||||||
@@ -96,6 +104,20 @@ class LoadBalancersController(RestController):
|
|||||||
lb['nodeCount'] = session.query(Node).\
|
lb['nodeCount'] = session.query(Node).\
|
||||||
filter(Node.lbid == lb['id']).count()
|
filter(Node.lbid == lb['id']).count()
|
||||||
lb['id'] = str(lb['id'])
|
lb['id'] = str(lb['id'])
|
||||||
|
|
||||||
|
# Unset options get set to default values
|
||||||
|
lb['options'] = {}
|
||||||
|
if lb['timeout']:
|
||||||
|
lb['options']['timeout'] = lb['timeout']
|
||||||
|
else:
|
||||||
|
lb['options']['timeout'] = self.LB_TIMEOUT_MS
|
||||||
|
if lb['retries']:
|
||||||
|
lb['options']['retries'] = lb['retries']
|
||||||
|
else:
|
||||||
|
lb['options']['retries'] = self.LB_RETRIES
|
||||||
|
del(lb['timeout'])
|
||||||
|
del(lb['retries'])
|
||||||
|
|
||||||
load_balancers['loadBalancers'].append(lb)
|
load_balancers['loadBalancers'].append(lb)
|
||||||
else:
|
else:
|
||||||
load_balancers = session.query(
|
load_balancers = session.query(
|
||||||
@@ -103,6 +125,7 @@ class LoadBalancersController(RestController):
|
|||||||
LoadBalancer.port, LoadBalancer.algorithm,
|
LoadBalancer.port, LoadBalancer.algorithm,
|
||||||
LoadBalancer.status, LoadBalancer.created,
|
LoadBalancer.status, LoadBalancer.created,
|
||||||
LoadBalancer.updated, LoadBalancer.errmsg,
|
LoadBalancer.updated, LoadBalancer.errmsg,
|
||||||
|
LoadBalancer.timeout, LoadBalancer.retries,
|
||||||
Vip.id.label('vipid'), Vip.ip
|
Vip.id.label('vipid'), Vip.ip
|
||||||
).join(LoadBalancer.devices).\
|
).join(LoadBalancer.devices).\
|
||||||
outerjoin(Device.vip).\
|
outerjoin(Device.vip).\
|
||||||
@@ -168,6 +191,21 @@ class LoadBalancersController(RestController):
|
|||||||
del node['weight']
|
del node['weight']
|
||||||
load_balancers['nodes'].append(node)
|
load_balancers['nodes'].append(node)
|
||||||
|
|
||||||
|
# Unset options get set to default values
|
||||||
|
load_balancers['options'] = {}
|
||||||
|
if load_balancers['timeout']:
|
||||||
|
load_balancers['options']['timeout'] =\
|
||||||
|
load_balancers['timeout']
|
||||||
|
else:
|
||||||
|
load_balancers['options']['timeout'] = self.LB_TIMEOUT_MS
|
||||||
|
if load_balancers['retries']:
|
||||||
|
load_balancers['options']['retries'] =\
|
||||||
|
load_balancers['retries']
|
||||||
|
else:
|
||||||
|
load_balancers['options']['retries'] = self.LB_RETRIES
|
||||||
|
del(load_balancers['timeout'])
|
||||||
|
del(load_balancers['retries'])
|
||||||
|
|
||||||
session.rollback()
|
session.rollback()
|
||||||
response.status = 200
|
response.status = 200
|
||||||
return load_balancers
|
return load_balancers
|
||||||
@@ -252,19 +290,33 @@ class LoadBalancersController(RestController):
|
|||||||
num_galera_primary_nodes += 1
|
num_galera_primary_nodes += 1
|
||||||
|
|
||||||
# Options defaults
|
# Options defaults
|
||||||
client_timeout_ms = 30000
|
timeout_ms = self.LB_TIMEOUT_MS
|
||||||
server_timeout_ms = 30000
|
retries = self.LB_RETRIES
|
||||||
connect_timeout_ms = 30000
|
|
||||||
connect_retries = 3
|
|
||||||
if body.options:
|
if body.options:
|
||||||
if body.options.client_timeout != Unset:
|
if body.options.timeout != Unset:
|
||||||
client_timeout_ms = body.options.client_timeout
|
try:
|
||||||
if body.options.server_timeout != Unset:
|
timeout_ms = int(body.options.timeout)
|
||||||
server_timeout_ms = body.options.server_timeout
|
if timeout_ms < 0 or timeout_ms > self.LB_TIMEOUT_MAX:
|
||||||
if body.options.connect_timeout != Unset:
|
raise ClientSideError(
|
||||||
connect_timeout_ms = body.options.connect_timeout
|
'timeout must be between 0 and {0} ms'
|
||||||
if body.options.connect_retries != Unset:
|
.format(self.LB_TIMEOUT_MAX)
|
||||||
connect_retries = body.options.connect_retries
|
)
|
||||||
|
except ValueError:
|
||||||
|
raise ClientSideError(
|
||||||
|
'timeout must be an integer'
|
||||||
|
)
|
||||||
|
if body.options.retries != Unset:
|
||||||
|
try:
|
||||||
|
retries = int(body.options.retries)
|
||||||
|
if retries < 0 or retries > self.LB_RETRIES_MAX:
|
||||||
|
raise ClientSideError(
|
||||||
|
'retries must be between 0 and {0}'
|
||||||
|
.format(self.LB_RETRIES_MAX)
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
raise ClientSideError(
|
||||||
|
'retries must be an integer'
|
||||||
|
)
|
||||||
|
|
||||||
# Galera sanity checks
|
# Galera sanity checks
|
||||||
if is_galera and num_galera_primary_nodes != 1:
|
if is_galera and num_galera_primary_nodes != 1:
|
||||||
@@ -431,10 +483,8 @@ class LoadBalancersController(RestController):
|
|||||||
else:
|
else:
|
||||||
lb.algorithm = 'ROUND_ROBIN'
|
lb.algorithm = 'ROUND_ROBIN'
|
||||||
|
|
||||||
lb.client_timeout = client_timeout_ms
|
lb.timeout = timeout_ms
|
||||||
lb.server_timeout = server_timeout_ms
|
lb.retries = retries
|
||||||
lb.connect_timeout = connect_timeout_ms
|
|
||||||
lb.connect_retries = connect_retries
|
|
||||||
|
|
||||||
lb.devices = [device]
|
lb.devices = [device]
|
||||||
# write to database
|
# write to database
|
||||||
@@ -491,20 +541,42 @@ class LoadBalancersController(RestController):
|
|||||||
address=None, id=None, type='ASSIGNING', ipVersion='IPV4'
|
address=None, id=None, type='ASSIGNING', ipVersion='IPV4'
|
||||||
)
|
)
|
||||||
return_data.virtualIps = [vip_resp]
|
return_data.virtualIps = [vip_resp]
|
||||||
|
|
||||||
|
nodes = session.query(
|
||||||
|
Node.id, Node.address, Node.port, Node.status,
|
||||||
|
Node.enabled, Node.weight
|
||||||
|
).join(LoadBalancer.nodes).\
|
||||||
|
filter(LoadBalancer.tenantid == tenant_id).\
|
||||||
|
filter(LoadBalancer.id == lb.id).\
|
||||||
|
all()
|
||||||
|
|
||||||
return_data.nodes = []
|
return_data.nodes = []
|
||||||
for node in body.nodes:
|
for node in nodes:
|
||||||
if node.weight != Unset and node.weight != 1:
|
if node.enabled == 1:
|
||||||
out_node = LBRespNode(
|
condition = 'ENABLED'
|
||||||
port=str(node.port), address=node.address,
|
else:
|
||||||
condition=node.condition, weight=weight
|
condition = 'DISABLED'
|
||||||
|
|
||||||
|
if node.weight == 1:
|
||||||
|
return_data.nodes.append(
|
||||||
|
LBRespNode(
|
||||||
|
id=str(node.id), port=str(node.port),
|
||||||
|
address=node.address, condition=condition,
|
||||||
|
status=node.status
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
out_node = LBRespNode(
|
return_data.nodes.append(
|
||||||
port=str(node.port), address=node.address,
|
LBRespNode(
|
||||||
condition=node.condition
|
id=str(node.id), port=str(node.port),
|
||||||
|
address=node.address, condition=condition,
|
||||||
|
status=node.status, weight=str(node.weight)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return_data.nodes.append(out_node)
|
return_data.options = LBOptions(timeout=timeout_ms,
|
||||||
|
retries=retries)
|
||||||
|
|
||||||
session.commit()
|
session.commit()
|
||||||
# trigger gearman client to create new lb
|
# trigger gearman client to create new lb
|
||||||
submit_job(
|
submit_job(
|
||||||
@@ -551,6 +623,34 @@ class LoadBalancersController(RestController):
|
|||||||
if body.algorithm != Unset:
|
if body.algorithm != Unset:
|
||||||
lb.algorithm = body.algorithm
|
lb.algorithm = body.algorithm
|
||||||
|
|
||||||
|
if body.options:
|
||||||
|
if body.options.timeout != Unset:
|
||||||
|
try:
|
||||||
|
timeout_ms = int(body.options.timeout)
|
||||||
|
if timeout_ms < 0 or timeout_ms > self.LB_TIMEOUT_MAX:
|
||||||
|
raise ClientSideError(
|
||||||
|
'timeout must be between 0 and {0} ms'
|
||||||
|
.format(self.LB_TIMEOUT_MAX)
|
||||||
|
)
|
||||||
|
lb.timeout = timeout_ms
|
||||||
|
except ValueError:
|
||||||
|
raise ClientSideError(
|
||||||
|
'timeout must be an integer'
|
||||||
|
)
|
||||||
|
if body.options.retries != Unset:
|
||||||
|
try:
|
||||||
|
retries = int(body.options.retries)
|
||||||
|
if retries < 0 or retries > self.LB_RETRIES_MAX:
|
||||||
|
raise ClientSideError(
|
||||||
|
'retries must be between 0 and {0}'
|
||||||
|
.format(self.LB_RETRIES_MAX)
|
||||||
|
)
|
||||||
|
lb.retries = retries
|
||||||
|
except ValueError:
|
||||||
|
raise ClientSideError(
|
||||||
|
'retries must be an integer'
|
||||||
|
)
|
||||||
|
|
||||||
lb.status = 'PENDING_UPDATE'
|
lb.status = 'PENDING_UPDATE'
|
||||||
device = session.query(
|
device = session.query(
|
||||||
Device.id, Device.name, Device.status
|
Device.id, Device.name, Device.status
|
||||||
|
@@ -27,10 +27,12 @@ class LBNode(Base):
|
|||||||
|
|
||||||
|
|
||||||
class LBRespNode(Base):
|
class LBRespNode(Base):
|
||||||
|
id = wtypes.text
|
||||||
port = wtypes.text
|
port = wtypes.text
|
||||||
address = wtypes.text
|
address = wtypes.text
|
||||||
condition = wtypes.text
|
condition = wtypes.text
|
||||||
weight = int
|
status = wtypes.text
|
||||||
|
weight = wtypes.text
|
||||||
|
|
||||||
|
|
||||||
class LBNodePut(Base):
|
class LBNodePut(Base):
|
||||||
@@ -60,10 +62,8 @@ class LBVip(Base):
|
|||||||
|
|
||||||
|
|
||||||
class LBOptions(Base):
|
class LBOptions(Base):
|
||||||
client_timeout = int
|
timeout = int
|
||||||
server_timeout = int
|
retries = int
|
||||||
connect_timeout = int
|
|
||||||
connect_retries = int
|
|
||||||
|
|
||||||
|
|
||||||
class LBPost(Base):
|
class LBPost(Base):
|
||||||
@@ -79,6 +79,7 @@ class LBPost(Base):
|
|||||||
class LBPut(Base):
|
class LBPut(Base):
|
||||||
name = wtypes.text
|
name = wtypes.text
|
||||||
algorithm = Enum(wtypes.text, 'ROUND_ROBIN', 'LEAST_CONNECTIONS')
|
algorithm = Enum(wtypes.text, 'ROUND_ROBIN', 'LEAST_CONNECTIONS')
|
||||||
|
options = wsattr('LBOptions')
|
||||||
|
|
||||||
|
|
||||||
class LBVipResp(Base):
|
class LBVipResp(Base):
|
||||||
@@ -106,6 +107,7 @@ class LBResp(Base):
|
|||||||
updated = wtypes.text
|
updated = wtypes.text
|
||||||
virtualIps = wsattr(['LBVipResp'])
|
virtualIps = wsattr(['LBVipResp'])
|
||||||
nodes = wsattr(['LBRespNode'])
|
nodes = wsattr(['LBRespNode'])
|
||||||
|
options = wsattr('LBOptions')
|
||||||
|
|
||||||
|
|
||||||
class LBMonitorPut(Base):
|
class LBMonitorPut(Base):
|
||||||
|
@@ -443,13 +443,12 @@ class GearmanClientThread(object):
|
|||||||
# All new LBs created since these options were supported
|
# All new LBs created since these options were supported
|
||||||
# will have default values in the DB. Pre-existing LBs will
|
# will have default values in the DB. Pre-existing LBs will
|
||||||
# not have any values, so we need to check for that.
|
# not have any values, so we need to check for that.
|
||||||
if any([lb.client_timeout, lb.server_timeout,
|
if any([lb.timeout, lb.retries]):
|
||||||
lb.connect_timeout, lb.connect_retries]):
|
|
||||||
lb_data['options'] = {
|
lb_data['options'] = {
|
||||||
'client_timeout': lb.client_timeout,
|
'client_timeout': lb.timeout,
|
||||||
'server_timeout': lb.server_timeout,
|
'server_timeout': lb.timeout,
|
||||||
'connect_timeout': lb.connect_timeout,
|
'connect_timeout': lb.timeout,
|
||||||
'connect_retries': lb.connect_retries
|
'connect_retries': lb.retries
|
||||||
}
|
}
|
||||||
|
|
||||||
lb_data['monitor'] = monitor_data
|
lb_data['monitor'] = monitor_data
|
||||||
|
@@ -111,10 +111,8 @@ class LoadBalancer(DeclarativeBase):
|
|||||||
tenantid = Column(u'tenantid', VARCHAR(length=128), nullable=False)
|
tenantid = Column(u'tenantid', VARCHAR(length=128), nullable=False)
|
||||||
updated = Column(u'updated', FormatedDateTime(), nullable=False)
|
updated = Column(u'updated', FormatedDateTime(), nullable=False)
|
||||||
created = Column(u'created', FormatedDateTime(), nullable=False)
|
created = Column(u'created', FormatedDateTime(), nullable=False)
|
||||||
client_timeout = Column(u'client_timeout', INTEGER(), nullable=True)
|
timeout = Column(u'timeout', INTEGER(), nullable=True)
|
||||||
server_timeout = Column(u'server_timeout', INTEGER(), nullable=True)
|
retries = Column(u'retries', INTEGER(), nullable=True)
|
||||||
connect_timeout = Column(u'connect_timeout', INTEGER(), nullable=True)
|
|
||||||
connect_retries = Column(u'connect_retries', INTEGER(), nullable=True)
|
|
||||||
nodes = relationship(
|
nodes = relationship(
|
||||||
'Node', backref=backref('loadbalancers', order_by='Node.id')
|
'Node', backref=backref('loadbalancers', order_by='Node.id')
|
||||||
)
|
)
|
||||||
|
@@ -26,10 +26,8 @@ CREATE TABLE loadbalancers (
|
|||||||
created TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', # timestamp of when LB was created
|
created TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', # timestamp of when LB was created
|
||||||
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, # timestamp of when LB was last updated
|
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, # timestamp of when LB was last updated
|
||||||
errmsg VARCHAR(128) DEFAULT NULL, # optional error message which can describe details regarding LBs state, can be blank if no error state exists
|
errmsg VARCHAR(128) DEFAULT NULL, # optional error message which can describe details regarding LBs state, can be blank if no error state exists
|
||||||
client_timeout INT,
|
timeout INT,
|
||||||
server_timeout INT,
|
retries INT,
|
||||||
connect_timeout INT,
|
|
||||||
connect_retries INT,
|
|
||||||
PRIMARY KEY (id) # ids are unique accross all LBs
|
PRIMARY KEY (id) # ids are unique accross all LBs
|
||||||
) DEFAULT CHARSET utf8 DEFAULT COLLATE utf8_general_ci;
|
) DEFAULT CHARSET utf8 DEFAULT COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user