David Shrewsbury 3ec02bcdb1 Start of obtaining worker stats.
The worker now gets the bytes-in/bytes-out for the specified
protocol (http or tcp). For now, these values are only logged,
and then only in debug mode. Added a test for setting these
values in the new LBStatistics class.

Updated README for the 'socat' requirement and to mention that
the PID file directory must be writable by the user.

Change-Id: I79f218747255cba84b25c4a69d0b210c9d1dfee5
2012-11-12 16:51:57 -05:00

158 lines
5.5 KiB
Python

# Copyright 2012 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from libra.openstack.common import importutils
from libra.worker.drivers.base import LoadBalancerDriver
from libra.worker.drivers.haproxy.services_base import ServicesBase
class HAProxyDriver(LoadBalancerDriver):
def __init__(self, ossvc):
ossvc_driver = importutils.import_class(ossvc)
self.ossvc = ossvc_driver()
if not isinstance(self.ossvc, ServicesBase):
raise Exception('Class is not derived from ServicesBase: %s' %
ossvc.__class__)
self._init_config()
def _init_config(self):
self._config = dict()
def _bind(self, protocol, address, port):
self._config[protocol]['bind_address'] = address
self._config[protocol]['bind_port'] = port
def _config_to_string(self):
"""
Use whatever configuration parameters have been set to generate
output suitable for a HAProxy configuration file.
"""
output = []
output.append('global')
output.append(' daemon')
output.append(' log /dev/log local0')
output.append(' log /dev/log local1 notice')
output.append(' maxconn 4096')
output.append(' user haproxy')
output.append(' group haproxy')
output.append(
' stats socket /var/run/haproxy-stats.socket mode operator'
)
output.append('defaults')
output.append(' log global')
output.append(' option dontlognull')
output.append(' option redispatch')
output.append(' maxconn 2000')
output.append(' retries 3')
output.append(' timeout connect 5000ms')
output.append(' timeout client 50000ms')
output.append(' timeout server 5000ms')
serv_num = 1
for proto in self._config:
protocfg = self._config[proto]
#------------------------
# Frontend configuration
#------------------------
output.append('frontend %s-in' % proto)
output.append(' mode %s' % proto)
output.append(' bind %s:%s' % (protocfg['bind_address'],
protocfg['bind_port']))
output.append(' default_backend %s-servers' % proto)
# HTTP specific options for the frontend
if proto == 'http':
output.append(' option httplog')
# TCP specific options for the frontend
elif proto == 'tcp':
output.append(' option tcplog')
#------------------------
# Backend configuration
#------------------------
output.append('backend %s-servers' % proto)
output.append(' mode %s' % proto)
output.append(' balance %s' % protocfg['algorithm'])
# HTTP specific options for the backend
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))
serv_num += 1
return '\n'.join(output) + '\n'
####################
# Driver API Methods
####################
def init(self):
self._init_config()
def add_protocol(self, protocol, port=None):
proto = protocol.lower()
if proto not in ('tcp', 'http', 'health'):
raise Exception("Unsupported protocol: %s" % protocol)
if proto in self._config:
raise Exception("Protocol '%s' is already defined." % protocol)
else:
self._config[proto] = dict()
if port is None:
if proto == 'tcp':
raise Exception('Port is required for TCP protocol.')
elif proto == 'http':
self._bind(proto, '0.0.0.0', 80)
else:
self._bind(proto, '0.0.0.0', port)
def add_server(self, protocol, host, port):
proto = protocol.lower()
if 'servers' not in self._config[proto]:
self._config[proto]['servers'] = []
self._config[proto]['servers'].append((host, port))
def set_algorithm(self, protocol, algo):
proto = protocol.lower()
if algo == self.ROUNDROBIN:
self._config[proto]['algorithm'] = 'roundrobin'
elif algo == self.LEASTCONN:
self._config[proto]['algorithm'] = 'leastconn'
else:
raise Exception('Invalid algorithm: %s' % protocol)
def create(self):
self.ossvc.write_config(self._config_to_string())
self.ossvc.service_stop()
self.ossvc.service_start()
def suspend(self):
self.ossvc.service_stop()
def enable(self):
self.ossvc.service_start()
def delete(self):
self.ossvc.service_stop()
self.ossvc.remove_configs()
def get_stats(self, protocol):
return self.ossvc.get_stats(protocol)