Made pylint happy.
This commit is contained in:
parent
024af2d26e
commit
a3a97a9721
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
"""Functionality to drop privileges to those of a specified user/group id."""
|
"""Functionality to drop privileges to those of a specified user/group id."""
|
||||||
|
|
||||||
from os import setuid, setgid, setuid, setgroups, getuid, geteuid, getgroups
|
from os import setuid, setgid, setgroups, getuid, geteuid, getgroups
|
||||||
from pwd import getpwnam, getpwuid
|
from pwd import getpwnam, getpwuid
|
||||||
from grp import getgrnam, getgrgid
|
from grp import getgrnam, getgrgid
|
||||||
from pgbouncemgr.logger import format_ex
|
from pgbouncemgr.logger import format_ex
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from pgbouncemgr.logger import Logger, ConsoleLog, SyslogLog, format_ex
|
from pgbouncemgr.logger import Logger, ConsoleLog, SyslogLog
|
||||||
from pgbouncemgr.config import Config
|
from pgbouncemgr.config import Config
|
||||||
from pgbouncemgr.state import State
|
from pgbouncemgr.state import State
|
||||||
from pgbouncemgr.drop_privileges import drop_privileges
|
from pgbouncemgr.drop_privileges import drop_privileges
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# no-pylint: disable=missing-docstring,too-many-instance-attributes
|
# no-pylint: disable=missing-docstring,too-many-instance-attributes,too-few-public-methods
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from pgbouncemgr.config import InvalidConfigValue
|
from pgbouncemgr.config import InvalidConfigValue
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# no-pylint: disable=missing-docstring
|
# no-pylint: disable=missing-docstring,too-few-public-methods
|
||||||
|
|
||||||
class NodePoller():
|
class NodePoller():
|
||||||
"""The NodePoller is used to poll all the nodes that are available
|
"""The NodePoller is used to poll all the nodes that are available
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
"""This module provides various classes that uare used for connecting to
|
"""This module provides various classes that uare used for connecting to
|
||||||
a PostgreSQL or pgbouncer server."""
|
a PostgreSQL or pgbouncer server."""
|
||||||
|
|
||||||
import psycopg2
|
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
from psycopg2.extras imoprt LogicalReplicationConnection
|
import psycopg2
|
||||||
|
from psycopg2.extras import LogicalReplicationConnection
|
||||||
from pgbouncemgr.logger import format_ex
|
from pgbouncemgr.logger import format_ex
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,10 @@ CONNECTED = 'CONNECTED'
|
||||||
REUSED = 'REUSED'
|
REUSED = 'REUSED'
|
||||||
RECONNECTED = 'RECONNECTED'
|
RECONNECTED = 'RECONNECTED'
|
||||||
|
|
||||||
|
# The properties that can be used in a configuration object to
|
||||||
|
# define connection parameters for psycopg2.
|
||||||
|
CONNECTION_PARAMS = ['host', 'port', 'connect_timeout', 'user', 'password']
|
||||||
|
|
||||||
class PgConnection():
|
class PgConnection():
|
||||||
"""Implements a connection to a PostgreSQL server."""
|
"""Implements a connection to a PostgreSQL server."""
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
|
@ -47,10 +51,17 @@ class PgConnection():
|
||||||
self.conn = None
|
self.conn = None
|
||||||
|
|
||||||
def _create_conn_params(self, config):
|
def _create_conn_params(self, config):
|
||||||
"""Use only connection parameters that don't have value None."""
|
"""Extract all connection parameters from the provided configuration,
|
||||||
return dict(
|
that don't have value of None."""
|
||||||
(k, v) for k, v in config.items()
|
conn_params = {}
|
||||||
if v is not None)
|
for key in CONNECTION_PARAMS:
|
||||||
|
if not hasattr(config, key):
|
||||||
|
continue
|
||||||
|
value = getattr(config, key)
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
conn_params[key] = value
|
||||||
|
return conn_params
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""Connect to the database server. When a connection exists,
|
"""Connect to the database server. When a connection exists,
|
||||||
|
@ -142,6 +153,31 @@ class PgReplicationConnection(PgConnection):
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
# The query that is used to check if pgbouncer is connected to the expected
|
||||||
|
# backend server. We don't really have a unique identifier for the node to
|
||||||
|
# work with there, but we can request the server host + port to see if they
|
||||||
|
# match those of the expected node. Additionally, a check is done to see if
|
||||||
|
# the node is running as a primary node.
|
||||||
|
#
|
||||||
|
# It would be really nice if it were possible to retrieve the system_id
|
||||||
|
# and timeline_id for the backend server, but that is only possible when
|
||||||
|
# using a replication connection. Pgbouncer (through which we are connected
|
||||||
|
# when running this query) does not support pooled replication connections.
|
||||||
|
VERIFY_QUERY = """
|
||||||
|
SELECT CASE
|
||||||
|
WHEN (
|
||||||
|
inet_server_addr() IS DISTINCT FROM %(host)s OR
|
||||||
|
inet_server_port() IS DISTINCT FROM %(port)s)
|
||||||
|
THEN format(
|
||||||
|
'connected to wrong server: %%s:%%s (expected %%s:%%s)',
|
||||||
|
inet_server_addr(), inet_server_port(), %(host)s, %(port)s)
|
||||||
|
WHEN pg_is_in_recovery()
|
||||||
|
THEN format(
|
||||||
|
'server %%s:%%s is not running as primary',
|
||||||
|
%(host)s, %(port)s)
|
||||||
|
ELSE NULL
|
||||||
|
END
|
||||||
|
"""
|
||||||
|
|
||||||
class PgConnectionViaPgbouncer(PgConnection):
|
class PgConnectionViaPgbouncer(PgConnection):
|
||||||
"""This PostgreSQL connection class is used to setup a connection
|
"""This PostgreSQL connection class is used to setup a connection
|
||||||
|
@ -158,8 +194,8 @@ class PgConnectionViaPgbouncer(PgConnection):
|
||||||
|
|
||||||
# Secondly, override parameters to redirect the connection to
|
# Secondly, override parameters to redirect the connection to
|
||||||
# the pgbouncer instance.
|
# the pgbouncer instance.
|
||||||
self.conn_params["host"] = pgbouncer_config["host"]
|
self.conn_params["host"] = pgbouncer_config["host"]
|
||||||
self.conn_params["port"] = pgbouncer_config["port"]
|
self.conn_params["port"] = pgbouncer_config["port"]
|
||||||
|
|
||||||
# Note that we don't setup a replication connection here. This is
|
# Note that we don't setup a replication connection here. This is
|
||||||
# unfortunately not possible, because pgbouncer does not support
|
# unfortunately not possible, because pgbouncer does not support
|
||||||
|
@ -178,7 +214,7 @@ class PgConnectionViaPgbouncer(PgConnection):
|
||||||
# then stall for quite a while. For swift operation of backend
|
# then stall for quite a while. For swift operation of backend
|
||||||
# switching, we therefore use the timeout setup here, to reconfigure
|
# switching, we therefore use the timeout setup here, to reconfigure
|
||||||
# the system more quickly.
|
# the system more quickly.
|
||||||
#
|
#
|
||||||
# Note that in most situations this shouldn't be an issue, since we
|
# Note that in most situations this shouldn't be an issue, since we
|
||||||
# will always reload pgbouncer after a configuration change and the
|
# will always reload pgbouncer after a configuration change and the
|
||||||
# connection from below will, because of that, work as intended
|
# connection from below will, because of that, work as intended
|
||||||
|
@ -207,9 +243,9 @@ class PgConnectionViaPgbouncer(PgConnection):
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return report_func(False, exception)
|
return report_func(False, exception)
|
||||||
|
|
||||||
# When the verify query did not return an error message, then we
|
# When the verify query did not return an error message, then we
|
||||||
# are in the green.
|
# are in the green.
|
||||||
return report_func(True, None)
|
return report_func(True, None)
|
||||||
|
|
||||||
parent_conn, child_conn = multiprocessing.Pipe()
|
parent_conn, child_conn = multiprocessing.Pipe()
|
||||||
def report_func(true_or_false, exception):
|
def report_func(true_or_false, exception):
|
||||||
|
@ -238,7 +274,7 @@ class PgBouncerConsoleConnection(PgConnection):
|
||||||
|
|
||||||
# For the console connection, the database name "pgbouncer"
|
# For the console connection, the database name "pgbouncer"
|
||||||
# must be used.
|
# must be used.
|
||||||
self.conn_params["dbname"] = "pgbouncer"
|
self.conn_params["dbname"] = "pgbouncer"
|
||||||
|
|
||||||
# The default ping query does not work when connected to the
|
# The default ping query does not work when connected to the
|
||||||
# pgbouncer console. Here's a simple replacement for it.
|
# pgbouncer console. Here's a simple replacement for it.
|
||||||
|
@ -251,7 +287,7 @@ class PgBouncerConsoleConnection(PgConnection):
|
||||||
transaction. Transactions are not supported by the pgbouncer
|
transaction. Transactions are not supported by the pgbouncer
|
||||||
console."""
|
console."""
|
||||||
result = super().connect()
|
result = super().connect()
|
||||||
self.conn.autocommit = True
|
self.conn.autocommit = True
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def reload(self):
|
def reload(self):
|
||||||
|
@ -268,4 +304,3 @@ class PgBouncerConsoleConnection(PgConnection):
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
raise ReloadingPgbouncerFailed(
|
raise ReloadingPgbouncerFailed(
|
||||||
"An exception occurred: %s" % format_ex(exception))
|
"An exception occurred: %s" % format_ex(exception))
|
||||||
|
|
||||||
|
|
|
@ -113,8 +113,8 @@ class State():
|
||||||
state = State(logger)
|
state = State(logger)
|
||||||
for node_id, settings in config.nodes.items():
|
for node_id, settings in config.nodes.items():
|
||||||
node_config = NodeConfig(node_id)
|
node_config = NodeConfig(node_id)
|
||||||
for k, v in settings.items():
|
for key, value in settings.items():
|
||||||
setattr(node_config, k, v)
|
setattr(node_config, key, value)
|
||||||
state.add_node(node_config)
|
state.add_node(node_config)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
@ -241,9 +241,9 @@ class State():
|
||||||
"node id: node config changed? (leader_node_id=%s)" %
|
"node id: node config changed? (leader_node_id=%s)" %
|
||||||
leader_node_id)
|
leader_node_id)
|
||||||
raise UnknownLeaderNodeId(leader_node_id)
|
raise UnknownLeaderNodeId(leader_node_id)
|
||||||
if self._leader_node_id == leader_node_id:
|
if self._leader_node_id == node.node_id:
|
||||||
return
|
return
|
||||||
self._leader_node_id = leader_node_id
|
self._leader_node_id = node.node_id
|
||||||
self.modified = True
|
self.modified = True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
# no-pylint: disable=missing-docstring,broad-except,too-many-instance-attributes
|
# no-pylint: disable=missing-docstring,broad-except,too-many-instance-attributes
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from datetime import datetime
|
|
||||||
from os import rename
|
from os import rename
|
||||||
from os.path import isfile
|
from os.path import isfile
|
||||||
from pgbouncemgr.logger import format_ex
|
from pgbouncemgr.logger import format_ex
|
||||||
|
@ -71,5 +70,5 @@ class StateStore():
|
||||||
rename(swap_path, self.path)
|
rename(swap_path, self.path)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
raise StateStoreException(
|
raise StateStoreException(
|
||||||
"Storing state to file (%s) failed: %s" % (
|
"Storing state to file (%s) failed: %s" %
|
||||||
self.path, format_ex(exception)))
|
(self.path, format_ex(exception)))
|
||||||
|
|
Loading…
Reference in New Issue