[WORKER] Implement new STATS request
STATS requests will now return usage information for each LB defined on a device (TCP, HTTP, or both). This change introduces a new StatisticsManager class for managing temporary storage of HAProxy statistics to deal with the fact that its reported values are reset on restart. Also add tests for the new class. Removed the LBStatistics class since it wasn't necessary. Change-Id: I56177a829650b2206ee855fdf4756ed52825e936
This commit is contained in:
@@ -21,7 +21,7 @@ from libra import __release__ as libra_release
|
||||
from libra.common.exc import DeletedStateError
|
||||
from libra.common.faults import BadRequest
|
||||
from libra.openstack.common import log
|
||||
from libra.worker.drivers.base import LoadBalancerDriver
|
||||
from libra.worker.drivers import base
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
@@ -71,8 +71,7 @@ class LBaaSController(object):
|
||||
elif action == 'ARCHIVE':
|
||||
return self._action_archive()
|
||||
elif action == 'STATS':
|
||||
# TODO: Implement new STATS function
|
||||
return self._action_ping()
|
||||
return self._action_stats()
|
||||
elif action == 'PING':
|
||||
return self._action_ping()
|
||||
elif action == 'DIAGNOSTICS':
|
||||
@@ -203,15 +202,15 @@ class LBaaSController(object):
|
||||
if 'algorithm' in current_lb:
|
||||
algo = current_lb['algorithm'].upper()
|
||||
if algo == 'ROUND_ROBIN':
|
||||
algo = LoadBalancerDriver.ROUNDROBIN
|
||||
algo = base.LoadBalancerDriver.ROUNDROBIN
|
||||
elif algo == 'LEAST_CONNECTIONS':
|
||||
algo = LoadBalancerDriver.LEASTCONN
|
||||
algo = base.LoadBalancerDriver.LEASTCONN
|
||||
else:
|
||||
LOG.error("Invalid algorithm: %s" % algo)
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_FAILURE
|
||||
return self.msg
|
||||
else:
|
||||
algo = LoadBalancerDriver.ROUNDROBIN
|
||||
algo = base.LoadBalancerDriver.ROUNDROBIN
|
||||
|
||||
try:
|
||||
self.driver.set_algorithm(current_lb['protocol'], algo)
|
||||
@@ -451,26 +450,69 @@ class LBaaSController(object):
|
||||
"""
|
||||
|
||||
try:
|
||||
stats = self.driver.get_status()
|
||||
nodes = self.driver.get_status()
|
||||
except NotImplementedError:
|
||||
error = "Selected driver does not support PING action."
|
||||
LOG.error(error)
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_FAILURE
|
||||
self.msg[self.ERROR_FIELD] = error
|
||||
except DeletedStateError:
|
||||
LOG.info("Invalid operation PING on a deleted LB")
|
||||
error = "Invalid operation PING on a deleted LB."
|
||||
LOG.error(error)
|
||||
self.msg['status'] = 'DELETED'
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_FAILURE
|
||||
self.msg[self.ERROR_FIELD] = error
|
||||
except Exception as e:
|
||||
LOG.error("PING failed: %s, %s" % (e.__class__, e))
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_FAILURE
|
||||
self.msg[self.ERROR_FIELD] = str(e)
|
||||
else:
|
||||
node_status = stats.node_status_map()
|
||||
self.msg['nodes'] = []
|
||||
for node in node_status.keys():
|
||||
self.msg['nodes'].append({'id': node,
|
||||
'status': node_status[node]})
|
||||
for node, status in nodes:
|
||||
self.msg['nodes'].append({'id': node, 'status': status})
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_SUCCESS
|
||||
|
||||
return self.msg
|
||||
|
||||
def _action_stats(self):
|
||||
"""
|
||||
Get load balancer statistics
|
||||
|
||||
This type of request gets the number of bytes out for each load
|
||||
balancer defined on the device. If both a TCP and HTTP load
|
||||
balancer exist, we report on each in a single response.
|
||||
"""
|
||||
|
||||
try:
|
||||
start, end, statistics = self.driver.get_statistics()
|
||||
except NotImplementedError:
|
||||
error = "Selected driver does not support STATS action."
|
||||
LOG.error(error)
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_FAILURE
|
||||
self.msg[self.ERROR_FIELD] = error
|
||||
return self.msg
|
||||
except DeletedStateError:
|
||||
error = "Invalid operation STATS on a deleted LB."
|
||||
LOG.error(error)
|
||||
self.msg['status'] = 'DELETED'
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_FAILURE
|
||||
self.msg[self.ERROR_FIELD] = error
|
||||
return self.msg
|
||||
except Exception as e:
|
||||
LOG.error("STATS failed: %s, %s" % (e.__class__, e))
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_FAILURE
|
||||
self.msg[self.ERROR_FIELD] = str(e)
|
||||
return self.msg
|
||||
|
||||
self.msg['utc_start'] = start
|
||||
self.msg['utc_end'] = end
|
||||
self.msg['loadBalancers'] = []
|
||||
|
||||
# We should have a list of tuples pairing the number of bytes
|
||||
# out with the protocol/LB.
|
||||
for proto, bytes_out in statistics:
|
||||
self.msg['loadBalancers'].append({'protocol': proto,
|
||||
'bytes_out': bytes_out})
|
||||
|
||||
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_SUCCESS
|
||||
return self.msg
|
||||
|
||||
Reference in New Issue
Block a user