Made pylint happy.

This commit is contained in:
Maurice Makaay 2019-12-12 13:48:17 +01:00
parent 024af2d26e
commit a3a97a9721
7 changed files with 60 additions and 26 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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)))