manageiq-postgres_ha_admin 2.0.0 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.codeclimate.yml +1 -0
- data/.travis.yml +1 -2
- data/CHANGELOG.md +31 -2
- data/CODEOWNERS +1 -0
- data/Gemfile +1 -4
- data/README.md +0 -1
- data/lib/manageiq-postgres_ha_admin.rb +22 -2
- data/lib/manageiq/postgres_ha_admin/config_handler.rb +35 -0
- data/lib/manageiq/postgres_ha_admin/config_handler/logical_replication_config_handler.rb +34 -0
- data/lib/manageiq/postgres_ha_admin/config_handler/pglogical_config_handler.rb +36 -0
- data/lib/manageiq/postgres_ha_admin/{database_yml.rb → config_handler/rails_config_handler.rb} +19 -15
- data/lib/manageiq/postgres_ha_admin/failover_monitor.rb +53 -72
- data/lib/manageiq/postgres_ha_admin/logging.rb +9 -0
- data/lib/manageiq/postgres_ha_admin/null_logger.rb +13 -0
- data/lib/manageiq/postgres_ha_admin/{failover_databases.rb → server_store.rb} +25 -30
- data/lib/manageiq/postgres_ha_admin/version.rb +1 -1
- data/manageiq-postgres_ha_admin.gemspec +4 -3
- metadata +35 -12
- data/bin/postgres_ha_admin +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4bbec7e79b7ae7140dadbeb59bd561ef7469f8568a9c1d5b8a78d2464b50d57d
|
4
|
+
data.tar.gz: 4f04ad4bb6a91887e77e5b85247510294a18ef8083c1883d5be0ff7ae21898ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6767d711af5f8b2b219e9924c8293f89c29f4b03770151f100e6a390f92eafc9be1630c43aa7149414fdec3b5ef6c6d6c12983b6a7d78c5d774ce0a8b870db5
|
7
|
+
data.tar.gz: e6e63fa21d95062f54fcbb9dde5efa942ca46f0627a0d243076d4f2a7bd034029610ff722e1cf8bd04dae897ae314e2e04a0112d255392ffd3e9447f073e674a
|
data/.codeclimate.yml
CHANGED
data/.travis.yml
CHANGED
@@ -2,7 +2,6 @@ language: ruby
|
|
2
2
|
rvm:
|
3
3
|
- '2.3.1'
|
4
4
|
- '2.4.2'
|
5
|
-
sudo: false
|
6
5
|
cache: bundler
|
7
6
|
env:
|
8
7
|
global:
|
@@ -10,5 +9,5 @@ env:
|
|
10
9
|
- RUBY_GC_HEAP_INIT_SLOTS=600000
|
11
10
|
- RUBY_GC_HEAP_GROWTH_FACTOR=1.25
|
12
11
|
addons:
|
13
|
-
postgresql: '
|
12
|
+
postgresql: '10'
|
14
13
|
after_script: bundle exec codeclimate-test-reporter
|
data/CHANGELOG.md
CHANGED
@@ -3,7 +3,31 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
5
5
|
|
6
|
-
## [
|
6
|
+
## [3.1.2] - 2020-12-21
|
7
|
+
- Allow for Rails 6.0 [#23](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/23)
|
8
|
+
|
9
|
+
## [3.1.1] - 2019-12-12
|
10
|
+
- Remove the dependency on linux_admin [#19](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/19)
|
11
|
+
|
12
|
+
## [3.1.0] - 2019-05-09
|
13
|
+
|
14
|
+
### Added
|
15
|
+
- Add a logical replication config handler [#17](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/17)
|
16
|
+
|
17
|
+
## [3.0.1] - 2019-03-19
|
18
|
+
|
19
|
+
### Changed
|
20
|
+
- Remove references to MiqPassword [#15](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/15)
|
21
|
+
|
22
|
+
## [3.0.0] - 2018-09-05
|
23
|
+
|
24
|
+
### Added
|
25
|
+
- Allow users of the gem to specify a logger object [#7](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/7)
|
26
|
+
|
27
|
+
### Changed
|
28
|
+
- Make sources of database connection info pluggable [#8](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/8)
|
29
|
+
- Improve FailoverDatabases/ServerStore class [#9](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/9)
|
30
|
+
- Make failover monitor generic [#10](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/10)
|
7
31
|
|
8
32
|
## [2.0.0] - 2018-08-01
|
9
33
|
|
@@ -14,5 +38,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
14
38
|
### Changed
|
15
39
|
- Make changes for upgrading repmgr to version 4 [#4](https://github.com/ManageIQ/manageiq-postgres_ha_admin/pull/4)
|
16
40
|
|
17
|
-
[Unreleased]: https://github.com/ManageIQ/manageiq-postgres_ha_admin/compare/
|
41
|
+
[Unreleased]: https://github.com/ManageIQ/manageiq-postgres_ha_admin/compare/v3.1.2...master
|
42
|
+
[3.1.2]: https://github.com/ManageIQ/manageiq-postgres_ha_admin/compare/v3.1.1...v3.1.2
|
43
|
+
[3.1.1]: https://github.com/ManageIQ/manageiq-postgres_ha_admin/compare/v3.1.0...v3.1.1
|
44
|
+
[3.1.0]: https://github.com/ManageIQ/manageiq-postgres_ha_admin/compare/v3.0.1...v3.1.0
|
45
|
+
[3.0.1]: https://github.com/ManageIQ/manageiq-postgres_ha_admin/compare/v3.0.0...v3.0.1
|
46
|
+
[3.0.0]: https://github.com/ManageIQ/manageiq-postgres_ha_admin/compare/v2.0.0...v3.0.0
|
18
47
|
[2.0.0]: https://github.com/ManageIQ/manageiq-postgres_ha_admin/compare/v1.0.0...v2.0.0
|
data/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @carbonin
|
data/Gemfile
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in manageiq-
|
3
|
+
# Specify your gem's dependencies in manageiq-postgres_ha_admin.gemspec
|
4
4
|
gemspec
|
5
|
-
|
6
|
-
# For MiqPassword
|
7
|
-
gem "manageiq-gems-pending", :git => "https://github.com/ManageIQ/manageiq-gems-pending", :branch => "master"
|
data/README.md
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
[](https://travis-ci.org/ManageIQ/manageiq-postgres_ha_admin)
|
5
5
|
[](https://codeclimate.com/github/ManageIQ/manageiq-postgres_ha_admin)
|
6
6
|
[](https://codeclimate.com/github/ManageIQ/manageiq-postgres_ha_admin/coverage)
|
7
|
-
[](https://gemnasium.com/ManageIQ/manageiq-postgres_ha_admin)
|
8
7
|
[](https://hakiri.io/github/ManageIQ/manageiq-postgres_ha_admin/master)
|
9
8
|
|
10
9
|
[](https://gitter.im/ManageIQ/manageiq-postgres_ha_admin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
@@ -1,4 +1,24 @@
|
|
1
1
|
require 'manageiq/postgres_ha_admin/version'
|
2
|
-
|
3
|
-
require 'manageiq/postgres_ha_admin/
|
2
|
+
|
3
|
+
require 'manageiq/postgres_ha_admin/logging'
|
4
|
+
require 'manageiq/postgres_ha_admin/null_logger'
|
5
|
+
|
6
|
+
require 'manageiq/postgres_ha_admin/server_store'
|
4
7
|
require 'manageiq/postgres_ha_admin/failover_monitor'
|
8
|
+
|
9
|
+
require 'manageiq/postgres_ha_admin/config_handler'
|
10
|
+
require 'manageiq/postgres_ha_admin/config_handler/rails_config_handler'
|
11
|
+
require 'manageiq/postgres_ha_admin/config_handler/pglogical_config_handler'
|
12
|
+
require 'manageiq/postgres_ha_admin/config_handler/logical_replication_config_handler'
|
13
|
+
|
14
|
+
module ManageIQ
|
15
|
+
module PostgresHaAdmin
|
16
|
+
class << self
|
17
|
+
attr_writer :logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.logger
|
21
|
+
@logger ||= NullLogger.new
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ManageIQ
|
2
|
+
module PostgresHaAdmin
|
3
|
+
class ConfigHandler
|
4
|
+
def name
|
5
|
+
"Config Handler"
|
6
|
+
end
|
7
|
+
|
8
|
+
def read
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(_conninfo)
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def before_failover(&block)
|
17
|
+
raise ArgumentError, "A block is required to set the before failover callback" unless block_given?
|
18
|
+
@before_failover_cb = block
|
19
|
+
end
|
20
|
+
|
21
|
+
def after_failover(&block)
|
22
|
+
raise ArgumentError, "A block is required to set the after failover callback" unless block_given?
|
23
|
+
@after_failover_cb = block
|
24
|
+
end
|
25
|
+
|
26
|
+
def do_before_failover
|
27
|
+
@before_failover_cb&.call
|
28
|
+
end
|
29
|
+
|
30
|
+
def do_after_failover(new_primary_conn_info)
|
31
|
+
@after_failover_cb&.call(new_primary_conn_info)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'pg'
|
2
|
+
require 'pg/dsn_parser'
|
3
|
+
|
4
|
+
module ManageIQ
|
5
|
+
module PostgresHaAdmin
|
6
|
+
class LogicalReplicationConfigHandler < ConfigHandler
|
7
|
+
attr_reader :subscription, :conn_info
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@subscription = options[:subscription]
|
11
|
+
@conn_info = options[:conn_info]
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
"Logical Replication subscription #{subscription} Config Handler"
|
16
|
+
end
|
17
|
+
|
18
|
+
def read
|
19
|
+
conn = PG::Connection.open(@conn_info)
|
20
|
+
dsn = conn.exec_params(<<~SQL, [@subscription]).first["subconninfo"]
|
21
|
+
SELECT subconninfo
|
22
|
+
FROM pg_subscription
|
23
|
+
WHERE subname = $1
|
24
|
+
SQL
|
25
|
+
PG::DSNParser.new.parse(dsn)
|
26
|
+
end
|
27
|
+
|
28
|
+
def write(_params)
|
29
|
+
# Nothing to do here as the expectation is that the user will
|
30
|
+
# remove and re-add the subscription in the after failover callback
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'pg'
|
2
|
+
require 'pg/dsn_parser'
|
3
|
+
|
4
|
+
module ManageIQ
|
5
|
+
module PostgresHaAdmin
|
6
|
+
class PglogicalConfigHandler < ConfigHandler
|
7
|
+
attr_reader :subscription, :conn_info
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@subscription = options[:subscription]
|
11
|
+
@conn_info = options[:conn_info]
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
"pglogical subscription #{subscription} Config Handler"
|
16
|
+
end
|
17
|
+
|
18
|
+
def read
|
19
|
+
conn = PG::Connection.open(@conn_info)
|
20
|
+
dsn = conn.exec_params(<<~SQL, [@subscription]).first["if_dsn"]
|
21
|
+
SELECT if_dsn
|
22
|
+
FROM pglogical.subscription s
|
23
|
+
JOIN pglogical.node_interface i
|
24
|
+
ON s.sub_origin_if = i.if_id
|
25
|
+
WHERE s.sub_name = $1
|
26
|
+
SQL
|
27
|
+
PG::DSNParser.new.parse(dsn)
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(_params)
|
31
|
+
# Nothing to do here as the expectation is that the user will
|
32
|
+
# remove and re-add the subscription in the after failover callback
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/manageiq/postgres_ha_admin/{database_yml.rb → config_handler/rails_config_handler.rb}
RENAMED
@@ -1,32 +1,36 @@
|
|
1
1
|
require 'active_support/all'
|
2
|
-
require '
|
2
|
+
require 'manageiq-password'
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
5
|
module ManageIQ
|
6
6
|
module PostgresHaAdmin
|
7
|
-
class
|
8
|
-
attr_reader :
|
7
|
+
class RailsConfigHandler < ConfigHandler
|
8
|
+
attr_reader :environment, :file_path
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@
|
12
|
-
@environment = environment
|
10
|
+
def initialize(options = {})
|
11
|
+
@file_path = options[:file_path]
|
12
|
+
@environment = options[:environment]
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
15
|
+
def name
|
16
|
+
"Rails #{environment} Config Handler"
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
19
|
+
def read
|
20
|
+
rails_params_to_pg(YAML.load_file(file_path)[environment])
|
21
|
+
end
|
22
|
+
|
23
|
+
def write(params)
|
24
|
+
db_yml = YAML.load_file(file_path)
|
21
25
|
db_yml[environment].merge!(pg_parameters_to_rails(params))
|
22
26
|
remove_empty(db_yml[environment])
|
23
27
|
|
24
|
-
new_name = "#{
|
25
|
-
FileUtils.copy(
|
28
|
+
new_name = "#{file_path}_#{Time.current.strftime("%d-%B-%Y_%H.%M.%S")}"
|
29
|
+
FileUtils.copy(file_path, new_name)
|
26
30
|
begin
|
27
|
-
File.write(
|
31
|
+
File.write(file_path, db_yml.to_yaml)
|
28
32
|
rescue
|
29
|
-
FileUtils.mv(new_name,
|
33
|
+
FileUtils.mv(new_name, file_path)
|
30
34
|
raise
|
31
35
|
end
|
32
36
|
new_name
|
@@ -40,7 +44,7 @@ module PostgresHaAdmin
|
|
40
44
|
pg_params[:user] = params['username']
|
41
45
|
pg_params[:port] = params['port']
|
42
46
|
pg_params[:host] = params['host']
|
43
|
-
pg_params[:password] =
|
47
|
+
pg_params[:password] = ManageIQ::Password.try_decrypt(params['password'])
|
44
48
|
remove_empty(pg_params)
|
45
49
|
end
|
46
50
|
|
@@ -1,52 +1,49 @@
|
|
1
1
|
require 'active_support/all'
|
2
2
|
require 'pg'
|
3
|
-
require 'linux_admin'
|
4
3
|
|
5
4
|
module ManageIQ
|
6
5
|
module PostgresHaAdmin
|
7
6
|
class FailoverMonitor
|
8
|
-
|
9
|
-
|
10
|
-
Pathname.new(File.expand_path(File.join(__dir__, "../..")))
|
11
|
-
].detect { |f| File.exist?(f) }
|
7
|
+
include Logging
|
8
|
+
|
12
9
|
FAILOVER_ATTEMPTS = 10
|
13
10
|
DB_CHECK_FREQUENCY = 300
|
14
11
|
FAILOVER_CHECK_FREQUENCY = 60
|
15
|
-
LOG_FILE = '/var/www/miq/vmdb/log/ha_admin.log'.freeze
|
16
12
|
attr_accessor :failover_attempts, :db_check_frequency, :failover_check_frequency
|
13
|
+
attr_reader :config_handlers
|
17
14
|
|
18
|
-
def initialize(
|
19
|
-
|
20
|
-
|
21
|
-
logger: nil,
|
22
|
-
environment: 'production')
|
23
|
-
if logger.respond_to?(:error, :info)
|
24
|
-
@logger = logger
|
25
|
-
else
|
26
|
-
@logger = Logger.new(LOG_FILE)
|
27
|
-
@logger.level = Logger::INFO
|
28
|
-
end
|
29
|
-
@database_yml = DatabaseYml.new(db_yml_file, environment)
|
30
|
-
@failover_db = FailoverDatabases.new(failover_yml_file, @logger)
|
31
|
-
initialize_settings(ha_admin_yml_file)
|
15
|
+
def initialize(config_path = "")
|
16
|
+
initialize_settings(config_path)
|
17
|
+
@config_handlers = []
|
32
18
|
end
|
33
19
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
@failover_db.update_failover_yml(connection)
|
38
|
-
connection.finish
|
39
|
-
return
|
40
|
-
end
|
41
|
-
|
42
|
-
@logger.error("Primary Database is not available. EVM server stop initiated. Starting to execute failover...")
|
43
|
-
stop_evmserverd
|
20
|
+
def add_handler(handler)
|
21
|
+
@config_handlers << [handler, ServerStore.new]
|
22
|
+
end
|
44
23
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
24
|
+
def monitor
|
25
|
+
config_handlers.each do |handler, server_store|
|
26
|
+
begin
|
27
|
+
connection = pg_connection(handler.read)
|
28
|
+
if connection
|
29
|
+
server_store.update_servers(connection)
|
30
|
+
connection.finish
|
31
|
+
next
|
32
|
+
end
|
33
|
+
|
34
|
+
logger.error("Primary Database is not available for #{handler.name}. Starting to execute failover...")
|
35
|
+
handler.do_before_failover
|
36
|
+
|
37
|
+
new_conn_info = execute_failover(handler, server_store)
|
38
|
+
if new_conn_info
|
39
|
+
handler.do_after_failover(new_conn_info)
|
40
|
+
else
|
41
|
+
logger.error("Failover failed")
|
42
|
+
end
|
43
|
+
rescue => e
|
44
|
+
logger.error("Received #{e.class} error while monitoring #{handler.name}: #{e.message}")
|
45
|
+
logger.error(e.backtrace)
|
46
|
+
end
|
50
47
|
end
|
51
48
|
end
|
52
49
|
|
@@ -55,59 +52,52 @@ module PostgresHaAdmin
|
|
55
52
|
begin
|
56
53
|
monitor
|
57
54
|
rescue => err
|
58
|
-
|
59
|
-
|
55
|
+
logger.error("#{err.class}: #{err}")
|
56
|
+
logger.error(err.backtrace.join("\n"))
|
60
57
|
end
|
61
58
|
sleep(db_check_frequency)
|
62
59
|
end
|
63
60
|
end
|
64
61
|
|
65
|
-
def active_servers_conninfo
|
66
|
-
servers =
|
67
|
-
|
68
|
-
servers.map! { |info|
|
69
|
-
end
|
70
|
-
|
71
|
-
def raise_failover_event
|
72
|
-
require "awesome_spawn"
|
73
|
-
AwesomeSpawn.run("rake evm:raise_server_event",
|
74
|
-
:chdir => RAILS_ROOT,
|
75
|
-
:params => ["--", {:event => "db_failover_executed"}])
|
62
|
+
def active_servers_conninfo(handler, server_store)
|
63
|
+
servers = server_store.connection_info_list
|
64
|
+
current_params = handler.read
|
65
|
+
servers.map! { |info| current_params.merge(info) }
|
76
66
|
end
|
77
67
|
|
78
68
|
private
|
79
69
|
|
80
70
|
def initialize_settings(ha_admin_yml_file)
|
71
|
+
ha_admin_yml = {}
|
81
72
|
begin
|
82
|
-
ha_admin_yml = YAML.load_file(ha_admin_yml_file)
|
73
|
+
ha_admin_yml = YAML.load_file(ha_admin_yml_file) if File.exist?(ha_admin_yml_file)
|
83
74
|
rescue SystemCallError, IOError => err
|
84
|
-
|
85
|
-
|
86
|
-
@logger.info("File not loaded: #{ha_admin_yml_file}. Default settings for failover will be used.")
|
75
|
+
logger.error("#{err.class}: #{err}")
|
76
|
+
logger.info("File not loaded: #{ha_admin_yml_file}. Default settings for failover will be used.")
|
87
77
|
end
|
88
78
|
@failover_attempts = ha_admin_yml['failover_attempts'] || FAILOVER_ATTEMPTS
|
89
79
|
@db_check_frequency = ha_admin_yml['db_check_frequency'] || DB_CHECK_FREQUENCY
|
90
80
|
@failover_check_frequency = ha_admin_yml['failover_check_frequency'] || FAILOVER_CHECK_FREQUENCY
|
91
|
-
|
81
|
+
logger.info("FAILOVER_ATTEMPTS=#{@failover_attempts} DB_CHECK_FREQUENCY=#{@db_check_frequency} FAILOVER_CHECK_FREQUENCY=#{@failover_check_frequency}")
|
92
82
|
end
|
93
83
|
|
94
|
-
def execute_failover
|
84
|
+
def execute_failover(handler, server_store)
|
95
85
|
failover_attempts.times do
|
96
|
-
with_each_standby_connection do |connection, params|
|
86
|
+
with_each_standby_connection(handler, server_store) do |connection, params|
|
97
87
|
next if database_in_recovery?(connection)
|
98
|
-
next unless
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
return
|
88
|
+
next unless server_store.host_is_primary?(params[:host], connection)
|
89
|
+
logger.info("Failing over to server using conninfo: #{params.reject { |k, _v| k == :password }}")
|
90
|
+
server_store.update_servers(connection)
|
91
|
+
handler.write(params)
|
92
|
+
return params
|
103
93
|
end
|
104
94
|
sleep(failover_check_frequency)
|
105
95
|
end
|
106
96
|
false
|
107
97
|
end
|
108
98
|
|
109
|
-
def with_each_standby_connection
|
110
|
-
active_servers_conninfo.each do |params|
|
99
|
+
def with_each_standby_connection(handler, server_store)
|
100
|
+
active_servers_conninfo(handler, server_store).each do |params|
|
111
101
|
connection = pg_connection(params)
|
112
102
|
next if connection.nil?
|
113
103
|
begin
|
@@ -121,19 +111,10 @@ module PostgresHaAdmin
|
|
121
111
|
def pg_connection(params)
|
122
112
|
PG::Connection.open(params)
|
123
113
|
rescue PG::Error => e
|
124
|
-
|
114
|
+
logger.error("Failed to establish PG connection: #{e.message}")
|
125
115
|
nil
|
126
116
|
end
|
127
117
|
|
128
|
-
def start_evmserverd
|
129
|
-
LinuxAdmin::Service.new("evmserverd").restart
|
130
|
-
@logger.info("Starting EVM server from failover monitor")
|
131
|
-
end
|
132
|
-
|
133
|
-
def stop_evmserverd
|
134
|
-
LinuxAdmin::Service.new("evmserverd").stop
|
135
|
-
end
|
136
|
-
|
137
118
|
# Checks if postgres database is in recovery mode
|
138
119
|
#
|
139
120
|
# @param pg_connection [PG::Connection] established pg connection
|
@@ -4,38 +4,38 @@ require 'pg/dsn_parser'
|
|
4
4
|
|
5
5
|
module ManageIQ
|
6
6
|
module PostgresHaAdmin
|
7
|
-
class
|
7
|
+
class ServerStore
|
8
|
+
include Logging
|
9
|
+
|
8
10
|
TABLE_NAME = "repmgr.nodes".freeze
|
9
11
|
|
10
|
-
attr_reader :
|
12
|
+
attr_reader :servers
|
11
13
|
|
12
|
-
def initialize
|
13
|
-
@
|
14
|
-
@logger = logger
|
14
|
+
def initialize
|
15
|
+
@servers = []
|
15
16
|
end
|
16
17
|
|
17
|
-
def
|
18
|
+
def connection_info_list
|
18
19
|
valid_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
|
19
|
-
|
20
|
+
servers.map! do |db_info|
|
20
21
|
db_info.keep_if { |k, _v| valid_keys.include?(k) }
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
File.write(yml_file, arr_yml.to_yaml) unless arr_yml.empty?
|
25
|
+
def update_servers(connection)
|
26
|
+
new_servers = query_repmgr(connection)
|
27
|
+
if servers_changed?(new_servers)
|
28
|
+
logger.info("Updating servers cache to #{new_servers}")
|
29
|
+
@servers = new_servers
|
30
|
+
end
|
31
31
|
rescue IOError => err
|
32
|
-
|
33
|
-
|
32
|
+
logger.error("#{err.class}: #{err}")
|
33
|
+
logger.error(err.backtrace.join("\n"))
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def host_is_primary?(host, connection)
|
37
37
|
query_repmgr(connection).each do |record|
|
38
|
-
if record[:host] == host &&
|
38
|
+
if record[:host] == host && record[:type] == 'primary'
|
39
39
|
return true
|
40
40
|
end
|
41
41
|
end
|
@@ -44,10 +44,14 @@ module PostgresHaAdmin
|
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
|
+
def servers_changed?(new_servers)
|
48
|
+
((servers - new_servers) + (new_servers - servers)).any?
|
49
|
+
end
|
50
|
+
|
47
51
|
def query_repmgr(connection)
|
48
52
|
return [] unless table_exists?(connection, TABLE_NAME)
|
49
53
|
result = []
|
50
|
-
db_result = connection.exec("SELECT type, conninfo, active FROM #{TABLE_NAME}")
|
54
|
+
db_result = connection.exec("SELECT type, conninfo, active FROM #{TABLE_NAME} WHERE active")
|
51
55
|
db_result.map_types!(PG::BasicTypeMapForResults.new(connection)).each do |record|
|
52
56
|
dsn = PG::DSNParser.parse(record.delete("conninfo"))
|
53
57
|
result << record.symbolize_keys.merge(dsn)
|
@@ -55,20 +59,11 @@ module PostgresHaAdmin
|
|
55
59
|
db_result.clear
|
56
60
|
result
|
57
61
|
rescue PG::Error => err
|
58
|
-
|
59
|
-
|
62
|
+
logger.error("#{err.class}: #{err}")
|
63
|
+
logger.error(err.backtrace.join("\n"))
|
60
64
|
result
|
61
65
|
end
|
62
66
|
|
63
|
-
def entry_is_active_master?(record)
|
64
|
-
record[:type] == 'primary' && record[:active]
|
65
|
-
end
|
66
|
-
|
67
|
-
def all_databases
|
68
|
-
return [] unless File.exist?(yml_file)
|
69
|
-
YAML.load_file(yml_file)
|
70
|
-
end
|
71
|
-
|
72
67
|
def table_exists?(connection, table_name)
|
73
68
|
result = connection.exec("SELECT to_regclass('#{table_name}')").first
|
74
69
|
!result['to_regclass'].nil?
|
@@ -20,10 +20,11 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.add_runtime_dependency "
|
24
|
-
spec.add_runtime_dependency "
|
23
|
+
spec.add_runtime_dependency "activesupport", ">=5.0", "< 6.1"
|
24
|
+
spec.add_runtime_dependency "awesome_spawn", "~> 1.4"
|
25
|
+
spec.add_runtime_dependency "manageiq-password", "~> 0.3"
|
25
26
|
spec.add_runtime_dependency "pg"
|
26
|
-
spec.add_runtime_dependency "pg-dsn_parser",
|
27
|
+
spec.add_runtime_dependency "pg-dsn_parser", "~> 0.1"
|
27
28
|
|
28
29
|
spec.add_development_dependency "bundler"
|
29
30
|
spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0"
|
metadata
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manageiq-postgres_ha_admin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ManageIQ Developers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '6.1'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '5.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '6.1'
|
13
33
|
- !ruby/object:Gem::Dependency
|
14
34
|
name: awesome_spawn
|
15
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -25,19 +45,19 @@ dependencies:
|
|
25
45
|
- !ruby/object:Gem::Version
|
26
46
|
version: '1.4'
|
27
47
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
48
|
+
name: manageiq-password
|
29
49
|
requirement: !ruby/object:Gem::Requirement
|
30
50
|
requirements:
|
31
51
|
- - "~>"
|
32
52
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
53
|
+
version: '0.3'
|
34
54
|
type: :runtime
|
35
55
|
prerelease: false
|
36
56
|
version_requirements: !ruby/object:Gem::Requirement
|
37
57
|
requirements:
|
38
58
|
- - "~>"
|
39
59
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
60
|
+
version: '0.3'
|
41
61
|
- !ruby/object:Gem::Dependency
|
42
62
|
name: pg
|
43
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -152,8 +172,7 @@ dependencies:
|
|
152
172
|
version: '0'
|
153
173
|
description: ManageIQ Postgres H.A. Admin
|
154
174
|
email:
|
155
|
-
executables:
|
156
|
-
- postgres_ha_admin
|
175
|
+
executables: []
|
157
176
|
extensions: []
|
158
177
|
extra_rdoc_files: []
|
159
178
|
files:
|
@@ -166,15 +185,20 @@ files:
|
|
166
185
|
- ".rubocop_local.yml"
|
167
186
|
- ".travis.yml"
|
168
187
|
- CHANGELOG.md
|
188
|
+
- CODEOWNERS
|
169
189
|
- Gemfile
|
170
190
|
- LICENSE.txt
|
171
191
|
- README.md
|
172
192
|
- Rakefile
|
173
|
-
- bin/postgres_ha_admin
|
174
193
|
- lib/manageiq-postgres_ha_admin.rb
|
175
|
-
- lib/manageiq/postgres_ha_admin/
|
176
|
-
- lib/manageiq/postgres_ha_admin/
|
194
|
+
- lib/manageiq/postgres_ha_admin/config_handler.rb
|
195
|
+
- lib/manageiq/postgres_ha_admin/config_handler/logical_replication_config_handler.rb
|
196
|
+
- lib/manageiq/postgres_ha_admin/config_handler/pglogical_config_handler.rb
|
197
|
+
- lib/manageiq/postgres_ha_admin/config_handler/rails_config_handler.rb
|
177
198
|
- lib/manageiq/postgres_ha_admin/failover_monitor.rb
|
199
|
+
- lib/manageiq/postgres_ha_admin/logging.rb
|
200
|
+
- lib/manageiq/postgres_ha_admin/null_logger.rb
|
201
|
+
- lib/manageiq/postgres_ha_admin/server_store.rb
|
178
202
|
- lib/manageiq/postgres_ha_admin/version.rb
|
179
203
|
- manageiq-postgres_ha_admin.gemspec
|
180
204
|
homepage: https://github.com/ManageIQ/manageiq-postgres_ha_admin
|
@@ -196,8 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
220
|
- !ruby/object:Gem::Version
|
197
221
|
version: '0'
|
198
222
|
requirements: []
|
199
|
-
|
200
|
-
rubygems_version: 2.6.14
|
223
|
+
rubygems_version: 3.0.6
|
201
224
|
signing_key:
|
202
225
|
specification_version: 4
|
203
226
|
summary: ManageIQ Postgres H.A. Admin
|