
There are some situations where we did not clean up CIB backup files correctly: 1) When a pcs show command was invoked 2) When we hit the maximum number of retries. 3) When the original file and the copy cib file are identical and we still called push_config() (very unlikely but we best clean that up) Let's remove these files in both of these cases. Closes-Bug: #1667145 Change-Id: I41404d569d81973c4b9531266c7a6c09904d1baf
123 lines
4.3 KiB
Ruby
123 lines
4.3 KiB
Ruby
require 'digest'
|
|
|
|
# backs up the current cib and returns the temporary file name where it
|
|
# was stored. Besides the temporary file it also makes an identical copy
|
|
# called temporary file + ".orig"
|
|
def backup_cib()
|
|
# We use the pacemaker CIB folder because of its restricted access permissions
|
|
cib = Dir::Tmpname.make_tmpname "/var/lib/pacemaker/cib/puppet-cib-backup", nil
|
|
cmd = "/usr/sbin/pcs cluster cib #{cib}"
|
|
output = `#{cmd}`
|
|
ret = $?
|
|
if not ret.success?
|
|
msg = "backup_cib: Running: #{cmd} failed with code: #{ret.exitstatus} -> #{output}"
|
|
FileUtils.rm(cib, :force => true)
|
|
raise Puppet::Error, msg
|
|
end
|
|
Puppet.debug("backup_cib: #{cmd} returned #{output}")
|
|
FileUtils.cp cib, "#{cib}.orig"
|
|
return cib
|
|
end
|
|
|
|
# Pushes the cib file back to the cluster and removes the cib files
|
|
# returns the pcs cluster cib-push return code. If the cib file and its
|
|
# original counterpart are the exact same push_cib() is a no-op.
|
|
# The pcs cluster-cib syntax with "diff-against" is used only if pcs supports
|
|
# it (it helps to minimize the chances that a cib-push might fail due
|
|
# to us trying to push a too old CIB)
|
|
def push_cib(cib)
|
|
cib_digest = Digest::SHA2.file(cib)
|
|
cib_orig_digest = Digest::SHA2.file("#{cib}.orig")
|
|
if cib_digest == cib_orig_digest
|
|
Puppet.debug("push_cib: #{cib} and #{cib}.orig were identical, skipping")
|
|
FileUtils.rm(cib, :force => true)
|
|
FileUtils.rm("#{cib}.orig", :force => true)
|
|
return 0
|
|
end
|
|
has_diffagainst = `/usr/sbin/pcs cluster cib-push --help`.include? 'diff-against'
|
|
cmd = "/usr/sbin/pcs cluster cib-push #{cib}"
|
|
if has_diffagainst
|
|
cmd += " diff-against=#{cib}.orig"
|
|
end
|
|
output = `#{cmd}`
|
|
ret = $?
|
|
FileUtils.rm(cib, :force => true)
|
|
FileUtils.rm("#{cib}.orig", :force => true)
|
|
if not ret.success?
|
|
msg = "push_cib: Running: #{cmd} failed with code: #{ret.exitstatus} -> #{output}"
|
|
Puppet.debug("push_cib failed: #{msg}")
|
|
end
|
|
|
|
Puppet.debug("push_cib: #{cmd} returned #{ret.exitstatus} -> #{output}")
|
|
return ret.exitstatus
|
|
end
|
|
|
|
def pcs(name, resource_name, cmd, tries=1, try_sleep=0,
|
|
verify_on_create=false, post_success_sleep=0)
|
|
if name.start_with?("create") && verify_on_create
|
|
return pcs_create_with_verify(name, resource_name, cmd, tries, try_sleep)
|
|
end
|
|
max_tries = name.include?('show') ? 1 : tries
|
|
max_tries.times do |try|
|
|
cib = backup_cib()
|
|
try_text = max_tries > 1 ? "try #{try+1}/#{max_tries}: " : ''
|
|
Puppet.debug("#{try_text}/usr/sbin/pcs -f #{cib} #{cmd}")
|
|
pcs_out = `/usr/sbin/pcs -f #{cib} #{cmd} 2>&1`
|
|
if name.include?('show')
|
|
FileUtils.rm(cib, :force => true)
|
|
FileUtils.rm("#{cib}.orig", :force => true)
|
|
# return output for good exit or false for failure.
|
|
return $?.exitstatus == 0 ? pcs_out : false
|
|
end
|
|
if $?.exitstatus == 0
|
|
# If push_cib failed, we stay in the loop and keep trying
|
|
if push_cib(cib) == 0
|
|
sleep post_success_sleep
|
|
return pcs_out
|
|
end
|
|
end
|
|
Puppet.debug("Error: #{pcs_out}")
|
|
if try == max_tries-1
|
|
FileUtils.rm(cib, :force => true)
|
|
FileUtils.rm("#{cib}.orig", :force => true)
|
|
pcs_out_line = pcs_out.lines.first ? pcs_out.lines.first.chomp! : ''
|
|
raise Puppet::Error, "pcs -f #{cib} #{name} failed: #{pcs_out_line}"
|
|
end
|
|
if try_sleep > 0
|
|
Puppet.debug("Sleeping for #{try_sleep} seconds between tries")
|
|
sleep try_sleep
|
|
end
|
|
end
|
|
end
|
|
|
|
def pcs_create_with_verify(name, resource_name, cmd, tries=1, try_sleep=0)
|
|
max_tries = tries
|
|
max_tries.times do |try|
|
|
try_text = max_tries > 1 ? "try #{try+1}/#{max_tries}: " : ''
|
|
Puppet.debug("#{try_text}/usr/sbin/pcs #{cmd}")
|
|
pcs_out = `/usr/sbin/pcs #{cmd} 2>&1`
|
|
if $?.exitstatus == 0
|
|
sleep try_sleep
|
|
cmd_show = "/usr/sbin/pcs resource show " + resource_name
|
|
Puppet.debug("Verifying with: "+cmd_show)
|
|
`#{cmd_show}`
|
|
if $?.exitstatus == 0
|
|
return pcs_out
|
|
else
|
|
Puppet.debug("Warning: verification of pcs resource creation failed")
|
|
end
|
|
else
|
|
Puppet.debug("Error: #{pcs_out}")
|
|
sleep try_sleep
|
|
end
|
|
if try == max_tries-1
|
|
pcs_out_line = pcs_out.lines.first ? pcs_out.lines.first.chomp! : ''
|
|
raise Puppet::Error, "pcs #{name} failed: #{pcs_out_line}"
|
|
end
|
|
end
|
|
end
|
|
|
|
def not_empty_string(p)
|
|
p && p.kind_of?(String) && ! p.empty?
|
|
end
|