Skip to content

Commit b236e59

Browse files
author
Pavlos Parissis
committed
Split internal classes to individual modules
We used to have one module(internal) which exposed all internal classes for frontend, backend, haproxy and server. This was a bit suboptimal approach in terms of modules management and therefore we create individual modules for each class.
1 parent db5157e commit b236e59

File tree

7 files changed

+350
-285
lines changed

7 files changed

+350
-285
lines changed

docs/source/dev/api.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,19 @@ meant for external use.
4040
.. autoclass:: Server
4141
:members:
4242

43-
.. automodule:: haproxyadmin.internal
43+
.. automodule:: haproxyadmin.internal.haproxy
44+
:members:
45+
:private-members:
46+
47+
.. automodule:: haproxyadmin.internal.frontend
48+
:members:
49+
:private-members:
50+
51+
.. automodule:: haproxyadmin.internal.backend
52+
:members:
53+
:private-members:
54+
55+
.. automodule:: haproxyadmin.internal.server
4456
:members:
4557
:private-members:
4658

haproxyadmin/haproxy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from haproxyadmin.utils import (is_unix_socket, cmd_across_all_procs, converter,
1818
calculate, isint, should_die, check_command,
1919
check_output, compare_values, connected_socket)
20-
from haproxyadmin.internal import _HAProxyProcess
20+
from haproxyadmin.internal.haproxy import _HAProxyProcess
2121
from haproxyadmin.exceptions import CommandFailed
2222

2323

haproxyadmin/internal/__init__.py

Whitespace-only changes.

haproxyadmin/internal/backend.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# pylint: disable=superfluous-parens
4+
#
5+
"""
6+
haproxyadmin.internal.backend
7+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8+
9+
This module provides a class, which is used within haproxyadmin for creating a
10+
object to work with a backend. This object is associated only with a single
11+
HAProxy process.
12+
13+
"""
14+
from haproxyadmin.internal.server import _Server
15+
16+
class _Backend:
17+
"""Class for interacting with a backend in one HAProxy process.
18+
19+
:param hap_process: a :class::`_HAProxyProcess` object.
20+
:param name: backend name.
21+
:type name: ``string``
22+
:param iid: unique proxy id of the backend.
23+
:type iid: ``integer``
24+
"""
25+
def __init__(self, hap_process, name, iid):
26+
self.hap_process = hap_process
27+
self._name = name
28+
self.hap_process_nb = self.hap_process.process_nb
29+
self._iid = iid
30+
31+
@property
32+
def name(self):
33+
"""Return a string which is the name of the backend"""
34+
return self._name
35+
36+
@property
37+
def iid(self):
38+
"""Return Proxy ID"""
39+
data = self.stats_data()
40+
self._iid = data.iid
41+
42+
return self._iid
43+
44+
@property
45+
def process_nb(self):
46+
"""Return the process number of the haproxy process
47+
48+
:rtype: ``int``
49+
"""
50+
return int(self.hap_process_nb)
51+
52+
def stats_data(self):
53+
"""Return stats data
54+
55+
Check documentation of ``stats_data`` method in :class:`_Frontend`.
56+
57+
:rtype: ``utils.CSVLine`` object
58+
"""
59+
# Fetch data using the last known iid
60+
try:
61+
data = self.hap_process.backends_stats(self._iid)[self.name]
62+
except KeyError:
63+
# A lookup on HAProxy with the current id doesn't return
64+
# an object with our name.
65+
# Most likely object got different id due to a reshuffle in conf.
66+
# Thus retrieve all objects to get latest data for the object.
67+
try:
68+
data = self.hap_process.backends_stats()[self.name]
69+
except KeyError:
70+
# The object has gone from running configuration!
71+
# We cant recover from this situation.
72+
raise
73+
74+
return data['stats']
75+
76+
def stats(self):
77+
"""Build dictionary for all statistics reported by HAProxy.
78+
79+
:return: A dictionary with statistics
80+
:rtype: ``dict``
81+
"""
82+
data = self.stats_data()
83+
keys = data.heads
84+
values = data.parts
85+
86+
return dict(zip(keys, values))
87+
88+
def metric(self, name):
89+
data = self.stats_data()
90+
91+
return getattr(data, name)
92+
93+
def command(self, cmd):
94+
"""Send command to HAProxy
95+
96+
:param cmd: command to send
97+
:type cmd: ``string``
98+
:return: the output of the command
99+
:rtype: ``string``
100+
"""
101+
return self.hap_process.command(cmd)
102+
103+
def servers(self, name=None):
104+
"""Return a list of _Server objects for each server of the backend.
105+
106+
:param name: (optional): server name to lookup, defaults to None.
107+
:type name: ``string``
108+
"""
109+
servers = []
110+
return_list = []
111+
112+
servers = self.hap_process.servers_stats(self.name, self.iid)
113+
if name is not None:
114+
if name in servers:
115+
return_list.append(_Server(self,
116+
name,
117+
servers[name].sid))
118+
else:
119+
return []
120+
else:
121+
for _name in servers:
122+
return_list.append(_Server(self,
123+
_name,
124+
servers[_name].sid))
125+
126+
return return_list

