Module: ForemanMaintain::Concerns::BaseDatabase

Defined in:
lib/foreman_maintain/concerns/base_database.rb

Instance Method Summary collapse

Instance Method Details

#backup_db_command(file_path, config = configuration) ⇒ Object

TODO: refactor to use dump_db



104
105
106
107
# File 'lib/foreman_maintain/concerns/base_database.rb', line 104

def backup_db_command(file_path, config = configuration)
  pg_dump_cmd = "pg_dump -Fc #{config['database']}"
  "runuser - postgres -c '#{pg_dump_cmd}' | bzip2 -9 > #{file_path}"
end

#backup_dirObject

TODO: remove the backup file path tools from here. Lib Utils::Backup?



110
111
112
# File 'lib/foreman_maintain/concerns/base_database.rb', line 110

def backup_dir
  @backup_dir ||= File.expand_path(ForemanMaintain.config.db_backup_dir)
end

#backup_file_path(config = configuration) ⇒ Object



61
62
63
64
# File 'lib/foreman_maintain/concerns/base_database.rb', line 61

def backup_file_path(config = configuration)
  dump_file_name = "#{config['database']}_#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}.dump"
  "#{backup_dir}/#{dump_file_name}.bz2"
end

#backup_global_objects(file) ⇒ Object



114
115
116
# File 'lib/foreman_maintain/concerns/base_database.rb', line 114

def backup_global_objects(file)
  execute!("runuser - postgres -c 'pg_dumpall -g > #{file}'")
end

#backup_local(backup_file, extra_tar_options = {}) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/foreman_maintain/concerns/base_database.rb', line 90

def backup_local(backup_file, extra_tar_options = {})
  dir = extra_tar_options.fetch(:data_dir, data_dir)
  FileUtils.cd(dir) do
    tar_options = {
      :archive => backup_file,
      :command => 'create',
      :transform => "s,^,#{data_dir[1..-1]},S",
      :files => '*'
    }.merge(extra_tar_options)
    feature(:tar).run(tar_options)
  end
end

#config_filesObject



27
28
29
30
31
# File 'lib/foreman_maintain/concerns/base_database.rb', line 27

def config_files
  [
    '/etc/systemd/system/postgresql.service'
  ]
end

#configurationObject

Raises:

  • (NotImplementedError)


23
24
25
# File 'lib/foreman_maintain/concerns/base_database.rb', line 23

def configuration
  raise NotImplementedError
end

#data_dirObject



4
5
6
7
8
9
10
# File 'lib/foreman_maintain/concerns/base_database.rb', line 4

def data_dir
  if el7? && package_manager.installed?('rh-postgresql12-postgresql-server-syspaths')
    '/var/opt/rh/rh-postgresql12/lib/pgsql/data/'
  else
    '/var/lib/pgsql/data/'
  end
end

#db_version(config = configuration) ⇒ Object



165
166
167
168
169
170
171
172
173
174
# File 'lib/foreman_maintain/concerns/base_database.rb', line 165

def db_version(config = configuration)
  if ping(config)
    # Note - t removes headers, -A removes alignment whitespace
    server_version_cmd = psql_command(config) + ' -c "SHOW server_version" -t -A'
    version_string = execute!(server_version_cmd, :hidden_patterns => [config['password']])
    version(version_string)
  else
    raise_service_error
  end
end

#delete_records_by_ids(tbl_name, rec_ids) ⇒ Object



137
138
139
140
141
142
143
144
145
146
# File 'lib/foreman_maintain/concerns/base_database.rb', line 137

def delete_records_by_ids(tbl_name, rec_ids)
  quotize_rec_ids = rec_ids.map { |el| "'#{el}'" }.join(',')
  unless quotize_rec_ids.empty?
    psql(<<-SQL)
      BEGIN;
       DELETE FROM #{tbl_name} WHERE id IN (#{quotize_rec_ids});
      COMMIT;
    SQL
  end
end

#dropdb(config = configuration) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/foreman_maintain/concerns/base_database.rb', line 152

def dropdb(config = configuration)
  if local?
    execute!("runuser - postgres -c 'dropdb #{config['database']}'")
  else
    delete_statement = psql(<<-SQL)
      select string_agg('drop table if exists \"' || tablename || '\" cascade;', '')
      from pg_tables
      where schemaname = 'public';
    SQL
    psql(delete_statement)
  end
end

#dump_db(file, config = configuration) ⇒ Object



66
67
68
# File 'lib/foreman_maintain/concerns/base_database.rb', line 66

def dump_db(file, config = configuration)
  execute!(dump_command(config) + " > #{file}", :hidden_patterns => [config['password']])
end

#find_base_directory(directory) ⇒ Object



