Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/datastore_mad/remotes/restic/restic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ def initialize(action, opts = {})
raise StandardError, 'Invalid value for RESTIC_PRUNE_MAX_UNUSED' \
unless @max_unused.nil? || @max_unused.match(/^\d+[kKmMgGtT%]?$|^unlimited$/)

# Max retries when waiting for an exclusive Restic lock (5 s between each retry).
@lock_retries = Integer(safe_get("#{prefix}TEMPLATE/RESTIC_LOCK_RETRIES", 720))

create_repo_if_not_exists if @options[:create_repo] && @repo_id
rescue StandardError => e
raise StandardError, "Wrong restic datastore configuration: #{e.message}"
Expand Down Expand Up @@ -176,12 +179,19 @@ def create_repo_if_not_exists
script = <<~EOS
set -e -o pipefail; shopt -qs failglob
#{resticenv_sh(RESTIC_BIN_PATHS[:frontend])}
#{restic('stats')} || #{restic('init')}
#{restic('stats')} || { ec=$?; if [ "$ec" -eq 11 ]; then exit 11; fi; #{restic('init')}; }
EOS

rc = LocalCommand.run '/bin/bash -s', nil, script
rc = nil
@lock_retries.times do
rc = LocalCommand.run '/bin/bash -s', nil, script
return if rc.code == 0
break unless rc.code == 11

raise StandardError, rc.stderr if rc.code != 0
sleep 5
end

raise StandardError, rc.stderr
end

# Gets (from Restic) full metadata of a specific snapshot.
Expand Down Expand Up @@ -268,7 +278,7 @@ def pull_snapshots(snaps, rhost = @sftp, wdir = nil)
# @return [nil]
def remove_snapshots(snaps, rhost = @sftp, opts = {})
options = {
:retries => 60,
:retries => @lock_retries,
:delay => 5 # seconds
}.merge!(opts)

Expand Down Expand Up @@ -339,7 +349,7 @@ def run_action(name, script, rhost = @sftp)
# @return [Object] RC struct
def run_with_lock_retry(name, script, rhost, opts = {})
options = {
:retries => 60,
:retries => @lock_retries,
:delay => 5
}.merge!(opts)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,19 @@ const RESTIC_SPARSIFY = {
grid: { xs: 12, md: 6 },
}

/** @type {Field} - Max retries when waiting for an exclusive Restic lock */
const RESTIC_LOCK_RETRIES = {
name: 'RESTIC_LOCK_RETRIES',
label: T.ResticLockRetries,
tooltip: T.ResticLockRetriesConcept,
dependOf: '$general.STORAGE_BACKEND',
type: INPUT_TYPES.TEXT,
htmlType: (type) =>
typeIsOneOf(type, [isRestic]) ? 'number' : INPUT_TYPES.HIDDEN,
validation: number(),
grid: { xs: 12, md: 6 },
}

export const RESTIC_FIELDS = [
RESTIC_PASSWORD,
RESTIC_SFTP_SERVER,
Expand All @@ -205,5 +218,6 @@ export const RESTIC_FIELDS = [
RESTIC_MAX_WIOPS,
RESTIC_CPU_QUOTA,
RESTIC_MAXPROC,
RESTIC_LOCK_RETRIES,
RESTIC_SPARSIFY,
]
3 changes: 3 additions & 0 deletions src/fireedge/src/modules/constants/translates.js
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,9 @@ module.exports = {
MaxNumberOSThreads: 'Max number of OS threads',
MaxNumberOSThreadsConcept:
'Sets GOMAXPROCS for restic to limit the OS threads that execute user-level Go code simultaneously.',
ResticLockRetries: 'Restic lock retries',
ResticLockRetriesConcept:
'Maximum number of retries (5 s apart) when waiting for an exclusive Restic repository lock to be released. Increase this for repositories where prune operations take a long time. Default: 720 (60 min).',
Sparsify: 'Sparsify',
SparsifyConcept:
'Runs virt-sparsify on flatten backups to reduce backup size. It requires libguestfs package.',
Expand Down