Class: RBarman::CliCommand

Inherits:
Object
  • Object
show all
Defined in:
lib/rbarman/cli_command.rb

Overview

Wrapper for the barman command line tool

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path_to_binary = nil, path_to_barman_home = nil) ⇒ CliCommand

Creates a new instance of CliCommand

Parameters:



28
29
30
31
# File 'lib/rbarman/cli_command.rb', line 28

def initialize(path_to_binary=nil, path_to_barman_home=nil)
  self.binary=path_to_binary || Configuration.instance.binary
  self.barman_home=path_to_barman_home || Configuration.instance.barman_home
end

Instance Attribute Details

#barman_homeString #barman_home=Object

Overloads:

  • #barman_homeString

    Returns base path where barman stores its backups.

    Returns:

    • (String)

      base path where barman stores its backups

  • #barman_home=Object

    Path to the base directory of barman’s backups

    Parameters:

    • path (String)

      path to the base directory

    Raises:

    • (ArgumentError)

      if path doesn’t exist



23
24
25
# File 'lib/rbarman/cli_command.rb', line 23

def barman_home
  @barman_home
end

#binaryString #binary=Object

Overloads:

  • #binaryString

    Returns path to the barman binary.

    Returns:

    • (String)

      path to the barman binary

  • #binary=Object

    Path to the barman binary

    Parameters:

    • path (String)

      path to the binary

    Raises:

    • (ArgumentError)

      if path doesn’t exist or path doesn’t end with ‘barman’



15
16
17
# File 'lib/rbarman/cli_command.rb', line 15

def binary
  @binary
end

Class Method Details

.size_in_bytes(size, unit) ⇒ Integer

Converts the size according to the unit to bytes

Examples:

CliCommand.size_in_bytes(2048, 'B') #=> 2048
CliCommand.size_in_bytes(2048, 'MiB') #=> 2048 * 1024 ** 2