148
149
150
# File 'lib/foreman_maintain/concerns/base_database.rb', line 148

def find_base_directory(directory)
  find_dir_containing_file(directory, 'postgresql.conf')
end

#local?(config = configuration) ⇒ Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/foreman_maintain/concerns/base_database.rb', line 33

def local?(config = configuration)
  ['localhost', '127.0.0.1', `hostname`.strip].include? config['host']
end

#perform_backup(config = configuration) ⇒ Object



118
119
120
121
122
123
124
# File 'lib/foreman_maintain/concerns/base_database.rb', line 118

def perform_backup(config = configuration)
  file_path = backup_file_path(config)
  backup_cmd = backup_db_command(file_path, config)
  execute!(backup_cmd, :hidden_patterns => [config['password']])
  puts "\n Note: Database backup file path - #{file_path}"
  puts "\n In case of any exception, use above dump file to restore DB."
end

#ping(config = configuration) ⇒ Object



55
56
57
58
59
# File 'lib/foreman_maintain/concerns/base_database.rb', line 55

def ping(config = configuration)
  execute?(psql_command(config),
           :stdin => 'SELECT 1 as ping',
           :hidden_patterns => [config['password']])
end

#postgresql_confObject



12
13
14
# File 'lib/foreman_maintain/concerns/base_database.rb', line 12

def postgresql_conf
  "#{data_dir}/postgresql.conf"
end

#psql(query, config = configuration) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/foreman_maintain/concerns/base_database.rb', line 45

def psql(query, config = configuration)
  if ping(config)
    execute(psql_command(config),
            :stdin => query,
            :hidden_patterns => [config['password']])
  else
    raise_service_error
  end
end

#psql_cmd_available?Boolean

Returns:

  • (Boolean)


176
177
178
179
# File 'lib/foreman_maintain/concerns/base_database.rb', line 176

def psql_cmd_available?
  exit_status, _output = execute_with_status('which psql')
  exit_status == 0
end

#query(sql, config = configuration) ⇒ Object



37
38
39
# File 'lib/foreman_maintain/concerns/base_database.rb', line 37

def query(sql, config = configuration)
  parse_csv(query_csv(sql, config))
end

#query_csv(sql, config = configuration) ⇒ Object



41
42
43
# File 'lib/foreman_maintain/concerns/base_database.rb', line 41

def query_csv(sql, config = configuration)
  psql(%{COPY (#{sql}) TO STDOUT WITH CSV HEADER}, config)
end

#raise_psql_missing_errorObject

Raises:



181
182
183
184
# File 'lib/foreman_maintain/concerns/base_database.rb', line 181

def raise_psql_missing_error
  raise Error::Fail, 'The psql command not found.'\
          ' Make sure system has psql utility installed.'
end

#restore_dump(file, localdb, config = configuration) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/foreman_maintain/concerns/base_database.rb', line 70

def restore_dump(file, localdb, config = configuration)
  if localdb
    dump_cmd = "runuser - postgres -c 'pg_restore -C -d postgres #{file}'"
    execute!(dump_cmd)
  else
    # TODO: figure out how to completely ignore errors. Currently this
    # sometimes exits with 1 even though errors are ignored by pg_restore
    dump_cmd = base_command(config, 'pg_restore') +
               ' --no-privileges --clean --disable-triggers -n public ' \
               "-d #{config['database']} #{file}"
    execute!(dump_cmd, :hidden_patterns => [config['password']],
                       :valid_exit_statuses => [0, 1])
  end
end

#restore_pg_globals(pg_globals, config = configuration) ⇒ Object



85
86
87
88
# File 'lib/foreman_maintain/concerns/base_database.rb', line 85

def restore_pg_globals(pg_globals, config = configuration)
  execute!(base_command(config, 'psql') + " -f #{pg_globals} postgres 2>/dev/null",
           :hidden_patterns => [config['password']])
end

#restore_transformObject



16
17
18
19
20
21
# File 'lib/foreman_maintain/concerns/base_database.rb', line 16

def restore_transform
  if el8?
    # this allows to transform an EL7 backup to EL8 paths
    's,^var/opt/rh/rh-postgresql12/,var/,S'
  end
end

#table_exist?(table_name) ⇒ Boolean

Returns:

  • (Boolean)


126
127
128
129
130
131
132
133
134
135
# File 'lib/foreman_maintain/concerns/base_database.rb', line 126

def table_exist?(table_name)
  sql = <<-SQL
    SELECT EXISTS ( SELECT *
    FROM information_schema.tables WHERE table_name =  '#{table_name}' )
  SQL
  result = query(sql)
  return false if result.nil? || (result && result.empty?)

  result.first['exists'].eql?('t')
end