Support server node weights.

Support setting a weighting value for each node that will determine
the proportion of load balancing requests that it receives in relation
to the other defined servers and their weights.

Also adds a file describing the worker JSON message versioning.

Fixes bug 1117349

Change-Id: Ie1460c165f03b0523ee28d864b74ea9e5858b256
This commit is contained in:
David Shrewsbury
2013-02-06 11:00:20 -05:00
parent 8316e49965
commit 53fedfca2a
6 changed files with 81 additions and 9 deletions

29
WORKER_MSG_FMT_VERSIONS Normal file
View File

@@ -0,0 +1,29 @@
# The worker versions the JSON messages that it comprehends. This version
# is used for the DISCOVER message that can be sent by the API server. E.g.,
#
# { 'hpcs_action': 'DISCOVER' }
#
# And an example response from the worker:
#
# {
# 'hpcs_action': 'DISCOVER',
# 'version': '1.0',
# 'hpcs_response': 'PASS'
# }
#
# The version number is set in the method:
#
# libra.worker.controller._action_discover()
#
# Version format is: <major>.<minor>
#
# A change to the <minor> value means that a change has been made, but
# we are still backwards compatible. A change to the <major> value means
# a significant change was made and we are no longer compatible with older
# versions.
[Version 1.1]
- Accept node 'weight' values.
[Version 1.0]
- Initial version.

View File

@@ -75,7 +75,7 @@ class LBaaSController(object):
version this worker supports.
"""
# Version of the JSON message format that this worker understands.
msg_fmt_version = "1.0"
msg_fmt_version = "1.1"
self.msg['version'] = msg_fmt_version
self.msg[self.RESPONSE_FIELD] = self.RESPONSE_SUCCESS
return self.msg

View File

@@ -48,7 +48,7 @@ class LoadBalancerDriver(object):
""" Add a supported protocol and listening port for the instance. """
raise NotImplementedError()
def add_server(self, protocol, host, port):
def add_server(self, protocol, host, port, weight):
""" Add a server for the protocol for which we will proxy. """
raise NotImplementedError()

View File

@@ -92,9 +92,9 @@ class HAProxyDriver(LoadBalancerDriver):
if proto == 'http':
output.append(' cookie SERVERID rewrite')
for (addr, port) in protocfg['servers']:
output.append(' server server%d %s:%s' %
(serv_num, addr, port))
for (addr, port, weight) in protocfg['servers']:
output.append(' server server%d %s:%s weight %d' %
(serv_num, addr, port, weight))
serv_num += 1
return '\n'.join(output) + '\n'
@@ -123,11 +123,20 @@ class HAProxyDriver(LoadBalancerDriver):
else:
self._bind(proto, '0.0.0.0', port)
def add_server(self, protocol, host, port):
def add_server(self, protocol, host, port, weight=1):
proto = protocol.lower()
try:
weight = int(weight)
except ValueError:
raise Exception("Non-integer 'weight' value: '%s'" % weight)
if weight > 256:
raise Exception("Server 'weight' %d exceeds max of 256" % weight)
if 'servers' not in self._config[proto]:
self._config[proto]['servers'] = []
self._config[proto]['servers'].append((host, port))
self._config[proto]['servers'].append((host, port, weight))
def set_algorithm(self, protocol, algo):
proto = protocol.lower()

View File

@@ -41,8 +41,8 @@ class TestHAProxyDriver(testtools.TestCase):
self.assertIn('servers', self.driver._config[proto])
servers = self.driver._config[proto]['servers']
self.assertEqual(len(servers), 2)
self.assertEqual(servers[0], ('1.2.3.4', 7777))
self.assertEqual(servers[1], ('5.6.7.8', 8888))
self.assertEqual(servers[0], ('1.2.3.4', 7777, 1))
self.assertEqual(servers[1], ('5.6.7.8', 8888, 1))
def testSetAlgorithm(self):
""" Test the HAProxy set_algorithm() method """
@@ -56,3 +56,35 @@ class TestHAProxyDriver(testtools.TestCase):
self.assertEqual(self.driver._config[proto]['algorithm'], 'leastconn')
e = self.assertRaises(Exception, self.driver.set_algorithm, proto, 99)
self.assertEqual("Invalid algorithm: http", e.message)
def testServerWeightInt(self):
""" Test setting integer server weights """
proto = 'http'
self.driver.add_protocol(proto, None)
self.driver.add_server(proto, '1.2.3.4', 7777, 10)
servers = self.driver._config[proto]['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0], ('1.2.3.4', 7777, 10))
def testServerWeightStr(self):
""" Test setting string server weights """
proto = 'http'
self.driver.add_protocol(proto, None)
self.driver.add_server(proto, '1.2.3.4', 7777, "20")
servers = self.driver._config[proto]['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0], ('1.2.3.4', 7777, 20))
def testServerWeightInvalid(self):
""" Test setting string server weights """
proto = 'http'
self.driver.add_protocol(proto, None)
e = self.assertRaises(
Exception,
self.driver.add_server, proto, '1.2.3.4', 7777, 257)
self.assertEqual("Server 'weight' 257 exceeds max of 256", e.message)
e = self.assertRaises(
Exception,
self.driver.add_server, proto, '1.2.3.4', 7777, "abc")
self.assertEqual("Non-integer 'weight' value: 'abc'", e.message)

View File

@@ -1,6 +1,8 @@
fixtures>=0.3.12
pep8
mock
httplib2
python-subunit
sphinx>=1.1.2
testrepository>=0.0.8
testtools>=0.9.22