Parameters:

  • size (Numeric)

    the size

  • unit (String)

    the unit, like ‘B`, `KiB`, `MiB`, `GiB` or `TiB`

Returns:

  • (Integer)

    the size in bytes

Raises:

  • (ArgumentError)

    if unit is not one of B|KiB|MiB|GiB|TiB



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/rbarman/cli_command.rb', line 275

def self.size_in_bytes(size, unit)
  raise(ArgumentError, "unit not one of B|KiB|MiB|GiB|TiB") if !unit.match(/(B|KiB|MiB|GiB|TiB)/)
  size_b = 0
  case unit
  when "B"
    size_b = size
  when "KiB"
    size_b = size * 1024
  when "MiB"
    size_b = size * 1024 ** 2
  when "GiB"
    size_b = size * 1024 ** 3
  when "TiB"
    size_b = size * 1024 ** 4
  end
  return size_b.to_i
end

Instance Method Details

#backup(server, backup_id, opts = {}) ⇒ Backup

Instructs barman to get information about a specific backup

Parameters:

  • server (String)

    server name

  • backup_id (String)

    id of the backup

  • opts (Hash) (defaults to: {})

    options for creating a Backup

Options Hash (opts):

  • :with_wal_files (Boolean)

    whether to include WalFiles in each Backup

Returns:

Raises:

  • (ArgumentError)

    if backup_id is nil



51
52
53
54
55
# File 'lib/rbarman/cli_command.rb', line 51

def backup(server, backup_id, opts = {})
  raise(ArgumentError, "backup id must not be nil!") if backup_id.nil?
  opts[:backup_id] = backup_id
  return backups(server, opts)[0]
end

#backups(server, opts = {}) ⇒ Backups

Instructs barman to get information about backups

Parameters:

  • server (String)

    server name

  • opts (Hash) (defaults to: {})

    options for creating Backups

Options Hash (opts):

  • :with_wal_files (Boolean)

    whether to include WalFiles in each Backup

  • :backup_id (String)

    retrieve just one Backup specified by this backup id

Returns:



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/rbarman/cli_command.rb', line 63

def backups(server, opts = {})
  list = run_barman_command("list-backup #{server}")
  list = list.grep(/#{opts[:backup_id]}/) if !opts[:backup_id].nil?

  backups = Backups.new(parse_backup_list(list))
  backups.each do |backup|
    parse_backup_info_file(backup)
    if opts[:with_wal_files]
      wals = wal_files(backup.server, backup.id)
      # using exact wal file size from xlog.db. show-backup is too inaccurate
      backup.wal_files = wals
      backup.wal_file_size = 0
      wals.each { |w| backup.wal_file_size += w.size }
    end
  end
  return backups
end

#create(server) ⇒ void

This method returns an undefined value.

Instructs barman to create a backup

Parameters:

  • server (String)

    server name



304
305
306
# File 'lib/rbarman/cli_command.rb', line 304

def create(server)
  run_barman_command("backup #{server}")
end

#create_recovery_cmd_args(opts = {}) ⇒ String

Creates an argument string for barman recovery command based on opts Hash

Parameters:

  • opts (Hash) (defaults to: {})

    options for creating the arguments

Options Hash (opts):

  • :remote_ssh_cmd (String)

    the ssh command to be used for remote recovery

  • :target_time (String, Time)

    the timestamp as recovery target

  • :target_xid (String)

    the transaction ID as recovery target

  • :exclusive (Boolean)

    whether to stop immediately before or immediately after the recovery target

Returns:

Since:

  • 0.0.3



335
336
337
338
339
340
341
342
# File 'lib/rbarman/cli_command.rb', line 335

def create_recovery_cmd_args(opts={})
  args = Array.new
  args << "--remote-ssh-command='#{opts[:remote_ssh_cmd]}'" if opts[:remote_ssh_cmd]
  args << "--target-time '#{opts[:target_time].to_s}'" if opts[:target_time]
  args << "--target-xid #{opts[:target_xid]}" if opts[:target_xid]
  args << "--exclusive" if opts[:exclusive]
  return args.join(" ")
end

#delete(server, backup_id) ⇒ void

This method returns an undefined value.

Instructs barman to delete a specific backup

Parameters:

  • server (String)

    server name

  • backup_id (String)

    id of the backup



297
298
299
# File 'lib/rbarman/cli_command.rb', line 297

def delete(server, backup_id)
  run_barman_command("delete #{server} #{backup_id}")
end

#parse_backup_info_file(backup) ⇒ void

This method returns an undefined value.

Assigns various values to a Backup by parsing the according “backup.info”

Parameters:

  • backup (Backup)

    the backup

Raises:

  • (ArgumentError)

    if backup is not of type Backup

  • (ArgumentError)

    if backup.id is not set

  • (ArgumentError)

    if backup.server is not set



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/rbarman/cli_command.rb', line 230

def parse_backup_info_file(backup)
  raise(ArgumentError, "arg not of type Backup") if !backup.is_a? Backup
  raise(ArgumentError, "Backup.id not set") if backup.id.nil?
  raise(ArgumentError, "Backup.server not set") if backup.server.nil?
  backup_info = file_content("#{barman_home}/#{backup.server}/base/#{backup.id}/backup.info")
  backup_info.each do |l|
    key, value = l.split("=")
    case key
    when "status"
      backup.status = value.downcase.to_sym
    end

    unless value == 'None'
      case key
      when "begin_time"
        backup.backup_start = value
      when "end_time"
        backup.backup_end = value
      when "size"
        backup.size = value.to_i
      when "timeline"
        backup.timeline = value.to_i
      when "begin_wal"
        backup.begin_wal = WalFile.parse(value)
      when "end_wal"
        backup.end_wal = WalFile.parse(value)
      when "pgdata"
        backup.pgdata = value
      when "version"
        backup.pg_version = value.to_i
      when "error"
        backup.error = value
      end
    end
  end
end

#parse_backup_list(lines) ⇒ Array<Backup>

Creates an array of Backup by parsing lines reported by barman

Parameters:

  • lines (Array<String>)

    an array of lines like ‘test 20130218T080002 - Mon Feb 18 18:11:16 2013 - Size: 213.0 GiB - WAL Size: 130.0 GiB’

Returns:



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/rbarman/cli_command.rb', line 203

def parse_backup_list(lines)
  result = Array.new
  lines.each do |l|
    match = l.match(/^(.+)\s(\d+T\d+)/)
    b = Backup.new
    b.server = match[1]
    b.id = match[2]

    status_match = l.match(/.+(FAILED|STARTED)/)
    status_match.nil? ? b.status = :done : b.status = status_match[1].downcase.to_sym

    if b.status == :done
      sizematch = l.match(/.+Size:\s(\S+)\s(\S+)\s-.+Size:\s(\S+)\s(\S+)/)
      b.size = CliCommand.size_in_bytes(sizematch[1].to_f, sizematch[2])
      b.wal_file_size = CliCommand.size_in_bytes(sizematch[3].to_f, sizematch[4])
    end
    result << b
  end
  return result
end

#parse_check_lines(server, lines) ⇒ Object

Parses lines reported by barman’s ‘check` and assigns according values

Parameters:

  • server (Server)

    the server

  • lines (Array<String>)

    an array of lines from output of barman’s ‘check` cmd

Raises:

  • (ArgumentError)

    if server is nil



176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/rbarman/cli_command.rb', line 176

def parse_check_lines(server, lines)
  raise(ArgumentError, 'arg server not of type Server') if !server.is_a? Server
  lines.each do |l|
    key, value = l.gsub("\t","").split(": ")
    case key.chomp
    when "ssh"
      server.ssh_check_ok = value =~ /OK/ ? true : false
    when "PostgreSQL"
      server.pg_conn_ok = value == "OK" ? true : false
    end
  end
end

#parse_list_server_lines(lines) ⇒ Array<String>

Parses lines reported by barman’s ‘list-server`

Parameters:

  • lines (Array<String>)

    an array of lines from output of barman’s ‘list-server` cmd

Returns:

  • (Array<String>)

    an array of server names



135
136
137
138
139
140
141
# File 'lib/rbarman/cli_command.rb', line 135

def parse_list_server_lines(lines)
  result = Array.new
  lines.each do |l|
    result << l.split("-")[0].strip
  end
  return result
end

#parse_show_server_lines(server, lines) ⇒ Server

Creates a Server object by parsing lines reported by barman’s ‘show-server`