haproxyadmin/internal/frontend.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# pylint: disable=superfluous-parens
4+
#
5+
"""
6+
haproxyadmin.internal.frontend
7+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8+
9+
This module provides a class, which is used within haproxyadmin for creating a
10+
object to work with a frontend. This object is associated only with a single
11+
HAProxy process.
12+
13+
14+
"""
15+
16+
17+
class _Frontend:
18+
"""Class for interacting with a frontend in one HAProxy process.
19+
20+
:param hap_process: a :class:`_HAProxyProcess` object.
21+
:param name: frontend name.
22+
:type name: ``string``
23+
:param iid: unique proxy id of the frontend.
24+
:type iid: ``integer``
25+
"""
26+
def __init__(self, hap_process, name, iid):
27+
self.hap_process = hap_process
28+
self._name = name
29+
self.hap_process_nb = self.hap_process.process_nb
30+
self._iid = iid
31+
32+
@property
33+
def name(self):
34+
"""Return a string which is the name of the frontend"""
35+
return self._name
36+
37+
@property
38+
def iid(self):
39+
"""Return Proxy ID"""
40+
data = self.stats_data()
41+
self._iid = data.iid
42+
43+
return self._iid
44+
45+
@property
46+
def process_nb(self):
47+
return int(self.hap_process_nb)
48+
49+
def stats_data(self):
50+
"""Return stats data
51+
52+
:rtype: ``utils.CSVLine`` object
53+
54+
HAProxy assigns unique ids to each object during the startup.
55+
The id can change when configuration changes, objects order
56+
is reshuffled or additions/removals take place.
57+
In those cases the id we store at the instantiation of the object may
58+
reference to another object or even to non-existent object when
59+
configuration takes places afterwards.
60+
61+
The technique we use is quite simple. When an object is created
62+
we store the name and the id. In order to detect if iid is changed,
63+
we simply send a request to fetch data only for the given iid and check
64+
if the current id points to an object of the same type
65+
(frontend, backend, server) which has the same name.
66+
"""
67+
# Fetch data using the last known iid
68+
try:
69+
data = self.hap_process.frontends_stats(self._iid)[self.name]
70+
except KeyError:
71+
# A lookup on HAProxy with the current id doesn't return
72+
# an object with our name.
73+
# Most likely object got different id due to a reshuffle in conf.
74+
# Thus retrieve all objects to get latest data for the object.
75+
try:
76+
# This will basically request all object of the type
77+
data = self.hap_process.frontends_stats()[self.name]
78+
except KeyError:
79+
# The object has gone from running configuration!
80+
# This occurs when object was removed from configuration
81+
# and haproxy was reloaded or frontend was shutdowned.
82+
# We cant recover from this situation
83+
raise
84+
85+
return data
86+
87+
def stats(self):
88+
"""Build dictionary for all statistics reported by HAProxy.
89+
90+
:return: A dictionary with statistics
91+
:rtype: ``dict``
92+
8. split internal to multiple files
93+
"""
94+
data = self.stats_data()
95+
keys = data.heads
96+
values = data.parts
97+
98+
return dict(zip(keys, values))
99+
100+
def metric(self, name):
101+
"""Return the value of a metric"""
102+
data = self.stats_data()
103+
104+
return getattr(data, name)
105+
106+
def command(self, cmd):
107+
"""Run command to HAProxy
108+
109+
:param cmd: a valid command to execute.
110+
:type cmd: ``string``
111+
:return: 1st line of the output.
112+
:rtype: ``string``
113+
"""
114+
return self.hap_process.command(cmd)

0 commit comments

Comments
 (0)