Parameters:

  • server (String)

    name of the server

  • lines (Array<String>)

    an array of lines from output of barman’s ‘show-server` cmd

Returns:



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/rbarman/cli_command.rb', line 148

def parse_show_server_lines(server, lines)
  s = Server.new(server)
  lines.each do |l|
    key, value = l.gsub("\t","").split(": ")
    case key.chomp
    when "active"
      s.active = value.to_bool
    when "ssh_command"
      s.ssh_cmd = value
    when "conninfo"
      s.conn_info = value
    when "backup_directory"
      s.backup_dir = value
    when "basebackups_directory"
      s.base_backups_dir = value
    when "wals_directory"
      s.wals_dir = value
    when "server_txt_version"
      s.pg_version = value
    end
  end
  return s
end

#parse_wal_files_list(lines) ⇒ WalFiles

Creates a WalFiles object by parsing lines reported by barman

Parameters:

  • lines (Array<String>)

    an array of lines like ‘/var/lib/barman/test/wals/00000001000005A9/00000001000005A9000000BC’

Returns:



192
193
194
195
196
197
198
# File 'lib/rbarman/cli_command.rb', line 192

def parse_wal_files_list(lines)
  wal_files = Array.new
  lines.each do |line|
    wal_files << WalFile.parse(line.split("/").last)
  end
  return wal_files
end

#recover(server, backup_id, path, opts = {}) ⇒ void

Note:

when :remote_ssh_cmd is passed in options, ‘path’ is the path on the remote host, otherwise local

This method returns an undefined value.

Instructs barman to recover a backup

Examples:

clicommand.recover('test2', '20130218T080002', '/var/lib/postgresql/9.2/main', { :remote_ssh_cmd => 'ssh [email protected]' })

Parameters:

  • server (String)

    the server which includes the backup

  • backup_id (String)

    the id of the backup

  • path (String)

    the path to which the backup should be restored

  • opts (Hash) (defaults to: {})

    options passed as arguments to barman recover cmd

Options Hash (opts):

  • :remote_ssh_cmd (String)

    the ssh command to be used for remote recovery

  • :target_time (String, Time)

    the timestamp as recovery target

  • :target_xid (String)

    the transaction ID as recovery target

  • :exclusive (Boolean)

    whether to stop immediately before or after the recovery target

Since:

  • 0.0.3



322
323
324
325
# File 'lib/rbarman/cli_command.rb', line 322

def recover(server, backup_id, path, opts={})
  args = create_recovery_cmd_args(opts)
  run_barman_command("recover #{args} #{server} #{backup_id} #{path}")
end

#server(name, opts = {}) ⇒ Server

Instructs barman to get information about a server

Parameters:

  • name (String)

    name of the server

  • opts (Hash) (defaults to: {})

    options for creating Server

Options Hash (opts):

  • :with_backups (Boolean)

    whether to include Backups in Server

  • :with_wal_files (Boolean)

    whether to include WalFiles in each Backup

Returns:



87
88
89
90
91
92
93
94
# File 'lib/rbarman/cli_command.rb', line 87

def server(name, opts = {})
  lines = run_barman_command("show-server #{name}")
  server = parse_show_server_lines(name, lines)
  lines = run_barman_command("check #{name}", { :abort_on_error => false })
  parse_check_lines(server, lines)
  server.backups = backups(server.name, opts) if opts[:with_backups]
  return server
end

#servers(opts = {}) ⇒ Servers

Instructs barman to get information about all servers

Parameters:

  • opts (Hash) (defaults to: {})

    options for creating Servers

Options Hash (opts):

  • :with_backups (Boolean)

    whether to include Backups

  • :with_wal_files (Boolean)

    whether to include WalFiles

Returns:



101
102
103
104
105
106
107
108
109
# File 'lib/rbarman/cli_command.rb', line 101

def servers(opts = {})
  result = Servers.new
  lines = run_barman_command("list-server")
  server_names = parse_list_server_lines(lines)
  server_names.each do |name|
    result << server(name, opts)
  end
  return result
end

#wal_files(server, backup_id) ⇒ WalFiles

Instructs barman to list all wal files for a specific backup id

Parameters:

  • server (String)

    server name

  • backup_id (String)

    id of the backup

Returns:

Raises:

  • (RuntimeError)

    if wal file duplicates are found in xlog.db

  • (RuntimeError)

    if barman lists a wal file but no information could be found in xlog.db



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/rbarman/cli_command.rb', line 117

def wal_files(server, backup_id)
  lines = run_barman_command("list-files --target wal #{server} #{backup_id}")
  wal_files = parse_wal_files_list(lines)
  xlog_db = read_xlog_db(server)
  wal_files.each do |w|
    wal = "#{w.timeline}#{w.xlog}#{w.segment}"
    entry = xlog_db[wal]
    w.size = entry[:size]
    w.compression = entry[:compression]
    w.created = entry[:created].to_i
  end
  return wal_files
end